/* * IDD_PROC.C - do real tx/rx processing */ #include #include #include #include #include #include #include #include #include #include #include #include #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); } }