summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/digi/pcimac/idd_proc.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/digi/pcimac/idd_proc.c988
1 files changed, 988 insertions, 0 deletions
diff --git a/private/ntos/ndis/digi/pcimac/idd_proc.c b/private/ntos/ndis/digi/pcimac/idd_proc.c
new file mode 100644
index 000000000..eac4e52cd
--- /dev/null
+++ b/private/ntos/ndis/digi/pcimac/idd_proc.c
@@ -0,0 +1,988 @@
+/*
+ * 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);
+ }
+}