📄 nsc.c
字号:
if (retStat != NDIS_STATUS_SUCCESS){
DBGERR(("NdisMRegisterIoPortRange config failed"));
thisDev->portInfo.ConfigIoBaseAddr=NULL;
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
}
NdisMSleep(20);
//
// Set to Non-Extended mode
//
NSC_WriteBankReg(thisDev->portInfo.ioBase, 2, 2, 0x02);
//
// set to bank 0
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+LCR_BSR_OFFSET, 03);
//
// mask all ints, before attaching interrupt
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+INT_ENABLE_REG_OFFSET, 0);
/*
* Register an interrupt with NDIS.
*/
retStat = NdisMRegisterInterrupt( (PNDIS_MINIPORT_INTERRUPT)&thisDev->interruptObj,
NdisAdapterHandle,
thisDev->portInfo.irq,
thisDev->portInfo.irq,
TRUE, // want ISR
TRUE, // MUST share interrupts
NdisInterruptLatched
);
if (retStat != NDIS_STATUS_SUCCESS){
DBGERR(("NdisMRegisterInterrupt failed"));
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
thisDev->InterruptRegistered=TRUE;
{
LONG VerifyTries=5;
while (VerifyTries > 0) {
if (VerifyHardware(thisDev)) {
break;
}
#if DBG
DbgPrint("NSCIRDA: VerifiyHardware() failed, trying again, tries left=%d\n",VerifyTries);
#endif
VerifyTries--;
}
if ( VerifyTries == 0) {
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
}
/*
* Open COMM communication channel.
* This will let the dongle driver update its capabilities from their default values.
*/
if (!DoOpen(thisDev)){
DBGERR(("DoOpen failed"));
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
/*
* Do special NSC setup
* (do this after comport resources, like read buf, have been allocated).
*/
if (!NSC_Setup(thisDev)){
DBGERR(("NSC_Setup failed"));
NSC_Shutdown(thisDev);
result = NDIS_STATUS_FAILURE;
goto _initDone;
}
_initDone:
if (result == NDIS_STATUS_SUCCESS){
/*
* Add this device object to the beginning of our global list.
*/
thisDev->hardwareStatus = NdisHardwareStatusReady;
DBGOUT(("MiniportInitialize succeeded"));
return result;
}
//
// init failed, release the resources
//
if (thisDev->InterruptRegistered) {
NdisMDeregisterInterrupt(&thisDev->interruptObj);
thisDev->InterruptRegistered=FALSE;
}
if (thisDev->portInfo.ioBase != NULL) {
NdisMDeregisterIoPortRange(
thisDev->ndisAdapterHandle,
thisDev->portInfo.ioBasePhys,
((thisDev->CardType==PUMA108)?16:8),
(PVOID)thisDev->portInfo.ioBase
);
thisDev->portInfo.ioBase=NULL;
}
if (thisDev->portInfo.ConfigIoBaseAddr != NULL) {
NdisMDeregisterIoPortRange(
thisDev->ndisAdapterHandle,
thisDev->portInfo.ConfigIoBasePhysAddr,
2,
(PVOID)thisDev->portInfo.ConfigIoBaseAddr
);
thisDev->portInfo.ConfigIoBaseAddr=NULL;
}
if (thisDev){
FreeDevice(thisDev);
}
DBGOUT(("MiniportInitialize failed"));
return result;
}
BOOLEAN
VerifyHardware(
IrDevice *thisDev
)
{
UCHAR TempValue;
LONG MilliSecondsToWait=500;
NdisMSleep(20);
//
// set to bank 0
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+LCR_BSR_OFFSET, 03);
//
// mask all ints, before attaching interrupt
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+INT_ENABLE_REG_OFFSET, 0);
NdisRawReadPortUchar(thisDev->portInfo.ioBase+INT_ENABLE_REG_OFFSET,&TempValue);
if (TempValue != 0) {
#if DBG
DbgPrint("NSCIRDA: After masking interrupts IER was not zero %x, base= %x\n",TempValue,thisDev->portInfo.ioBase);
#endif
return FALSE;
}
//
// reset the fifo's and enable the fifos
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+INT_ID_AND_FIFO_CNTRL_REG_OFFSET, 0x7);
//
// read the interrupt ident reg, to see if the fifo's enabled
//
NdisRawReadPortUchar(thisDev->portInfo.ioBase+INT_ID_AND_FIFO_CNTRL_REG_OFFSET,&TempValue);
if ((TempValue & 0xc0) != 0xc0) {
#if DBG
DbgPrint("NSCIRDA: Fifo's not enabled in iir %x, base= %x\n",TempValue,thisDev->portInfo.ioBase);
#endif
return FALSE;
}
//
// bring up DTR and RTS, turn on the out pins
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+MODEM_CONTROL_REG_OFFSET, 0xf);
thisDev->GotTestInterrupt=FALSE;
thisDev->TestingInterrupt=TRUE;
//
// unmask the transmit holding register so an interrupt will be generated
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+INT_ENABLE_REG_OFFSET, 2);
while ((thisDev->GotTestInterrupt == FALSE) && (MilliSecondsToWait > 0)) {
NdisMSleep(1000);
MilliSecondsToWait--;
}
#if DBG
if (!thisDev->GotTestInterrupt) {
NdisRawReadPortUchar(thisDev->portInfo.ioBase+INT_ID_AND_FIFO_CNTRL_REG_OFFSET,&TempValue);
DbgPrint("NSCIRDA: Did not get interrupt while initializing, ier-%x, base= %x\n",TempValue,thisDev->portInfo.ioBase);
}
#endif
//
// mask all ints again;
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+INT_ENABLE_REG_OFFSET, 0);
thisDev->TestingInterrupt=FALSE;
return thisDev->GotTestInterrupt;
}
/*
*************************************************************************
* QueueReceivePacket
*************************************************************************
*
*
*
*
*/
VOID QueueReceivePacket(IrDevice *thisDev, PUCHAR data, UINT dataLen, BOOLEAN IsFIR)
{
rcvBuffer *rcvBuf = NULL;
PLIST_ENTRY ListEntry;
/*
* Note: We cannot use a spinlock to protect the rcv buffer structures
* in an ISR. This is ok, since we used a sync-with-isr function
* the the deferred callback routine to access the rcv buffers.
*/
LOG("==> QueueReceivePacket");
DBGOUT(("==> QueueReceivePacket(0x%x, 0x%lx, 0x%x)",
thisDev, data, dataLen));
LOG("QueueReceivePacket, len: %d ", dataLen);
if (!IsFIR)
{
// This function is called inside the ISR during SIR mode.
if (IsListEmpty(&thisDev->rcvBufFree))
{
ListEntry = NULL;
}
else
{
ListEntry = RemoveHeadList(&thisDev->rcvBufFree);
}
}
else
{
ListEntry = NDISSynchronizedRemoveHeadList(&thisDev->rcvBufFree,
&thisDev->interruptObj);
}
if (ListEntry)
{
rcvBuf = CONTAINING_RECORD(ListEntry,
rcvBuffer,
listEntry);
if (IsFIR)
{
LOG_Data(thisDev, data);
}
}
if (rcvBuf){
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("<== QueueReceivePacket");
DBGOUT(("<== 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);
if (thisDev->TestingInterrupt) {
//
// we are testing to make sure the interrupt works
//
UCHAR TempValue;
//
// Read the interrupt identification register
//
NdisRawReadPortUchar(thisDev->portInfo.ioBase+INT_ID_AND_FIFO_CNTRL_REG_OFFSET,&TempValue);
//
// if the low bit is clear then an interrupt is pending
//
if ((TempValue & 1) == 0) {
//
// inform the test code that we got the interrupt
//
thisDev->GotTestInterrupt=TRUE;
thisDev->TestingInterrupt=FALSE;
//
// mask all ints again
//
NdisRawWritePortUchar(thisDev->portInfo.ioBase+INT_ENABLE_REG_OFFSET, 0);
DBGOUT(("NSCIRDA: Got test interrupt %x\n",TempValue))
*InterruptRecognized=TRUE;
*QueueMiniportHandleInterrupt=FALSE;
return;
}
//
// seems that our uart did not generate this interrupt
//
*InterruptRecognized=FALSE;
*QueueMiniportHandleInterrupt=FALSE;
return;
}
//LOG("==> MiniportISR", ++thisDev->interruptCount);
//DBGOUT(("==> MiniportISR(0x%x), interrupt #%d)", (UINT)thisDev,
// thisDev->interruptCount));
#if DBG
{
UCHAR TempVal;
//
// This code assumes that bank 0 is current, we will make sure of that
//
NdisRawReadPortUchar(thisDev->portInfo.ioBase+LCR_BSR_OFFSET, &TempVal);
ASSERT((TempVal & BKSE) == 0);
}
#endif
/*
* Service the interrupt.
*/
if (thisDev->currentSpeed > MAX_SIR_SPEED){
NSC_FIR_ISR(thisDev, InterruptRecognized,
QueueMiniportHandleInterrupt);
}
else {
COM_ISR(thisDev, InterruptRecognized,
QueueMiniportHandleInterrupt);
}
LOG("<== MiniportISR");
DBGOUT(("<== MiniportISR"));
}
/*
*************************************************************************
* MiniportReset
*************************************************************************
*
*
* MiniportReset issues a hardware reset to the network interface card.
* The miniport driver also resets its software state.
*
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -