Пример #1
0
NTSTATUS
NICStartSend(
    __in  PFDO_DATA  FdoData,
    __in  PMP_TCB    pMpTcb
    )
/*++
Routine Description:

    Issue a send command to the NIC
    Assumption: Send spinlock has been acquired

Arguments:

    FdoData     Pointer to our FdoData
    pMpTcb      Pointer to MP_TCB

Return Value:

    NTSTATUS code

--*/
{
    NTSTATUS     status;

    DebugPrint(TRACE, DBG_WRITE, "--> NICStartSend\n");

    //
    // If the transmit unit is idle (very first transmit) then we must
    // setup the general pointer and issue a full CU-start
    //
    if (FdoData->TransmitIdle)
    {

        DebugPrint(TRACE, DBG_WRITE, "CU is idle -- First TCB added to Active List\n");

        //
        // Wait for the SCB to clear before we set the general pointer
        //
        if (!WaitScb(FdoData))
        {
            DebugPrint(ERROR, DBG_WRITE, "NICStartSend -- WaitScb returned error\n");
            status = STATUS_DEVICE_DATA_ERROR;
            goto exit;
        }

        //
        // Don't try to start the transmitter if the command unit is not
        // idle ((not idle) == (Cu-Suspended or Cu-Active)).
        //
        if ((FdoData->CSRAddress->ScbStatus & SCB_CUS_MASK) != SCB_CUS_IDLE)
        {
            DebugPrint(ERROR, DBG_WRITE, "FdoData = %p, CU Not IDLE\n", FdoData);
            MP_SET_HARDWARE_ERROR(FdoData);
            KeStallExecutionProcessor(25);
        }

        FdoData->CSRAddress->ScbGeneralPointer = pMpTcb->HwTcbPhys;

        status = D100IssueScbCommand(FdoData, SCB_CUC_START, FALSE);

        FdoData->TransmitIdle = FALSE;
        FdoData->ResumeWait = TRUE;
    }
    else
    {
        //
        // If the command unit has already been started, then append this
        // TCB onto the end of the transmit chain, and issue a CU-Resume.
        //
        DebugPrint(LOUD, DBG_WRITE, "adding TCB to Active chain\n");

        //
        // Clear the suspend bit on the previous packet.
        //
        pMpTcb->PrevHwTcb->TxCbHeader.CbCommand &= ~CB_S_BIT;

        //
        // Issue a CU-Resume command to the device.  We only need to do a
        // WaitScb if the last command was NOT a RESUME.
        //
        status = D100IssueScbCommand(FdoData, SCB_CUC_RESUME, FdoData->ResumeWait);
    }

    exit:

    DebugPrint(TRACE, DBG_WRITE, "<-- NICStartSend\n");

    return status;
}
Пример #2
0
NTSTATUS
MPSetUpFilterCB(
    __in PFDO_DATA FdoData
    )
{
    NTSTATUS         status = STATUS_SUCCESS;
    PCB_HEADER_STRUC    NonTxCmdBlockHdr = (PCB_HEADER_STRUC)FdoData->NonTxCmdBlock;
    PFILTER_CB_STRUC    pFilterCb = (PFILTER_CB_STRUC)NonTxCmdBlockHdr;
    ULONG               Curr = 0;
    ULONG               Next = 0;
    PLIST_ENTRY         pPatternEntry = ListNext(&FdoData->PoMgmt.PatternList) ;

    DebugPrint(TRACE, DBG_POWER, "--> MPSetUpFilterCB\n");

    RtlZeroMemory (pFilterCb, sizeof(*pFilterCb));

    // Individual Address Setup
    NonTxCmdBlockHdr->CbStatus = 0;
    NonTxCmdBlockHdr->CbCommand = CB_EL_BIT | CB_LOAD_PROG_FILTER;
    NonTxCmdBlockHdr->CbLinkPointer = DRIVER_NULL;




    // go through each filter in the list.

    while (pPatternEntry != (&FdoData->PoMgmt.PatternList))
    {
        PMP_WAKE_PATTERN            pWakeUpPattern = NULL;

        // initialize local variables
        pWakeUpPattern = CONTAINING_RECORD(pPatternEntry, MP_WAKE_PATTERN, linkListEntry);

        // increment the iterator
        pPatternEntry = ListNext (pPatternEntry);

        // Update the Curr Array Pointer
        Curr = Next;

        // Create the Programmable filter for this device.
        MPCreateProgrammableFilter (pWakeUpPattern , &pFilterCb->Pattern[Curr], &Next);

        if (Next >=16)
        {
            break;
        }

    }

    {
        // Set the EL bit on the last pattern
        PUCHAR pLastPattern = (PUCHAR) &pFilterCb->Pattern[Curr];

        // Get to bit 31
        pLastPattern[3] |= CB_FILTER_EL ;


    }

    ASSERT(FdoData->CSRAddress->ScbCommandLow == 0);

    //  Wait for the CU to Idle before giving it this command
    if(!WaitScb(FdoData))
    {
        status = STATUS_DEVICE_DATA_ERROR;
    }

    DebugPrint(TRACE, DBG_POWER, "<-- MPSetUpFilterCB\n");

    return status;


}
Пример #3
0
NTSTATUS
NICSetMulticastList(
    PFDO_DATA  FdoData
    )
/*++
Routine Description:

    This routine will set up the FdoData for a specified multicast address list

Arguments:

    FdoData     Pointer to our FdoData

Return Value:


--*/
{
    NTSTATUS        status;
    PUCHAR          McAddress;
    UINT            i, j;
    BOOLEAN         bResult;

    DebugPrint(TRACE, DBG_IOCTLS, "--> NICSetMulticastList\n");

    //
    // Setup the command block for the multicast command.
    //
    for (i = 0; i < FdoData->MCAddressCount; i++)
    {
        DebugPrint(TRACE, DBG_IOCTLS, "MC(%d) = %02x-%02x-%02x-%02x-%02x-%02x\n",
            i,
            FdoData->MCList[i][0],
            FdoData->MCList[i][1],
            FdoData->MCList[i][2],
            FdoData->MCList[i][3],
            FdoData->MCList[i][4],
            FdoData->MCList[i][5]);

        McAddress = &FdoData->NonTxCmdBlock->NonTxCb.Multicast.McAddress[i*ETHERNET_ADDRESS_LENGTH];

        for (j = 0; j < ETH_LENGTH_OF_ADDRESS; j++)
            *(McAddress++) = FdoData->MCList[i][j];
    }

    FdoData->NonTxCmdBlock->NonTxCb.Multicast.McCount =
        (USHORT)(FdoData->MCAddressCount * ETH_LENGTH_OF_ADDRESS);
    ((PCB_HEADER_STRUC)FdoData->NonTxCmdBlock)->CbStatus = 0;
    ((PCB_HEADER_STRUC)FdoData->NonTxCmdBlock)->CbCommand = CB_MULTICAST;

    //
    // Wait for the SCB to clear before we check the CU status.
    //
    if (!WaitScb(FdoData))
    {
        status = STATUS_DEVICE_DATA_ERROR;
        MP_EXIT;
    }

    //
    // If we have issued any transmits, then the CU will either be active, or
    // in the suspended state.  If the CU is active, then we wait for it to be
    // suspended.
    //
    if (FdoData->TransmitIdle == FALSE)
    {
        //
        // Wait for suspended state
        //
        MP_STALL_AND_WAIT((FdoData->CSRAddress->ScbStatus & SCB_CUS_MASK) != SCB_CUS_ACTIVE, 5000, bResult);
        if (!bResult)
        {
            MP_SET_HARDWARE_ERROR(FdoData);
            status = STATUS_DEVICE_DATA_ERROR;
        }

        //
        // Restore the transmit software flags.  After the multicast command is
        // issued, the command unit will be idle, because the EL bit will be
        // set in the multicast commmand block.
        //
        FdoData->TransmitIdle = TRUE;
        FdoData->ResumeWait = TRUE;
    }

    //
    // Update the command list pointer.
    //
    FdoData->CSRAddress->ScbGeneralPointer = FdoData->NonTxCmdBlockPhys;

    //
    // Submit the multicast command to the FdoData and wait for it to complete.
    //
    status = D100SubmitCommandBlockAndWait(FdoData);
    if (status != STATUS_SUCCESS)
    {
        status = STATUS_DEVICE_NOT_READY;
    }

    exit:

    DebugPrint(TRACE, DBG_IOCTLS, "<-- NICSetMulticastList, status=%x\n", status);

    return(status);

}
Пример #4
0
NTSTATUS NICSetPacketFilter(
    __in PFDO_DATA    FdoData,
    __in ULONG        PacketFilter
    )
/*++
Routine Description:

    This routine will set up the FdoData so that it accepts packets
    that match the specified packet filter.  The only filter bits
    that can truly be toggled are for broadcast and promiscuous

Arguments:

    FdoData         Pointer to our FdoData
    PacketFilter    The new packet filter

Return Value:


--*/
{
    NTSTATUS        status = STATUS_SUCCESS;
    UCHAR           NewParameterField;
    UINT            i;
    BOOLEAN         bResult;

    DebugPrint(TRACE, DBG_IOCTLS, "--> NICSetPacketFilter, PacketFilter=%08x\n", PacketFilter);

    //
    // Need to enable or disable broadcast and promiscuous support depending
    // on the new filter
    //
    NewParameterField = CB_557_CFIG_DEFAULT_PARM15;

    if (PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
    {
        NewParameterField &= ~CB_CFIG_BROADCAST_DIS;
    }
    else
    {
        NewParameterField |= CB_CFIG_BROADCAST_DIS;
    }

    if (PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
    {
        NewParameterField |= CB_CFIG_PROMISCUOUS;
    }
    else
    {
        NewParameterField &= ~CB_CFIG_PROMISCUOUS;
    }

    do
    {
        if ((FdoData->OldParameterField == NewParameterField ) &&
            !(PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST))
        {
            break;
        }

        //
        // Only need to do something to the HW if the filter bits have changed.
        //
        FdoData->OldParameterField = NewParameterField;
        ((PCB_HEADER_STRUC)FdoData->NonTxCmdBlock)->CbCommand = CB_CONFIGURE;
        ((PCB_HEADER_STRUC)FdoData->NonTxCmdBlock)->CbStatus = 0;
        ((PCB_HEADER_STRUC)FdoData->NonTxCmdBlock)->CbLinkPointer = DRIVER_NULL;

        //
        // First fill in the static (end user can't change) config bytes
        //
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[0] = CB_557_CFIG_DEFAULT_PARM0;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[2] = CB_557_CFIG_DEFAULT_PARM2;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] = CB_557_CFIG_DEFAULT_PARM3;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[6] = CB_557_CFIG_DEFAULT_PARM6;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[9] = CB_557_CFIG_DEFAULT_PARM9;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[10] = CB_557_CFIG_DEFAULT_PARM10;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[11] = CB_557_CFIG_DEFAULT_PARM11;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[12] = CB_557_CFIG_DEFAULT_PARM12;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[13] = CB_557_CFIG_DEFAULT_PARM13;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[14] = CB_557_CFIG_DEFAULT_PARM14;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[16] = CB_557_CFIG_DEFAULT_PARM16;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[17] = CB_557_CFIG_DEFAULT_PARM17;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[18] = CB_557_CFIG_DEFAULT_PARM18;
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[20] = CB_557_CFIG_DEFAULT_PARM20;

        //
        // Set the Tx underrun retries
        //
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[7] =
            (UCHAR) (CB_557_CFIG_DEFAULT_PARM7 | (FdoData->AiUnderrunRetry << 1));

        //
        // Set the Tx and Rx Fifo limits
        //
        FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[1] =
            (UCHAR) ((FdoData->AiTxFifo << 4) | FdoData->AiRxFifo);

        //
        // set the MWI enable bit if needed
        //
        if (FdoData->MWIEnable)
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[3] |= CB_CFIG_B3_MWI_ENABLE;

        //
        // Set the Tx and Rx DMA maximum byte count fields.
        //
        if ((FdoData->AiRxDmaCount) || (FdoData->AiTxDmaCount))
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] =
                FdoData->AiRxDmaCount;
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] =
                (UCHAR) (FdoData->AiTxDmaCount | CB_CFIG_DMBC_EN);
        }
        else
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[4] =
                CB_557_CFIG_DEFAULT_PARM4;
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[5] =
                CB_557_CFIG_DEFAULT_PARM5;
        }

        //
        // Setup for MII or 503 operation.  The CRS+CDT bit should only be
        // set when operating in 503 mode.
        //
        if (FdoData->PhyAddress == 32)
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
                (CB_557_CFIG_DEFAULT_PARM8 & (~CB_CFIG_503_MII));
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
                (UCHAR) (NewParameterField | CB_CFIG_CRS_OR_CDT);
        }
        else
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[8] =
                (CB_557_CFIG_DEFAULT_PARM8 | CB_CFIG_503_MII);
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[15] =
                (UCHAR) (NewParameterField & (~CB_CFIG_CRS_OR_CDT));
        }

        //
        // Setup Full duplex stuff
        //

        //
        // If forced to half duplex
        //
        if (FdoData->AiForceDpx == 1)
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
                (CB_557_CFIG_DEFAULT_PARM19 &
                (~(CB_CFIG_FORCE_FDX| CB_CFIG_FDX_ENABLE)));
        }
        //
        // If forced to full duplex
        //
        else if (FdoData->AiForceDpx == 2)
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
                (CB_557_CFIG_DEFAULT_PARM19 | CB_CFIG_FORCE_FDX);
        }
        //
        // If auto-duplex
        //
        else
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[19] =
                                                CB_557_CFIG_DEFAULT_PARM19;
        }

        //
        // if multicast all is being turned on, set the bit
        //
        if (PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[21] =
                                 (CB_557_CFIG_DEFAULT_PARM21 | CB_CFIG_MULTICAST_ALL);
        }
        else
        {
            FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[21] =
                                                CB_557_CFIG_DEFAULT_PARM21;
        }


        //
        // Wait for the SCB to clear before we check the CU status.
        //
        if (!WaitScb(FdoData))
        {
            status = STATUS_DEVICE_DATA_ERROR;
            break;
        }

        //
        // If we have issued any transmits, then the CU will either be active,
        // or in the suspended state.  If the CU is active, then we wait for
        // it to be suspended.
        //
        if (FdoData->TransmitIdle == FALSE)
        {
            //
            // Wait for suspended state
            //
            MP_STALL_AND_WAIT((FdoData->CSRAddress->ScbStatus & SCB_CUS_MASK) != SCB_CUS_ACTIVE, 5000, bResult);
            if (!bResult)
            {
                MP_SET_HARDWARE_ERROR(FdoData);
                status = STATUS_DEVICE_DATA_ERROR;
                break;
            }

            //
            // Check the current status of the receive unit
            //
            if ((FdoData->CSRAddress->ScbStatus & SCB_RUS_MASK) != SCB_RUS_IDLE)
            {
                // Issue an RU abort.  Since an interrupt will be issued, the
                // RU will be started by the DPC.
                status = D100IssueScbCommand(FdoData, SCB_RUC_ABORT, TRUE);
                if (status != STATUS_SUCCESS)
                {
                    break;
                }
            }

            if (!WaitScb(FdoData))
            {
                status = STATUS_DEVICE_DATA_ERROR;
                break;
            }

            //
            // Restore the transmit software flags.  After the multicast
            // command is issued, the command unit will be idle, because the
            // EL bit will be set in the multicast commmand block.
            //
            FdoData->TransmitIdle = TRUE;
            FdoData->ResumeWait = TRUE;
        }

        //
        // Display config info
        //
        DebugPrint(TRACE, DBG_IOCTLS, "Re-Issuing Configure command for filter change\n");
        DebugPrint(TRACE, DBG_IOCTLS, "Config Block at virt addr %p, phys address %x\n",
            &((PCB_HEADER_STRUC)FdoData->NonTxCmdBlock)->CbStatus, FdoData->NonTxCmdBlockPhys);

        for (i = 0; i < CB_CFIG_BYTE_COUNT; i++)
            DebugPrint(LOUD, DBG_IOCTLS, "  Config byte %x = %.2x\n", i, FdoData->NonTxCmdBlock->NonTxCb.Config.ConfigBytes[i]);

        //
        // Submit the configure command to the chip, and wait for it to complete.
        //
        FdoData->CSRAddress->ScbGeneralPointer = FdoData->NonTxCmdBlockPhys;
        status = D100SubmitCommandBlockAndWait(FdoData);
        if (status != STATUS_SUCCESS)
        {
            status = STATUS_DEVICE_NOT_READY;
        }

    } while (FALSE);

    DebugPrint(TRACE, DBG_IOCTLS, "<-- NICSetPacketFilter, Status=%x\n", status);

    return(status);
}
Пример #5
0
NTSTATUS
NICStartRecv(
    IN  PFDO_DATA  FdoData
    )
/*++
Routine Description:

    Start the receive unit if it's not in a ready state

    Assumption: This function is called with the Rcv SPINLOCK held.

Arguments:

    FdoData     Pointer to our FdoData

Return Value:

    NT Status code

--*/
{
    PMP_RFD         pMpRfd;
    NTSTATUS        status;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "---> NICStartRecv\n");

    //
    // If the receiver is ready, then don't try to restart.
    //
    if (NIC_IS_RECV_READY(FdoData))
    {
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Receive unit already active\n");
        return STATUS_SUCCESS;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Re-start receive unit...\n");
    ASSERT(!IsListEmpty(&FdoData->RecvList));

    //
    // Get the MP_RFD head
    //
    pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList);

    //
    // If more packets are received, clean up RFD chain again
    //
    if (NIC_RFD_GET_STATUS(pMpRfd->HwRfd))
    {
        NICHandleRecvInterrupt(FdoData);
        ASSERT(!IsListEmpty(&FdoData->RecvList));

        //
        // Get the new MP_RFD head
        //
        pMpRfd = (PMP_RFD)GetListHeadEntry(&FdoData->RecvList);
    }

    //
    // Wait for the SCB to clear before we set the general pointer
    //
    if (!WaitScb(FdoData))
    {
        status = STATUS_DEVICE_DATA_ERROR;
        goto exit;
    }

    if (FdoData->DevicePowerState > PowerDeviceD0)
    {
        status = STATUS_DEVICE_DATA_ERROR;
        goto exit;
    }
    //
    // Set the SCB General Pointer to point the current Rfd
    //
    FdoData->CSRAddress->ScbGeneralPointer = pMpRfd->HwRfdPhys;

    //
    // Issue the SCB RU start command
    //
    status = D100IssueScbCommand(FdoData, SCB_RUC_START, FALSE);
    if (status == STATUS_SUCCESS)
    {
        // wait for the command to be accepted
        if (!WaitScb(FdoData))
        {
            status = STATUS_DEVICE_DATA_ERROR;
        }
    }

    exit:

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<--- NICStartRecv, Status=%x\n", status);
    return status;
}