📄 nsc.c
字号:
}
#endif
rcvBuf->dataBuf = data;
VerifyNdisPacket(rcvBuf->packet, 0);
rcvBuf->state = STATE_FULL;
rcvBuf->dataLen = dataLen;
if (!IsFIR)
{
rcvBuf->isDmaBuf = FALSE;
InsertTailList(&thisDev->rcvBufFull,
ListEntry);
}
else
{
rcvBuf->isDmaBuf = TRUE;
LOG_InsertTailList(thisDev, &thisDev->rcvBufFull, rcvBuf);
NDISSynchronizedInsertTailList(&thisDev->rcvBufFull,
ListEntry,
&thisDev->interruptObj);
}
}
LOG(TEXT("<== QueueReceivePacket"), 1);
DBGOUT((TEXT("<== QueueReceivePacket")));
}
/*
*************************************************************************
* MiniportISR
*************************************************************************
*
*
* This is the miniport's interrupt service routine (ISR).
*
*
*/
VOID MiniportISR(PBOOLEAN InterruptRecognized,
PBOOLEAN QueueMiniportHandleInterrupt,
NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
*InterruptRecognized = FALSE;
*QueueMiniportHandleInterrupt = FALSE;
{
UINT val;
//IrDA int req?
val = READ_REGISTER_USHORT(pNIRR);
if(val & CC_INTC_NIRR_IRDAR){
// It's our Iinterrupt
;
}
else{
DEBUGMSG(1, (TEXT("MiniportISR: SPURIOUS INT!!!!!!!!!!!!!!!!!\r\n")));
*InterruptRecognized = FALSE;
*QueueMiniportHandleInterrupt = FALSE;
}
}
if (!thisDev->resourcesReleased){
/*
* Service the interrupt.
*/
if (thisDev->currentSpeed > MAX_SIR_SPEED){
NSC_FIR_ISR(thisDev, InterruptRecognized,
QueueMiniportHandleInterrupt);
}
else {
COM_ISR(thisDev, InterruptRecognized,
QueueMiniportHandleInterrupt);
}
#ifdef UNDER_CE
if (*InterruptRecognized == TRUE && *QueueMiniportHandleInterrupt == TRUE)
{
MiniportHandleInterrupt(MiniportAdapterContext);
*QueueMiniportHandleInterrupt = FALSE;
// NDIS normally re-enables ints for me after the DPC, but does
// NOT if a DPC is not required.
SetCOMInterrupts(thisDev, TRUE);
// WRITE_REGISTER_UCHAR(pIMSTCR, READ_REGISTER_UCHAR(pIMSTCR) | CC_FIR_IMSTCR_IEN);
} // end move
#endif
}
else{
/* clear interrupt */
UCHAR iir;
iir = READ_REGISTER_UCHAR(pIrIIR);
if(iir & 0x01){
// interrupt none
;
}else{
switch(iir & 0x0e){
case SERIAL_IIR_MS:
// Modem Status
READ_REGISTER_UCHAR(pIrMSR);
break;
case SERIAL_IIR_THRE:
// Transmitter Holding Register Empty
break;
case SERIAL_IIR_RDA:
// Receive Data Available
READ_REGISTER_UCHAR(pIrRBR);
break;
case SERIAL_IIR_RLS:
// Receiver Line Status
READ_REGISTER_UCHAR(pIrLSR);
case SERIAL_IIR_CTI:
// Character Timer-out Indication
READ_REGISTER_UCHAR(pIrRBR);
default:
break;
}
}
}
*InterruptRecognized = TRUE;
*QueueMiniportHandleInterrupt = FALSE;
}
/*
*************************************************************************
* MiniportReconfigure
*************************************************************************
*
*
* Reconfigures the network interface card to new parameters available
* in the NDIS library configuration functions.
*
*
*/
NDIS_STATUS MiniportReconfigure ( OUT PNDIS_STATUS OpenErrorStatus,
IN NDIS_HANDLE MiniportAdapterContext,
IN NDIS_HANDLE WrapperConfigurationContext
)
{
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
NDIS_STATUS result;
DBGOUT((TEXT("MiniportReconfigure(0x%x)"), (UINT)MiniportAdapterContext));
MiniportHalt(MiniportAdapterContext);
if (Configure(thisDev, WrapperConfigurationContext)){
result = NDIS_STATUS_SUCCESS;
}
else {
result = NDIS_STATUS_FAILURE;
}
DBGOUT((TEXT("MiniportReconfigure")));
*OpenErrorStatus = result;
return result;
}
/*
*************************************************************************
* MiniportReset
*************************************************************************
*
*
* MiniportReset issues a hardware reset to the network interface card.
* The miniport driver also resets its software state.
*
*
*/
// NOTE: Arguments are reversed from as documented in April '96 MSDN!
NDIS_STATUS MiniportReset(PBOOLEAN AddressingReset, NDIS_HANDLE MiniportAdapterContext)
{
IrDevice *dev, *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
NDIS_STATUS result = NDIS_STATUS_SUCCESS;
DBGOUT((TEXT("MiniportReset(0x%x)"), (UINT)MiniportAdapterContext));
/*
* Verify that the context is not bogus.
* I've seen bad contexts getting passed in when the system gets corrupted.
*/
for (dev = firstIrDevice; dev && (dev != thisDev); dev = dev->next){}
if (!dev){
DBGERR((TEXT("Bad context in MiniportReset")));
return NDIS_STATUS_FAILURE;
}
DoClose(thisDev);
CloseDevice(thisDev);
/*** change start ***/
if(OpenDevice(thisDev) && DoOpen(thisDev)){
*AddressingReset = TRUE;
result = NDIS_STATUS_SUCCESS;
}else{
*AddressingReset = FALSE;
result = NDIS_STATUS_HARD_ERRORS;
}
/*** change end ***/
DBGOUT((TEXT("MiniportReset done.")));
return result;
}
#ifdef UNDER_CE
//
// NOTE: Under WinCE, only MiniportSend will ever be called. On NT and 98,
// MiniportSend is the serial IR handler for SendPacketsHandler.
// SendCommPacket is the SIR handler and MiniportSend handles both
// the SIR and FIR routing.
//
NDIS_STATUS
SendCommPacket(
IN IrDevice *thisDev,
IN PNDIS_PACKET Packet
)
{
NDIS_STATUS result;
DBGOUT((TEXT("==>SendCommPacket(thisDev=0x%x)"), (UINT)thisDev));
DEBUGMSG(DBG_TRACE_TX, (TEXT("+SendCommPacket(pkt = 0x%x)\r\n"), Packet));
/*
* If we have temporarily lost access to the hardware, don't queue up any sends.
* Just pretend everything is going smoothly until we regain access to the hw.
*/
if (thisDev->resourcesReleased){
return NDIS_STATUS_SUCCESS;
}
DBGPKT((TEXT("Queueing send packet 0x%x."), (UINT)Packet));
//
// Use MiniportReserved as a LIST_ENTRY. First check so no one
// ever changes the size of these the wrong way.
//
ASSERT(sizeof(Packet->MiniportReserved)>=sizeof(LIST_ENTRY));
NdisInterlockedInsertTailList(&thisDev->SendQueue,
(PLIST_ENTRY)Packet->MiniportReserved,
&thisDev->QueueLock);
/*
* Try to send the first queued send packet.
*/
if (IsCommReadyForTransmit(thisDev)){
BOOLEAN firstBufIsPending;
firstBufIsPending = (BOOLEAN)(Packet != HEAD_SEND_PACKET(thisDev));
result = PortReadyForWrite(thisDev, firstBufIsPending);
DEBUGMSG(DBG_TRACE_TX, (TEXT("PortReadyForWrite returned 0x%x\r\n"),
result));
}
else {
DEBUGMSG(DBG_TRACE_TX, (TEXT("SendCommPacket: NDIS_STATUS_PENDING\r\n")));
result = NDIS_STATUS_PENDING;
}
DBGOUT((TEXT("<==SendCommPacket [%s]"), DBG_NDIS_RESULT_STR(result)));
return result;
}
/*
*************************************************************************
* MiniportSend
*************************************************************************
*
*
* Transmits a packet through the network interface card onto the medium.
*
*
*
*/
NDIS_STATUS MiniportSend(
IN NDIS_HANDLE MiniportAdapterContext,
IN PNDIS_PACKET Packet,
IN UINT Flags
)
{
NDIS_STATUS stat;
BOOLEAN TxWasActive, DmaPend;
IrDevice *thisDev = CONTEXT_TO_DEV(MiniportAdapterContext);
LOG(TEXT("==> MiniportSend"), 0);
DBGOUT((TEXT("==> MiniportSend(0x%x, pakcet = 0x%x)"),
(UINT)MiniportAdapterContext, Packet));
DEBUGMSG(DBG_TX | DBG_TRACE_TX,
(TEXT("+MiniportSend(pkt = 0x%x)\r\n"), Packet));
//
// If we have temporarily lost access to the hardware, don't queue up any sends.
// Just pretend everything is going smoothly until we regain access to the hw.
//
if (thisDev->resourcesReleased){
ASSERT(FALSE);
#ifdef OUTMSG
RETAILMSG(1, (TEXT("ERROR resourcesReleased in MiniportSend\r\n")));
#endif
return (NDIS_STATUS_FAILURE);
}
IRFIR_LOG_NDIS_PACKET(LOG_TXFRAME, Packet);
if (thisDev->currentSpeed > MAX_SIR_SPEED)
{
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend => MIR | FIR\r\n")));
NdisAcquireSpinLock(&thisDev->QueueLock);
TxWasActive = (thisDev->AdapterState==ADAPTER_TX);
thisDev->AdapterState = ADAPTER_TX;
NDIS_SET_PACKET_STATUS(Packet, NDIS_STATUS_PENDING);
InsertTailList(&thisDev->SendQueue,
(PLIST_ENTRY)Packet->MiniportReserved);
NdisReleaseSpinLock(&thisDev->QueueLock);
if(READ_REGISTER_UCHAR(pISIRR) & CC_FIR_ISIRR_SIRMOD){
DmaPend = FALSE;
}else{
WRITE_REGISTER_UCHAR(pIMSTCR, (READ_REGISTER_UCHAR(pIMSTCR) & CC_FIR_IMSTCR_RST_BANK)|CC_FIR_IMSTCR_BANK0 );
DmaPend = (BOOLEAN)(READ_REGISTER_UCHAR(pIRSR) & CC_FIR_IRSR_RFEM);
}
if (!TxWasActive)
{
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend => TX idle, do work...\r\n")));
//
// Complete the Receive DMA before starting the next
// set of transmits.
//
NdisMCompleteDmaTransfer(&stat, thisDev->DmaHandle,
thisDev->rcvDmaBuffer,
thisDev->rcvDmaOffset,
thisDev->rcvDmaSize, FALSE);
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend: CompleteDma returned 0x%x\r\n"),
stat));
if (!RegStats.RxWindow) {
LOG(TEXT("SendPacketsHandler - RxWindow has zero value"), 0);
DBGOUT((TEXT("SendPacketsHandler - RxWindow has zero value")));
}
if (RegStats.RxDPC_Window > 1) {
RegStats.RxDPC_G1_Count++;
}
RegStats.RxWindowMax = MAX(RegStats.RxWindowMax, RegStats.RxWindow);
RegStats.RxWindow = 0;
RegStats.RxDPC_WindowMax = MAX(RegStats.RxDPC_WindowMax, RegStats.RxDPC_Window);
RegStats.RxDPC_Window = 0;
//
// Use DMA swap bit to switch to DMA to Transmit.
//
//
// Switch on the DMA interrupt to decide when
// transmission is complete.
//
thisDev->IntMask = 0x14;
SetCOMInterrupts(thisDev, TRUE);
//
// Kick off the first transmit.
//
FIR_MegaSend(thisDev);
}
else
{
DEBUGMSG(DBG_TRACE_TX, (TEXT("MSend: TX active, queue packet\r\n")));
}
stat = NDIS_STATUS_PENDING;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -