Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

777 lines
17 KiB

/*
* 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);
}