mirror of https://github.com/lianthony/NT4.0
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.
988 lines
27 KiB
988 lines
27 KiB
/*
|
|
* IDD_PROC.C - do real tx/rx processing
|
|
*/
|
|
|
|
|
|
#include <ndis.h>
|
|
#include <ndiswan.h>
|
|
#include <mytypes.h>
|
|
#include <mydefs.h>
|
|
#include <disp.h>
|
|
#include <util.h>
|
|
#include <opcodes.h>
|
|
#include <adapter.h>
|
|
#include <idd.h>
|
|
#include <mtl.h>
|
|
#include <cm.h>
|
|
#include <res.h>
|
|
|
|
#if DBG
|
|
#define AddBufferToList(_idd, _Part, _Buffer) \
|
|
{ \
|
|
BUFFER_MANAGER *IdpBufferStuff = &(_idd)->BufferStuff[_Part]; \
|
|
ULONG *PutBuffer = &IdpBufferStuff->Buffer[IdpBufferStuff->Put % 32]; \
|
|
ASSERT(!*PutBuffer); \
|
|
*PutBuffer = _Buffer; \
|
|
IdpBufferStuff->Put++; \
|
|
IdpBufferStuff->Count++; \
|
|
ASSERT(IdpBufferStuff->Count < 32); \
|
|
}
|
|
|
|
#define RemoveBufferFromList(_idd, _Part) \
|
|
{ \
|
|
BUFFER_MANAGER *IdpBufferStuff = &(_idd)->BufferStuff[_Part]; \
|
|
ULONG *GetBuffer = &IdpBufferStuff->Buffer[IdpBufferStuff->Get % 32]; \
|
|
ASSERT(*GetBuffer); \
|
|
*GetBuffer = 0; \
|
|
IdpBufferStuff->Get++; \
|
|
ASSERT(IdpBufferStuff->Count > 0); \
|
|
IdpBufferStuff->Count--; \
|
|
}
|
|
#endif
|
|
|
|
/* poll (process) trasmitter side */
|
|
ULONG
|
|
IdpPollTx(IDD *idd)
|
|
{
|
|
INT n, has_msg;
|
|
ULONG EventNum = 0;
|
|
IDD_SMSG smsg;
|
|
USHORT buf_len = 0, TxFlags = 0, TempUshort;
|
|
UCHAR status;
|
|
ULONG msg_bufptr, TempUlong;
|
|
|
|
D_LOG(D_NEVER, ("IdpPollTx: entry, idd: 0x%lx\n", idd));
|
|
|
|
/* must get semaphore */
|
|
if ( !sema_get(&idd->proc_sema) )
|
|
return(IDD_E_SUCC);
|
|
|
|
/* lock idd */
|
|
NdisAcquireSpinLock(&idd->lock);
|
|
|
|
if (!GetResourceSem (idd->res_mem))
|
|
{
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
sema_free(&idd->proc_sema);
|
|
return(IDD_E_SUCC);
|
|
}
|
|
|
|
IdpCPage(idd, 0);
|
|
|
|
/* loop on all tx ports */
|
|
for ( n = 0 ; n < IDD_TX_PORTS ; n++ )
|
|
{
|
|
USHORT part = idd->tx_partq[n];
|
|
|
|
/* skip non existent ports */
|
|
if ( !idd->tx_port[n] )
|
|
continue;
|
|
|
|
/* check if port is blocked on a buffer */
|
|
if ( !idd->tx_buf[part] )
|
|
{
|
|
/* try to get a buffer for this partition */
|
|
IdpCPage(idd, 0);
|
|
|
|
TempUlong = (ULONG)(part + 4);
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_param, (PVOID)&TempUlong, sizeof (ULONG));
|
|
|
|
status = idd->Execute(idd, IDP_L_GET_WBUF);
|
|
|
|
if ( status != IDP_S_OK)
|
|
{
|
|
D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #1: status=0x%x\n",
|
|
((ULONG)status & 0x000000FF)) );
|
|
continue;
|
|
}
|
|
|
|
/* if here, buffer allocated, register it */
|
|
NdisMoveFromMappedMemory( (PVOID)&idd->tx_buf[part], (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG));
|
|
|
|
#if DBG
|
|
AddBufferToList(idd, part, idd->tx_buf[part]);
|
|
#endif
|
|
|
|
}
|
|
|
|
/* check if a message is waiting to be sent on a port */
|
|
NdisAcquireSpinLock(&idd->sendq[n].lock);
|
|
if ( has_msg = idd->sendq[n].num )
|
|
{
|
|
/* extract message off queue */
|
|
smsg = idd->sendq[n].tbl[idd->sendq[n].get];
|
|
if ( ++idd->sendq[n].get >= idd->sendq[n].max )
|
|
idd->sendq[n].get = 0;
|
|
idd->sendq[n].num--;
|
|
}
|
|
NdisReleaseSpinLock(&idd->sendq[n].lock);
|
|
|
|
/* if no message, escape here */
|
|
if ( !has_msg )
|
|
continue;
|
|
|
|
/* debug print message */
|
|
D_LOG(DIGIIDD, ("poll_tx: smsg: opcode: 0x%x, buflen: 0x%x, bufptr: 0x%lx\n", \
|
|
smsg.msg.opcode, smsg.msg.buflen, smsg.msg.bufptr));
|
|
D_LOG(DIGIIDD, ("poll_tx: bufid: 0x%x, param: 0x%x, handler: 0x%lx, arg: 0x%lx\n", \
|
|
smsg.msg.bufid, smsg.msg.param, smsg.handler, smsg.handler_arg));
|
|
|
|
//
|
|
// save xmitflags clearing out dkf fragment indicator
|
|
// they are in most significant nible
|
|
// Bits - xxxx
|
|
// ||||__ fragment indicator
|
|
// |||___ tx flush flag
|
|
// ||____ !tx end flag
|
|
// |_____ !tx begin flag
|
|
//
|
|
TxFlags = smsg.msg.buflen & TX_FLAG_MASK;
|
|
|
|
|
|
#if DBG
|
|
switch (idd->BufferStuff[part].TxState)
|
|
{
|
|
case TX_BEGIN:
|
|
case TX_END:
|
|
if (TxFlags & H_TX_N_BEG)
|
|
{
|
|
DbgPrint("Missed a begining buffer! idd: 0x%x, part: %d\n", idd, part);
|
|
DbgPrint("TxFlags: 0x%x, State: 0x%x\n", TxFlags, idd->BufferStuff[part].TxState);
|
|
DbgBreakPoint();
|
|
}
|
|
else if (TxFlags & H_TX_N_END)
|
|
{
|
|
idd->BufferStuff[part].TxState = TX_MIDDLE;
|
|
idd->BufferStuff[part].FragsSinceBegin = 0;
|
|
}
|
|
break;
|
|
|
|
case TX_MIDDLE:
|
|
if (TxFlags & H_TX_N_BEG)
|
|
break;
|
|
else
|
|
{
|
|
DbgPrint("Missed an ending buffer! idd: 0x%x, part: %d\n", idd, part);
|
|
DbgPrint("TxFlags: 0x%x, State: 0x%x\n", TxFlags, idd->BufferStuff[part].TxState);
|
|
DbgBreakPoint();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DbgPrint("Unknown State! idd: 0x%x, part: %d\n", idd, part);
|
|
DbgPrint("TxFlags: 0x%x, State: 0x%x\n", TxFlags, idd->BufferStuff[part].TxState);
|
|
DbgBreakPoint();
|
|
idd->BufferStuff[part].TxState = TX_BEGIN;
|
|
idd->BufferStuff[part].FragsSinceBegin = 0;
|
|
break;
|
|
}
|
|
|
|
idd->BufferStuff[part].FragsSinceBegin++;
|
|
if (!(TxFlags & H_RX_N_END))
|
|
idd->BufferStuff[part].TxState = TX_END;
|
|
|
|
#endif
|
|
/* check for buffer, if has one, copyin */
|
|
|
|
IdpCPage(idd, 0);
|
|
|
|
if( idd->tx_buf[part] == 0 )
|
|
DbgPrint( "Giving a 0 buffer back in IDP_L_WRITE call!\n" );
|
|
|
|
NdisMoveToMappedMemory( (PVOID)&idd->IdpCmd->msg_bufptr,
|
|
(PVOID)&idd->tx_buf[part],
|
|
sizeof (ULONG) );
|
|
|
|
#if DBG
|
|
RemoveBufferFromList(idd, part);
|
|
#endif
|
|
|
|
if ( smsg.msg.bufptr )
|
|
buf_len = IdpCopyin(idd, (char*)idd->tx_buf[part],
|
|
smsg.msg.bufptr, smsg.msg.buflen);
|
|
else
|
|
buf_len = 0;
|
|
|
|
IdpCPage(idd, 0);
|
|
|
|
TempUshort = (USHORT)(buf_len | TxFlags);
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_buflen, (PVOID)&TempUshort, sizeof(USHORT));
|
|
|
|
/* copy rest of command area */
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_opcode, (PVOID)&smsg.msg.opcode, sizeof(USHORT));
|
|
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_bufid, (PVOID)&smsg.msg.bufid, sizeof (ULONG));
|
|
|
|
TempUlong = (ULONG)(part + 4);
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_param, (PVOID)&TempUlong, sizeof (ULONG));
|
|
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_id, (PVOID)&idd->tx_port[n], sizeof(USHORT));
|
|
|
|
/* execute the command, mark an event */
|
|
|
|
status = idd->Execute(idd, IDP_L_WRITE);
|
|
|
|
EventNum++;
|
|
|
|
/* if came back with no buffer, mark it - else store buffer */
|
|
if ( status != IDP_S_OK )
|
|
{
|
|
idd->tx_buf[part] = 0;
|
|
D_LOG(D_RARE, ("poll_tx: no buffer!, part: %d\n", part));
|
|
D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #2: status=0x%x\n",
|
|
((ULONG)status & 0x000000FF)) );
|
|
}
|
|
else
|
|
{
|
|
NdisMoveFromMappedMemory((PVOID)&msg_bufptr, (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG));
|
|
|
|
if ( msg_bufptr )
|
|
{
|
|
idd->tx_buf[part] = msg_bufptr;
|
|
|
|
#if DBG
|
|
AddBufferToList(idd, part, idd->tx_buf[part]);
|
|
#endif
|
|
|
|
D_LOG(D_RARE, ("poll_tx: new buffer, part: %d, buf: 0x%lx\n", \
|
|
part, idd->tx_buf[part]));
|
|
}
|
|
else
|
|
{
|
|
idd->tx_buf[part] = 0;
|
|
DbgPrint( "Adapter did not return buffer in IDP_L_WRITE\n" );
|
|
}
|
|
}
|
|
|
|
/* call user's handler */
|
|
if ( smsg.handler ) {
|
|
(*smsg.handler)(smsg.handler_arg, n, &smsg);
|
|
}
|
|
|
|
}
|
|
|
|
/* unset page, free memory window */
|
|
IdpCPage(idd, IDD_PAGE_NONE);
|
|
|
|
FreeResourceSem (idd->res_mem);
|
|
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
|
|
sema_free(&idd->proc_sema);
|
|
|
|
return(EventNum);
|
|
}
|
|
|
|
/* poll (process) trasmitter side */
|
|
ULONG
|
|
AdpPollTx(IDD *idd)
|
|
{
|
|
USHORT buf_len = 0, TxFlags = 0;
|
|
UCHAR status;
|
|
ULONG n, part, has_msg, EventNum = 0;
|
|
IDD_SMSG smsg;
|
|
|
|
D_LOG(D_NEVER, ("AdpPollTx: entry, idd: 0x%lx\n", idd));
|
|
|
|
/* must get semaphore */
|
|
if ( !sema_get(&idd->proc_sema) )
|
|
return(IDD_E_SUCC);
|
|
|
|
/* lock idd */
|
|
NdisAcquireSpinLock(&idd->lock);
|
|
|
|
//
|
|
// Lock access to the I/O ports in case this is a multi-BRI adapter
|
|
// e.g. DataFire4
|
|
//
|
|
if (!GetResourceSem (idd->res_io))
|
|
{
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
sema_free(&idd->proc_sema);
|
|
return(IDD_E_SUCC);
|
|
}
|
|
|
|
//
|
|
// for all tx ports
|
|
//
|
|
for (n = 0; n < IDD_TX_PORTS; n++)
|
|
{
|
|
//
|
|
// skip non existent ports
|
|
//
|
|
if (!idd->tx_port[n])
|
|
continue;
|
|
|
|
//
|
|
// clear command structure
|
|
//
|
|
NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD));
|
|
|
|
//
|
|
// see if port is blocked needing a buffer
|
|
//
|
|
if ( !idd->tx_buf[part = idd->tx_partq[n]] )
|
|
{
|
|
|
|
//
|
|
// fill port id and status bit
|
|
//
|
|
idd->AdpCmd.msg_param = (UCHAR)part + 4;
|
|
//
|
|
// execute command
|
|
//
|
|
status = idd->Execute(idd, ADP_L_GET_WBUF);
|
|
|
|
//
|
|
// if no buffer then go to next port
|
|
//
|
|
if (status != ADP_S_OK)
|
|
{
|
|
D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #1: status=0x%x\n",
|
|
((ULONG)status & 0x000000FF)) );
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// if here, buffer was allocate, register it
|
|
//
|
|
idd->tx_buf[part] = (ULONG)idd->AdpCmd.msg_bufptr;
|
|
|
|
}
|
|
|
|
//
|
|
// see if there is a message waiting to be sent
|
|
//
|
|
NdisAcquireSpinLock(&idd->sendq[n].lock);
|
|
if ( has_msg = idd->sendq[n].num )
|
|
{
|
|
/* extract message off queue */
|
|
smsg = idd->sendq[n].tbl[idd->sendq[n].get];
|
|
if ( ++idd->sendq[n].get >= idd->sendq[n].max )
|
|
idd->sendq[n].get = 0;
|
|
idd->sendq[n].num--;
|
|
}
|
|
NdisReleaseSpinLock(&idd->sendq[n].lock);
|
|
|
|
//
|
|
// if no message go to next port
|
|
//
|
|
if (!has_msg)
|
|
continue;
|
|
|
|
/* debug print message */
|
|
D_LOG(DIGIIDD, ("AdpPollTx: smsg: opcode: 0x%x, buflen: 0x%x, bufptr: 0x%lx\n", \
|
|
smsg.msg.opcode, smsg.msg.buflen, smsg.msg.bufptr));
|
|
D_LOG(DIGIIDD, ("AdpPollTx: bufid: 0x%x, param: 0x%x, handler: 0x%lx, arg: 0x%lx\n", \
|
|
smsg.msg.bufid, smsg.msg.param, smsg.handler, smsg.handler_arg));
|
|
|
|
|
|
//
|
|
// save xmitflags clearing out dkf fragment indicator
|
|
// they are in most significant nible
|
|
// Bits - xxxx
|
|
// ||||__ fragment indicator
|
|
// |||___ tx flush flag
|
|
// ||____ !tx end flag
|
|
// |_____ !tx begin flag
|
|
//
|
|
TxFlags = smsg.msg.buflen & TX_FLAG_MASK;
|
|
|
|
//
|
|
// see if there is a buffer to be copied
|
|
//
|
|
(ULONG)idd->AdpCmd.msg_bufptr = idd->tx_buf[part];
|
|
|
|
if ( smsg.msg.bufptr )
|
|
buf_len = AdpCopyin(idd, smsg.msg.bufptr, smsg.msg.buflen);
|
|
else
|
|
buf_len = 0;
|
|
|
|
idd->AdpCmd.msg_buflen = buf_len | TxFlags;
|
|
idd->AdpCmd.msg_opcode = smsg.msg.opcode;
|
|
idd->AdpCmd.msg_bufid = smsg.msg.bufid;
|
|
idd->AdpCmd.msg_param = (ULONG)(part + 4);
|
|
idd->AdpCmd.port_id = idd->tx_port[n];
|
|
|
|
status = idd->Execute(idd, ADP_L_WRITE);
|
|
|
|
EventNum++;
|
|
|
|
if (status != ADP_S_OK)
|
|
{
|
|
idd->tx_buf[part] = 0;
|
|
D_LOG(D_RARE, ("poll_tx: no buffer!, part: %d\n", part));
|
|
D_LOG( DIGIERRORS, ( "Please contact Kendal Gabel or Rik Logan #2: status=0x%x\n",
|
|
((ULONG)status & 0x000000FF)) );
|
|
}
|
|
else
|
|
{
|
|
if (idd->AdpCmd.msg_bufptr)
|
|
{
|
|
idd->tx_buf[part] = (ULONG)idd->AdpCmd.msg_bufptr;
|
|
D_LOG(D_RARE, ("poll_tx: new buffer, part: %d, buf: 0x%lx\n", \
|
|
part, idd->tx_buf[part]));
|
|
|
|
}
|
|
}
|
|
/* call user's handler */
|
|
if ( smsg.handler )
|
|
(*smsg.handler)(smsg.handler_arg, n, &smsg);
|
|
}
|
|
|
|
FreeResourceSem (idd->res_io);
|
|
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
|
|
sema_free(&idd->proc_sema);
|
|
|
|
return(EventNum);
|
|
} // end AdpPollTx
|
|
|
|
/* poll (process) reciever ports */
|
|
ULONG
|
|
IdpPollRx(IDD *idd)
|
|
{
|
|
INT n, m;
|
|
USHORT stat, ofs;
|
|
IDD_XMSG msg;
|
|
UCHAR status, Page;
|
|
ULONG TempUlong, EventNum = 0;
|
|
|
|
/* must get semaphore */
|
|
if ( !sema_get(&idd->proc_sema) )
|
|
return(IDD_E_SUCC);
|
|
|
|
/* lock idd */
|
|
NdisAcquireSpinLock(&idd->lock);
|
|
|
|
if (!GetResourceSem (idd->res_mem))
|
|
{
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
sema_free(&idd->proc_sema);
|
|
return(IDD_E_SUCC);
|
|
}
|
|
|
|
/* get status port */
|
|
IdpCPage(idd, 0);
|
|
|
|
NdisMoveFromMappedMemory((PVOID)&stat, (PVOID)idd->IdpStat, sizeof(USHORT));
|
|
|
|
D_LOG(D_NEVER, ("poll_rx: stat: 0x%x (@0x%lx)\n", stat, idd->IdpStat));
|
|
|
|
/* make one pass on all rx ports which have a status bit on */
|
|
for ( n = 0 ; n < IDD_RX_PORTS ; n++, stat >>= 1 )
|
|
if ( stat & 1 )
|
|
{
|
|
//
|
|
// skip non existent ports
|
|
//
|
|
if (!idd->rx_port[n])
|
|
continue;
|
|
|
|
/* install returned read buffer */
|
|
IdpCPage(idd, 0);
|
|
|
|
TempUlong = MAKELONG(HIWORD(idd->rx_buf), 0);
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->msg_bufid, (PVOID)&TempUlong, sizeof (ULONG));
|
|
|
|
idd->rx_buf = 0;
|
|
|
|
/* install port & execute a read */
|
|
D_LOG(DIGIIDD, ("poll_rx: index: %d, ReadPort 0x%x\n", n, idd->rx_port[n]));
|
|
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->port_id, (PVOID)&idd->rx_port[n], sizeof(USHORT));
|
|
|
|
status = idd->Execute(idd, IDP_L_READ);
|
|
|
|
if ( status != IDP_S_OK )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
EventNum++;
|
|
|
|
/* copy message out */
|
|
NdisMoveFromMappedMemory((PVOID)&msg.opcode, (PVOID)&idd->IdpCmd->msg_opcode, sizeof(USHORT));
|
|
|
|
NdisMoveFromMappedMemory((PVOID)&msg.buflen, (PVOID)&idd->IdpCmd->msg_buflen, sizeof(USHORT));
|
|
|
|
// save receive fragment flags
|
|
// they are in most significant nible
|
|
// Bits - xxxx
|
|
// ||||__ reserved
|
|
// |||___ reserved
|
|
// ||____ !rx end flag
|
|
// |_____ !rx begin flag
|
|
//
|
|
msg.FragmentFlags = msg.buflen & RX_FLAG_MASK;
|
|
|
|
//
|
|
// get real buffer length
|
|
//
|
|
msg.buflen &= H_RX_LEN_MASK;
|
|
|
|
NdisMoveFromMappedMemory((PVOID)&msg.bufptr, (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG));
|
|
|
|
NdisMoveFromMappedMemory((PVOID)&msg.bufid, (PVOID)&idd->IdpCmd->msg_bufid, sizeof (ULONG));
|
|
|
|
NdisMoveFromMappedMemory((PVOID)&msg.param, (PVOID)&idd->IdpCmd->msg_param, sizeof (ULONG));
|
|
|
|
/* save rx buffer */
|
|
idd->rx_buf = (ULONG)msg.bufptr;
|
|
D_LOG(DIGIIDD, ("poll_rx: 0x%x 0x%x %lx %lx %lx\n", \
|
|
msg.opcode, \
|
|
msg.buflen, \
|
|
msg.bufptr, \
|
|
msg.bufid, \
|
|
msg.param));
|
|
|
|
if ( msg.bufptr)
|
|
{
|
|
ofs = LOWORD(msg.bufptr);
|
|
Page = (UCHAR)(ofs >> 14) & 3;
|
|
#if DBG
|
|
if (Page > 1 )
|
|
{
|
|
DbgPrint("Page changed to %d on idd 0x%lx!\n", Page, idd);
|
|
DbgBreakPoint();
|
|
}
|
|
#endif
|
|
msg.bufptr = idd->vhw.vmem + (ofs & 0x3FFF);
|
|
IdpCPage(idd, Page);
|
|
}
|
|
|
|
/* loop on rx handler, call user to copyout buffer */
|
|
for ( m = 0 ; m < idd->recit[n].num ; m++ )
|
|
(*idd->recit[n].tbl[m].handler)(idd->recit[n].tbl[m].handler_arg,
|
|
n,
|
|
idd->recit[n].RxFrameType,
|
|
&msg);
|
|
}
|
|
|
|
/* unset page, free memory window */
|
|
IdpCPage(idd, IDD_PAGE_NONE);
|
|
|
|
FreeResourceSem (idd->res_mem);
|
|
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
|
|
sema_free(&idd->proc_sema);
|
|
|
|
return(EventNum);
|
|
}
|
|
|
|
/* poll (process) receiver side */
|
|
ULONG
|
|
AdpPollRx(IDD *idd)
|
|
{
|
|
INT n, m;
|
|
UCHAR status;
|
|
ULONG EventNum = 0;
|
|
USHORT stat = 0;
|
|
IDD_XMSG msg;
|
|
|
|
/* must get semaphore */
|
|
if ( !sema_get(&idd->proc_sema) )
|
|
return(IDD_E_SUCC);
|
|
|
|
/* lock idd */
|
|
NdisAcquireSpinLock(&idd->lock);
|
|
|
|
if (!GetResourceSem (idd->res_io))
|
|
{
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
sema_free(&idd->proc_sema);
|
|
return(IDD_E_SUCC);
|
|
}
|
|
|
|
stat = AdpReadReceiveStatus(idd);
|
|
|
|
for( n = 0; stat && (n < IDD_RX_PORTS); n++, stat >>= 1 )
|
|
if (stat & 1)
|
|
{
|
|
//
|
|
// clear command structure
|
|
//
|
|
NdisZeroMemory(&idd->AdpCmd, sizeof(ADP_CMD));
|
|
|
|
D_LOG(DIGIIDD, ("poll_rx: index: %d, ReadPort 0x%x\n", n, idd->rx_port[n]));
|
|
//
|
|
// return read buffer
|
|
//
|
|
idd->AdpCmd.msg_bufid = MAKELONG(HIWORD(idd->rx_buf), 0);
|
|
idd->rx_buf = 0;
|
|
|
|
idd->AdpCmd.port_id = idd->rx_port[n];
|
|
|
|
status = idd->Execute(idd, ADP_L_READ);
|
|
|
|
if (status != ADP_S_OK)
|
|
continue;
|
|
|
|
EventNum++;
|
|
|
|
msg.opcode = idd->AdpCmd.msg_opcode;
|
|
msg.buflen = idd->AdpCmd.msg_buflen;
|
|
|
|
// save receive fragment flags
|
|
// they are in most significant nible
|
|
// Bits - xxxx
|
|
// ||||__ reserved
|
|
// |||___ reserved
|
|
// ||____ !rx end flag
|
|
// |_____ !rx begin flag
|
|
//
|
|
msg.FragmentFlags = msg.buflen & RX_FLAG_MASK;
|
|
|
|
//
|
|
// get real buffer length
|
|
//
|
|
msg.buflen &= H_RX_LEN_MASK;
|
|
|
|
msg.bufptr = (UCHAR*)LOWORD(idd->AdpCmd.msg_bufptr);
|
|
idd->rx_buf = (ULONG)idd->AdpCmd.msg_bufptr;
|
|
msg.bufid = idd->AdpCmd.msg_bufid;
|
|
msg.param = idd->AdpCmd.msg_param;
|
|
|
|
|
|
D_LOG(DIGIIDD, ("AdpPollRx: Opcode: 0x%x, BufLen: 0x%x, BufPtr: 0x%x\n", \
|
|
msg.opcode, \
|
|
msg.buflen, \
|
|
msg.bufptr));
|
|
D_LOG(DIGIIDD, ("AdpPollRx: FragmentFlags: 0x%x, BufId: 0x%x, Param: 0x%x\n", \
|
|
msg.FragmentFlags,\
|
|
msg.bufid, \
|
|
msg.param));
|
|
|
|
/* loop on rx handler, call user to copyout buffer */
|
|
for ( m = 0 ; m < idd->recit[n].num ; m++ )
|
|
(*idd->recit[n].tbl[m].handler)(idd->recit[n].tbl[m].handler_arg,
|
|
n,
|
|
idd->recit[n].RxFrameType,
|
|
&msg);
|
|
}
|
|
|
|
FreeResourceSem( idd->res_io );
|
|
|
|
NdisReleaseSpinLock(&idd->lock);
|
|
|
|
sema_free(&idd->proc_sema);
|
|
|
|
return(EventNum);
|
|
} // end AdpPollRx
|
|
|
|
/* execute an idp command. assumes cpage=0 */
|
|
UCHAR
|
|
IdpExec(IDD *idd, UCHAR opcode)
|
|
{
|
|
UCHAR status = IDP_S_PEND;
|
|
ULONG TempWaitCounter;
|
|
|
|
#if DBG
|
|
USHORT IdpCounter1 = 0;
|
|
ULONG IdpCounter2 = 0;
|
|
#endif
|
|
|
|
D_LOG(D_ENTRY, ("IdpExec: entry, idd: 0x%lx, opcode=%d\n", idd, opcode));
|
|
|
|
/* install opcode, get command started */
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->opcode, (PVOID)&opcode, sizeof(UCHAR));
|
|
|
|
NdisMoveToMappedMemory((PVOID)&idd->IdpCmd->status, (PVOID)&status, sizeof(UCHAR));
|
|
|
|
status = IDP_S_EXEC;
|
|
|
|
#if DBG
|
|
NdisMoveFromMappedMemory((PVOID)&IdpCounter1, (PVOID)(idd->vhw.vmem + 0x804), sizeof(USHORT));
|
|
NdisMoveFromMappedMemory((PVOID)&IdpCounter2, (PVOID)(idd->vhw.vmem + 0x808), sizeof(ULONG));
|
|
#endif
|
|
|
|
idd->WaitCounter = 0;
|
|
|
|
while ( idd->state != IDD_S_SHUTDOWN )
|
|
{
|
|
NdisMoveFromMappedMemory((PVOID)&TempWaitCounter, (PVOID)(idd->vhw.vmem + 0x80C), sizeof(ULONG));
|
|
NdisMoveFromMappedMemory((PVOID)&status, (PVOID)&idd->IdpCmd->status, sizeof(UCHAR));
|
|
|
|
if ( IDP_S_DONE(status) )
|
|
break;
|
|
|
|
//
|
|
// wait for 1ms
|
|
// the ddk says that this function uses milliseconds but it
|
|
// actually takes microseconds
|
|
//
|
|
NdisStallExecution(1000L);
|
|
|
|
idd->WaitCounter++;
|
|
NdisMoveToMappedMemory((PVOID)(idd->vhw.vmem + 0x80C), (PVOID)&idd->WaitCounter, sizeof(ULONG));
|
|
|
|
//
|
|
// this should wait for about one second
|
|
//
|
|
if (idd->WaitCounter > 1000)
|
|
{
|
|
|
|
idd->state = IDD_S_SHUTDOWN;
|
|
#if DBG
|
|
DbgPrint("Shutdown! idd: 0x%lx, Status: 0x%x\n", idd, status);
|
|
DbgPrint("Original: IdpCounter1: 0x%x, IdpCounter2: 0x%x\n", IdpCounter1, IdpCounter2);
|
|
NdisMoveFromMappedMemory((PVOID)&IdpCounter1, (PVOID)(idd->vhw.vmem + 0x804), sizeof(USHORT));
|
|
NdisMoveFromMappedMemory((PVOID)&IdpCounter2, (PVOID)(idd->vhw.vmem + 0x808), sizeof(ULONG));
|
|
DbgPrint("Current: IdpCounter1: 0x%x, IdpCounter2: 0x%x\n", IdpCounter1, IdpCounter2);
|
|
NdisMoveFromMappedMemory((PVOID)&status, (PVOID)&idd->IdpCmd->status, sizeof(UCHAR));
|
|
DbgPrint("CurrentStatus: 0x%x\n",status);
|
|
DbgBreakPoint();
|
|
#endif
|
|
break;
|
|
}
|
|
else
|
|
status = IDP_S_EXEC;
|
|
}
|
|
|
|
D_LOG(D_EXIT, ("IdpExec: exit, IdpCmd->status: 0x%x\n", status));
|
|
|
|
#if DBG
|
|
if (status && (status != IDP_S_NOBUF)
|
|
&& (status != IDP_S_NOMSG))
|
|
{
|
|
USHORT MsgOpcode;
|
|
USHORT MsgBuflen;
|
|
UCHAR *MsgBufPtr;
|
|
ULONG MsgBufId;
|
|
ULONG MsgParam;
|
|
|
|
DbgPrint("Idd 0x%lx error executing opcode: 0x%x, status: 0x%x\n", idd, opcode, status);
|
|
NdisMoveFromMappedMemory((PVOID)&MsgOpcode, (PVOID)&idd->IdpCmd->msg_opcode, sizeof(USHORT));
|
|
NdisMoveFromMappedMemory((PVOID)&MsgBuflen, (PVOID)&idd->IdpCmd->msg_buflen, sizeof(USHORT));
|
|
NdisMoveFromMappedMemory( (PVOID)&MsgBufPtr, (PVOID)&idd->IdpCmd->msg_bufptr, sizeof (ULONG));
|
|
NdisMoveFromMappedMemory((PVOID)&MsgBufId, (PVOID)&idd->IdpCmd->msg_bufid, sizeof (ULONG));
|
|
NdisMoveFromMappedMemory((PVOID)&MsgParam, (PVOID)&idd->IdpCmd->msg_param, sizeof (ULONG));
|
|
DbgPrint("IdpExec: MsgOpcode: 0x%x, MsgBufLen: 0x%x, MsgBufPtr: 0x%x\n", MsgOpcode, MsgBuflen, MsgBufPtr);
|
|
DbgPrint("IdpExec: MsgBufId: 0x%x, MsgParam: 0x%x\n", MsgBufId, MsgParam);
|
|
}
|
|
#endif
|
|
|
|
if (idd->WaitCounter > idd->MaxWaitCounter)
|
|
idd->MaxWaitCounter = idd->WaitCounter;
|
|
|
|
return(status);
|
|
}
|
|
|
|
/* execute an Adp command. assumes cpage=0 */
|
|
UCHAR
|
|
AdpExec(IDD *idd, UCHAR opcode)
|
|
{
|
|
UCHAR status = ADP_S_PEND;
|
|
ULONG TempWaitCounter;
|
|
|
|
//
|
|
// set opcode
|
|
//
|
|
idd->AdpCmd.opcode = opcode;
|
|
|
|
D_LOG(D_ENTRY, ("AdpExec: entry, idd: 0x%lx, opcode: %d\n", idd, opcode));
|
|
D_LOG(D_ENTRY, ("status: 0x%x, port_id: 0x%x", idd->AdpCmd.status, idd->AdpCmd.port_id));
|
|
D_LOG(D_ENTRY, ("msg_opcode: 0x%x, msg_buflen: 0x%x\n", idd->AdpCmd.msg_opcode, idd->AdpCmd.msg_buflen));
|
|
D_LOG(D_ENTRY, ("msg_bufptr: 0x%x, msg_bufid: 0x%x\n", idd->AdpCmd.msg_bufptr, idd->AdpCmd.msg_bufid));
|
|
D_LOG(D_ENTRY, ("msg_param: 0x%x\n", idd->AdpCmd.msg_param));
|
|
|
|
//
|
|
// copy in command buffer
|
|
//
|
|
AdpPutBuffer(idd, ADP_CMD_WINDOW, (PUCHAR)&idd->AdpCmd, sizeof(ADP_CMD));
|
|
|
|
//
|
|
// start operation
|
|
//
|
|
AdpWriteCommandStatus(idd, ADP_S_PEND);
|
|
|
|
idd->WaitCounter = 0;
|
|
|
|
while ( idd->state != IDD_S_SHUTDOWN )
|
|
{
|
|
TempWaitCounter = AdpGetULong(idd, 0x50C);
|
|
|
|
status = AdpReadCommandStatus(idd);
|
|
|
|
if ( ADP_S_DONE(status) )
|
|
break;
|
|
|
|
//
|
|
// wait for 1ms
|
|
// the ddk says that this function uses milliseconds but it
|
|
// actually takes microseconds
|
|
//
|
|
NdisStallExecution(1000L);
|
|
|
|
idd->WaitCounter++;
|
|
AdpPutULong(idd, 0x50C, idd->WaitCounter);
|
|
|
|
//
|
|
// this should wait for about one second
|
|
//
|
|
if (idd->WaitCounter > 1000)
|
|
{
|
|
idd->state = IDD_S_SHUTDOWN;
|
|
idd->AbortReason = AdpGetUShort(idd, ADP_STS_WINDOW + 12);
|
|
}
|
|
}
|
|
|
|
AdpGetBuffer(idd, (PUCHAR)&idd->AdpCmd, ADP_CMD_WINDOW, sizeof(ADP_CMD));
|
|
|
|
if (idd->WaitCounter > idd->MaxWaitCounter)
|
|
idd->MaxWaitCounter = idd->WaitCounter;
|
|
|
|
D_LOG(D_EXIT, ("AdpExec: exit, AdpCmd.status: 0x%x\n", status));
|
|
|
|
return(status);
|
|
} // end AdpExec
|
|
|
|
/* map current idp page in */
|
|
VOID
|
|
IdpCPage(IDD *idd, UCHAR page)
|
|
{
|
|
D_LOG(D_RARE, ("IdpCPage: entry, idd: 0x%lx, page: 0x%x\n", idd, page));
|
|
|
|
/* if page is IDD_PAGE_NONE, idd is releasing ownership of the page */
|
|
if ( page == IDD_PAGE_NONE )
|
|
{
|
|
idd->SetPage(idd, IDD_PAGE_NONE);
|
|
res_unown(idd->res_mem, idd);
|
|
}
|
|
else
|
|
{
|
|
page &= 3;
|
|
|
|
/* real mapping required, lock memory resource */
|
|
res_own(idd->res_mem, idd);
|
|
idd->SetPage(idd, page);
|
|
}
|
|
}
|
|
|
|
/* map current Adp page in */
|
|
VOID
|
|
AdpCPage(IDD *idd, UCHAR page)
|
|
{
|
|
|
|
}
|
|
|
|
/* copy data from user buffer to idp */
|
|
USHORT
|
|
IdpCopyin(IDD *idd, UCHAR *dst, UCHAR *src, USHORT src_len)
|
|
{
|
|
USHORT ofs, copylen;
|
|
UCHAR Page;
|
|
UINT tot_len, frag_num;
|
|
IDD_FRAG *frag;
|
|
|
|
D_LOG(D_RARE, ("Idpcopyin: entry, idd: 0x%lx, dst: 0x%lx, src: 0x%lx, src_len: 0x%x\n", \
|
|
idd, dst, src, src_len));
|
|
|
|
/* convert destination pointer to address & map in */
|
|
ofs = LOWORD((long)dst);
|
|
Page = (UCHAR)(ofs >> 14) & 3;
|
|
|
|
#if DBG
|
|
if (Page > 1 )
|
|
DbgPrint("Page changed to %d on idd 0x%lx!\n", Page, idd);
|
|
#endif
|
|
|
|
dst = idd->vhw.vmem + (ofs & 0x3FFF);
|
|
|
|
IdpCPage(idd, Page);
|
|
|
|
//
|
|
// mask out various flags to get length to copy
|
|
//
|
|
copylen = src_len & H_TX_LEN_MASK;
|
|
|
|
/* check for a simple copy, real easy - doit here */
|
|
if ( !(src_len & TX_FRAG_INDICATOR) )
|
|
{
|
|
NdisMoveToMappedMemory (dst, src, copylen);
|
|
return(copylen);
|
|
}
|
|
|
|
/* if here, its a fragment descriptor */
|
|
tot_len = 0;
|
|
frag_num = (copylen) / sizeof(IDD_FRAG);
|
|
frag = (IDD_FRAG*)src;
|
|
|
|
/* copy fragments */
|
|
for ( ; frag_num ; frag_num--, frag++ )
|
|
{
|
|
NdisMoveToMappedMemory (dst, frag->ptr, frag->len);
|
|
dst += frag->len;
|
|
tot_len += frag->len;
|
|
}
|
|
|
|
/* read total length */
|
|
return(tot_len);
|
|
}
|
|
|
|
/* copy data from user buffer to idp */
|
|
USHORT
|
|
AdpCopyin(IDD *idd, UCHAR *src, USHORT src_len)
|
|
{
|
|
USHORT Destination, CopyLength;
|
|
UINT tot_len, frag_num;
|
|
IDD_FRAG *frag;
|
|
|
|
D_LOG(D_RARE, ("Adpcopyin: entry, idd: 0x%lx, src: 0x%lx, src_len: 0x%x\n", \
|
|
idd, src, src_len));
|
|
|
|
/* convert destination pointer to address & map in */
|
|
Destination = LOWORD(idd->AdpCmd.msg_bufptr);
|
|
|
|
//
|
|
// mask out various flags to get length to copy
|
|
//
|
|
CopyLength = src_len & H_TX_LEN_MASK;
|
|
|
|
/* check for a simple copy, real easy - doit here */
|
|
if ( !(src_len & TX_FRAG_INDICATOR) )
|
|
{
|
|
AdpPutBuffer(idd, Destination, src, CopyLength);
|
|
return(CopyLength);
|
|
}
|
|
|
|
/* if here, its a fragment descriptor */
|
|
tot_len = 0;
|
|
frag_num = (CopyLength) / sizeof(IDD_FRAG);
|
|
frag = (IDD_FRAG*)src;
|
|
|
|
/* copy fragments */
|
|
for ( ; frag_num ; frag_num--, frag++ )
|
|
{
|
|
AdpPutBuffer(idd, Destination, frag->ptr, frag->len);
|
|
Destination += frag->len;
|
|
tot_len += frag->len;
|
|
}
|
|
|
|
/* read total length */
|
|
return(tot_len);
|
|
} // end AdpCopyin
|
|
|
|
VOID
|
|
IddGetDataFromAdapter(
|
|
VOID *idd_1,
|
|
PUCHAR Destination,
|
|
PUCHAR Source,
|
|
USHORT Length
|
|
)
|
|
{
|
|
IDD *idd = (IDD*)idd_1;
|
|
|
|
if( (idd->btype != IDD_BT_DATAFIREU) &&
|
|
(idd->btype != IDD_BT_DATAFIREST) &&
|
|
(idd->btype != IDD_BT_DATAFIRE4ST) )
|
|
{
|
|
NdisMoveFromMappedMemory(Destination, Source, Length);
|
|
}
|
|
else
|
|
{
|
|
AdpGetBuffer(idd, Destination, (ULONG)Source, Length);
|
|
}
|
|
}
|