⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nsc.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
        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 + -