|
|
/*
* IDD_RUN.C - run (startup) and shutdown idd object */
#include <ndis.h>
#include <mytypes.h>
#include <mydefs.h>
#include <disp.h>
#include <util.h>
#include <idd.h>
#include <res.h>
/* a port descriptor */ typedef struct { char *name; /* port name */ INT must; /* mast map this port? */ } PORT;
/* port tables */ static PORT api_rx_port_tbl[] = { { "b1_rx ", 1 }, { "b2_rx ", 1 }, { "uart_rx ", 0 }, { "tdat ", 1 }, { "Cm.0 ", 1 }, { "Cm.1 ", 0 }, { NULL } }; static PORT api_tx_port_tbl[] = { { "b1_tx ", 1 }, { "b2_tx ", 1 }, { "uart_tx ", 0 }, { "cmd ", 1 }, { "Q931.0 ", 1 }, { "Q931.1 ", 0 }, { NULL } };
/* partition queue table */
static INT api_tx_partq_tbl[] = { 0, 1, 2, 3, 3, 3 };
/* local prototypes */ INT api_setup(IDD* idd); INT api_map_ports(IDD* idd); INT api_bind_ports(IDD* idd); INT api_setup_partq(IDD* idd); INT api_alloc_partq(IDD* idd);
#pragma NDIS_INIT_FUNCTION(idd_startup)
/* startup (run) an idd object */ INT idd_startup(VOID *idd_1) { IDD *idd = (IDD*)idd_1; INT ret; D_LOG(D_ENTRY, ("idd_startup: entry, idd: 0x%p", idd));
/* lock idd */ NdisAcquireSpinLock(&idd->lock);
/* mark starting */ idd->state = IDD_S_STARTUP;
if (idd->btype != IDD_BT_DATAFIREU) while(!GetResourceSem (idd->res_mem));
/* do the startup */ if ( (ret = idd->LoadCode(idd)) != IDD_E_SUCC ) { /* release idd */ FreeResourceSem (idd->res_mem); NdisReleaseSpinLock(&idd->lock); D_LOG(D_EXIT, ("idd_startup: error exit, ret=0x%x", ret)); return(ret); }
/* initialize api level - talks to memory! */ ret = api_setup(idd);
/* change state */ idd->state = IDD_S_RUN;
if (idd->btype != IDD_BT_DATAFIREU) FreeResourceSem (idd->res_mem);
/* release idd */ NdisReleaseSpinLock(&idd->lock);
/* return result */ D_LOG(D_EXIT, ("idd_startup: exit, ret=0x%x", ret)); return(ret); }
/* shutdown an idd object, not implemented yet */ INT idd_shutdown(VOID *idd_1) { IDD *idd = (IDD*)idd_1; D_LOG(D_ENTRY, ("idd_shutdown: idd: 0x%p", idd));
idd->state = IDD_S_SHUTDOWN;
idd->ResetAdapter(idd);
return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(IdpLoadCode)
/* load idp code in & run it */ INT IdpLoadCode(IDD *idd) { ULONG CurrentTime = 0, TimeOut = 0; USHORT bank, page, n, NumberOfBanks; UCHAR *fbin_data; NDIS_STATUS stat; UCHAR status = IDP_S_PEND; NDIS_PHYSICAL_ADDRESS pa = NDIS_PHYSICAL_ADDRESS_CONST(0xffffffff, 0xffffffff); D_LOG(D_ENTRY, ("load_code: entry, idd=0x%p", idd));
/* setup pointers into shared memory */ idd->IdpStat = (USHORT*)(idd->vhw.vmem + IDP_STS_WINDOW); idd->IdpCmd = (IDP_CMD*)(idd->vhw.vmem + IDP_CMD_WINDOW); idd->IdpEnv = (UCHAR*)(idd->vhw.vmem + IDP_ENV_WINDOW);
/* setup base memory address registers */ idd->SetBasemem(idd, idd->phw.base_mem);
/* while in reset, clear all idp banks/pages */ for ( bank = 0 ; bank < 3 ; bank++ ) { /* setup bank */ idd->SetBank(idd, (UCHAR)bank, 0);
/* loop on pages */ for ( page = 0 ; page < 4 ; page++ ) { /* setup page */ idd->ChangePage (idd, (UCHAR)page);
/* zero out (has to be a word fill!) */ IdpMemset((UCHAR*)idd->vhw.vmem, 0, 0x4000); } } //free page
idd->ChangePage (idd, (UCHAR)IDD_PAGE_NONE);
/* set idp to code bank, keep in reset */ idd->SetBank(idd, IDD_BANK_CODE, 0);
/* map file data in */ NdisMapFile(&stat, (PVOID*)&fbin_data, idd->phw.fbin);
if ( stat != NDIS_STATUS_SUCCESS ) { D_LOG(D_ALWAYS, ("load_code: file mapping failed!, stat: 0x%x", stat)); return(IDD_E_FMAPERR); }
// code to check for filelength greater than 64K
if (idd->phw.fbin_len > 0x10000) NumberOfBanks = 2; else NumberOfBanks = 1;
for (n = 0; n < NumberOfBanks; n++) { /* copy data in (must be a word operation) */ for ( page = 0 ; page < 4 ; page++ ) { idd->ChangePage(idd, (UCHAR)page);
IdpMemcpy((UCHAR*)idd->vhw.vmem, (UCHAR*)(fbin_data + (page * 0x4000) + (n * 0x10000)), 0x4000);
// DbgPrint ("Load: Src: 0x%p, Dst: 0x%p, Page: %d\n",
// (fbin_data + (page*0x4000) + (n * 0x10000)), idd->vhw.vmem, page);
} /* set idp to data bank, keep in reset */ idd->SetBank(idd, IDD_BANK_DATA, 0); }
/* map file data out */ NdisUnmapFile(idd->phw.fbin);
/* switch back to buffer bank */ idd->ChangePage(idd, 0); idd->SetBank(idd, IDD_BANK_BUF, 0);
/* add 'no_uart' definition */ NdisMoveMemory(idd->DefinitionTable + idd->DefinitionTableLength, "no_uart\0any\0", 12);
idd->DefinitionTableLength += 12;
/* load initial environment */ NdisMoveToMappedMemory((PVOID)idd->IdpEnv, (PVOID)idd->DefinitionTable, idd->DefinitionTableLength);
/* install startup byte signal */ NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->status, (PVOID)&status, sizeof(UCHAR));
/* start idp running, wait for 1 second to complete */ idd->SetBank(idd, IDD_BANK_BUF, 1);
while ( !TimeOut ) { NdisMoveFromMappedMemory((PVOID)&status, (PVOID)&idd->IdpCmd->status, sizeof(UCHAR));
if ( !status ) break;
//
// stall for a 1 millisecond
//
NdisStallExecution(1000L);
//
// add 1 millisecond to timeout counter
//
CurrentTime += 1;
//
// if timeout counter is greater the 2 seconds we have a problem
//
if ( CurrentTime > 2000) TimeOut = 1; }
if (TimeOut) { D_LOG(D_ALWAYS, ("load_code: idp didn't start!"));
idd->state = IDD_S_SHUTDOWN;
/* unset page, free memory window */ idd->ChangePage(idd, IDD_PAGE_NONE);
return(IDD_E_RUNERR); }
/* unset page, free memory window */ idd->ChangePage(idd, IDD_PAGE_NONE);
/* if here, idp runs now! */ D_LOG(D_EXIT, ("load_code: exit, idp running")); return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(AdpLoadCode)
/* load idp code in & run it */ INT AdpLoadCode(IDD *idd) { UCHAR *Zero; UCHAR *fbin_data, status; NDIS_STATUS stat; ADP_BIN_HEADER *Header; ADP_BIN_BLOCK *Block, *FirstBlock; ULONG CurrentTime = 0, TimeOut = 0; USHORT BlockCount = 0; ULONG n;
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
D_LOG(D_ENTRY, ("AdpLoadCode: entry, idd: 0x%p", idd));
//
// reset the adapter
//
AdpWriteControlBit(idd, ADP_RESET_BIT, 1);
//
// clear adapter memory
//
D_LOG(D_ENTRY, ("AdpLoadCode: Clear Memory"));
NdisAllocateMemory((PVOID*)&Zero, 0xFFFF, 0, HighestAcceptableMax);
NdisZeroMemory(Zero, 1024);
for (n = 0; n < ADP_RAM_SIZE; n += 0xFFFF) AdpPutBuffer(idd, n, Zero, (USHORT)0xFFFF);
NdisFreeMemory(Zero, 0xFFFF, 0);
//
// map file data into memory
//
NdisMapFile(&stat, (PVOID*)&fbin_data, idd->phw.fbin);
if ( stat != NDIS_STATUS_SUCCESS ) { D_LOG(D_ALWAYS, ("AdpLoadCode: file mapping failed!, stat: 0x%x", stat)); return(IDD_E_FMAPERR); }
//
// Get bin file header
//
(UCHAR*)Header = fbin_data;
if (Header->Format != ADP_BIN_FORMAT) return(IDD_E_FMAPERR);
//
// Check file size
//
if (Header->ImageSize > ADP_RAM_SIZE) return(IDD_E_FMAPERR);
BlockCount = Header->BlockCount; (UCHAR*)FirstBlock = fbin_data + sizeof(ADP_BIN_HEADER);
for (n = 0; n < BlockCount; n++) { Block = FirstBlock + n;
AdpPutBuffer(idd, Block->Address, Block->Data, ADP_BIN_BLOCK_SIZE); }
//
// unmap file data
//
NdisUnmapFile(idd->phw.fbin);
//
// add initial enviornment
//
/* add 'no_uart' definition */ NdisMoveMemory(idd->DefinitionTable + idd->DefinitionTableLength, "no_uart\0any\0", 12); idd->DefinitionTableLength += 12;
D_LOG(D_ENTRY, ("AdpLoadCode: Add Enviornment"));
AdpPutBuffer(idd, ADP_ENV_WINDOW, idd->DefinitionTable, idd->DefinitionTableLength);
//
// write startup byte
//
AdpWriteCommandStatus(idd, ADP_S_PEND);
//
// release processor from reset
//
AdpWriteControlBit(idd, ADP_RESET_BIT, 0);
while ( !TimeOut ) { status = AdpReadCommandStatus(idd);
if ( !status ) break;
//
// stall for a 1 millisecond
//
NdisStallExecution(1000L);
//
// add 1 millisecond to timeout counter
//
CurrentTime += 1;
//
// if timeout counter is greater the 2 seconds we have a problem
//
if ( CurrentTime > 2000) TimeOut = 1; }
if (TimeOut) { D_LOG(D_ALWAYS, ("AdpLodeCode: Adp didn't start!")); return(IDD_E_RUNERR); }
/* if here, Adp runs now! */ D_LOG(D_EXIT, ("AdpLoadCode: exit, Adp running"));
return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(api_setup)
/* setup idp api related fields */ INT api_setup(IDD *idd) { INT ret;
D_LOG(D_ENTRY, ("api_setup: entry, idd: 0x%p", idd));
/* map port names */ if ( (ret = api_map_ports(idd)) != IDD_E_SUCC ) return(ret); /* bind ports to status bits */ if ( (ret = api_bind_ports(idd)) != IDD_E_SUCC ) return(ret); /* setup partition queues */ if ( (ret = api_setup_partq(idd)) != IDD_E_SUCC ) return(ret);
/* allocate initial buffers off partition queues */ if ( (ret = api_alloc_partq(idd)) != IDD_E_SUCC ) return(ret); D_LOG(D_EXIT, ("api_setup: exit, success"));
return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(api_map_ports)
/* map port names to ids */ INT api_map_ports(IDD *idd) { INT n;
D_LOG(D_ENTRY, ("api_map_ports: entry, idd: 0x%p", idd));
/* map rx ports */ for ( n = 0 ; api_rx_port_tbl[n].name ; n++ ) { idd->rx_port[n] = idd->ApiGetPort(idd, api_rx_port_tbl[n].name);
D_LOG(D_ALWAYS, ("api_map_ports: RxPorts: PortName: %s, PortId: 0x%x", api_rx_port_tbl[n].name, idd->rx_port[n])); if ( !idd->rx_port[n] && api_rx_port_tbl[n].must ) { D_LOG(D_ALWAYS, ("api_map_ports: failed to map rx port [%s]", \ api_rx_port_tbl[n].name)); return(IDD_E_PORTMAPERR); } } /* map tx ports */ for ( n = 0 ; api_tx_port_tbl[n].name ; n++ ) { idd->tx_port[n] = idd->ApiGetPort(idd, api_tx_port_tbl[n].name);
D_LOG(D_ALWAYS, ("api_map_ports: TxPorts: PortName: %s, PortId: 0x%x", api_tx_port_tbl[n].name, idd->tx_port[n])); if ( !idd->tx_port[n] && api_tx_port_tbl[n].must ) { D_LOG(D_ALWAYS, ("api_map_ports: failed to map tx port [%s]", \ api_tx_port_tbl[n].name)); return(IDD_E_PORTMAPERR); } } return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(api_bind_ports)
/* bind ports to status bits */ INT api_bind_ports(IDD *idd) { INT n; D_LOG(D_ENTRY, ("api_bind_ports: entry, idd: 0x%p", idd));
/* bind rx ports */ for ( n = 0 ; api_rx_port_tbl[n].name; n++ ) { if (idd->rx_port[n]) if ( idd->ApiBindPort(idd, idd->rx_port[n], (USHORT)(1 << n)) < 0 ) { D_LOG(D_ALWAYS, ("api_bind_ports: failed to bind status bit on port [%s]", \ api_rx_port_tbl[n].name)); return(IDD_E_PORTBINDERR); } }
return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(api_setup_partq)
/* setup partition queues */ INT api_setup_partq(IDD *idd) { INT n;
D_LOG(D_ENTRY, ("api_setup_partq: entry, idd: 0x%p", idd));
/* simply copy table */ for ( n = 0 ; n < IDD_TX_PORTS ; n++ ) idd->tx_partq[n] = api_tx_partq_tbl[n];
return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(api_alloc_partq)
/* allocate initial buffers off partition queues */ INT api_alloc_partq(IDD *idd) { INT n, part;
D_LOG(D_ENTRY, ("api_alloc_partq: entry, idd: 0x%p", idd)); /* scan using partq_tbl as a refrence. allocate only once per partq */ for ( n = 0 ; n < IDD_TX_PORTS ; n++ ) if ( !idd->tx_buf[part = api_tx_partq_tbl[n]] ) { if ( !(idd->tx_buf[part] = idd->ApiAllocBuffer(idd, part)) ) { D_LOG(D_ALWAYS, ("api_alloc_partq: failed to alloc initial buffer, part: %d", part)); DbgPrint("api_alloc_partq: failed to alloc initial buffer, part: %d\n", part); return(IDD_E_PARTQINIT); } #if DBG
ASSERT(!idd->BufferStuff[part].Buffer[0]); idd->BufferStuff[part].Buffer[0] = idd->tx_buf[part]; idd->BufferStuff[part].Count++; idd->BufferStuff[part].Put++; idd->BufferStuff[part].Get = 0; ASSERT(idd->BufferStuff[part].Count < 32); #endif
}
return(IDD_E_SUCC); }
#pragma NDIS_INIT_FUNCTION(IdpGetPort)
/* get port id from a name */ USHORT IdpGetPort(IDD *idd, CHAR name[8]) { UCHAR status; USHORT port_id;
D_LOG(D_ENTRY, ("IdpGetPort: entry, idd: 0x%p, name: [%s]", idd, name));
idd->ChangePage(idd, 0);
/* install target name & execute a map */ NdisMoveToMappedMemory ((CHAR *)idd->IdpCmd->port_name, (CHAR *)name, 8);
status = idd->Execute(idd, IDP_L_MAP);
NdisMoveFromMappedMemory((PVOID)&port_id, (PVOID)&idd->IdpCmd->port_id, sizeof(USHORT));
idd->ChangePage(idd, IDD_PAGE_NONE);
D_LOG(D_EXIT, ("IdpGetPort: exit, port_id: 0x%x", port_id));
return( (status == IDP_S_OK) ? port_id : 0); }
#pragma NDIS_INIT_FUNCTION(AdpGetPort)
/* get port id from a name */ USHORT AdpGetPort(IDD *idd, CHAR name[8]) { UCHAR status; D_LOG(D_ENTRY, ("AdpGetPort: entry, idd: 0x%p, name: [%s]", idd, name));
//
// clear command structure
//
NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD));
//
// put port name in command structure
//
NdisMoveMemory((PVOID)&idd->AdpCmd.port_name, name, 8);
//
// execute command
//
status = idd->Execute(idd, ADP_L_MAP);
//
// check return status
//
if (status != ADP_S_OK) return(0);
D_LOG(D_ALWAYS, ("AdpGetPort: PortId: 0x%x", idd->AdpCmd.port_id)); //
// return port
//
return(idd->AdpCmd.port_id); }
#pragma NDIS_INIT_FUNCTION(IdpBindPort)
/* bind a port to a status bit */ INT IdpBindPort(IDD *idd, USHORT port, USHORT bitpatt) { UCHAR status;
D_LOG(D_ENTRY, ("IdpBindPort: entry, idd: 0x%p, port: 0x%x, bitpatt: 0x%x", idd, port, bitpatt));
idd->ChangePage(idd, 0);
/* fillup cmd & execute a bind */ NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_id, (PVOID)&port, sizeof(USHORT)); NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_bitpatt, (PVOID)&bitpatt, sizeof(USHORT));
status = idd->Execute(idd, IDP_L_BIND);
idd->ChangePage(idd, IDD_PAGE_NONE);
return( (status == IDP_S_OK) ? 0 : -1 ); }
#pragma NDIS_INIT_FUNCTION(AdpBindPort)
/* bind a port to a status bit */ INT AdpBindPort(IDD *idd, USHORT port, USHORT bitpatt) { UCHAR status;
D_LOG(D_ENTRY, ("AdpBindPort: entry, idd: 0x%p, port: 0x%x, bitpatt: 0x%x", idd, port, bitpatt)); //
// clear command structure
//
NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD));
//
// fill port id and status bit
//
idd->AdpCmd.port_id = port; idd->AdpCmd.port_bitpatt = bitpatt;
//
// execute command
//
status = idd->Execute(idd, ADP_L_BIND);
D_LOG(D_ALWAYS, ("AdpBindPort: ExecuteStatus: 0x%x", status));
if (status != ADP_S_OK) return(1);
return(0); }
#pragma NDIS_INIT_FUNCTION(IdpAllocBuf)
/* allocate a buffer off a partition */ ULONG IdpAllocBuf(IDD *idd, INT part) { UCHAR status; ULONG msg_bufptr; ULONG temp;
D_LOG(D_ENTRY, ("IdpAllocBuf: entry, idd: 0x%p, part: %d", idd, part));
idd->ChangePage(idd, 0);
/* fillup & execute */ temp = (ULONG)(part + 4);
NdisMoveToMappedMemory ((PVOID)&idd->IdpCmd->msg_param, (PVOID)&temp, sizeof (ULONG));
status = idd->Execute(idd, IDP_L_GET_WBUF);
NdisMoveFromMappedMemory((PVOID)&msg_bufptr, (PVOID)&idd->IdpCmd->msg_bufptr, (ULONG)sizeof (ULONG));
idd->ChangePage(idd, IDD_PAGE_NONE);
return( (status == IDP_S_OK) ? msg_bufptr : 0 ); }
#pragma NDIS_INIT_FUNCTION(AdpAllocBuf)
/* allocate a buffer off a partition */ ULONG AdpAllocBuf(IDD *idd, INT part) { UCHAR status;
D_LOG(D_ENTRY, ("AdpAllocBuf: entry, idd: 0x%p, part: %d", idd, part));
//
// clear command structure
//
NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD));
//
// fill port id and status bit
//
idd->AdpCmd.msg_param = (UCHAR)part + 4; //
// execute command
//
status = idd->Execute(idd, ADP_L_GET_WBUF);
D_LOG(D_ALWAYS, ("AdpAllocBuf: status: 0x%x, BufPtr: 0x%x", status, idd->AdpCmd.msg_bufptr));
return ((status == ADP_S_OK) ? (ULONG)idd->AdpCmd.msg_bufptr : 0); }
/* reset idp board */ INT IdpResetBoard(IDD *idd) { USHORT bank, page; D_LOG(D_ENTRY, ("reset_board: entry, idd: 0x%p", idd));
/* while in reset, clear all idp banks/pages */ for ( bank = 0 ; bank < 3 ; bank++ ) { /* setup bank */ idd->SetBank(idd, (UCHAR)bank, 0);
/* loop on pages */ for ( page = 0 ; page < 4 ; page++ ) { /* setup page */ idd->ChangePage (idd, (UCHAR)page);
/* zero out (has to be a word fill!) */ IdpMemset((UCHAR*)idd->vhw.vmem, 0, 0x4000); } }
idd->SetBank(idd, IDD_BANK_CODE, 0);
//free page
idd->ChangePage (idd, (UCHAR)IDD_PAGE_NONE);
return(IDD_E_SUCC); }
/* reset idp board */ INT AdpResetBoard(IDD *idd) { //
// reset the adapter
//
AdpWriteControlBit(idd, ADP_RESET_BIT, 1);
return(IDD_E_SUCC); }
|