diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/pcimac/idd_run.c | 777 |
1 files changed, 777 insertions, 0 deletions
diff --git a/private/ntos/ndis/pcimac/idd_run.c b/private/ntos/ndis/pcimac/idd_run.c new file mode 100644 index 000000000..585bbeb51 --- /dev/null +++ b/private/ntos/ndis/pcimac/idd_run.c @@ -0,0 +1,777 @@ +/* + * 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); +} + |