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

📄 ncdevice.c

📁 CE下 NET2778 NDIS Drivers, 在每个平台上都可以使用
💻 C
📖 第 1 页 / 共 5 页
字号:
{   // Handle Setup Packet Interrupt
    // Upon ACKing a Setup Packet, the NET2272 will:
    //  - Set Setup Packet Interrupt (which is how we got here)
    //  - Set EP0 Endpoint Direction to match bit 7 of bmRequestType
    //  - Set EP0 Endpoint Toggle (Toggle always set for first Data Phase packet)
    //  - Set EP0 Control Status Phase Handshake (must be cleared by firmware 
    //    to allow the Status Phase to complete)
    //  - Clear EP0 Endpoint Halt (guarantees the Setup Request will be ACK'd)
    //  - Clear EP0 data buffers (resets pointers so buffers appear empty)
    // See USB 2.0: 8.5.3 for details about setup packets and control transfers

    // Setup to interrupt on the start of the Status Phase, which is:
    //  - OUT token for Control Read or "no-data" request (wLength is zero)
    //  - IN token for Control Write
    NCSTATUS NcStatus;

    NETCHIP_WRITE(IRQSTAT1, 1<<CONTROL_STATUS_INTERRUPT);
    NETCHIP_WRITE(IRQENB1, NETCHIP_READ(IRQENB1) | (1<<CONTROL_STATUS_INTERRUPT_ENABLE));

    // Ensure Control Read pre-validation setting is beyond maximum size
    //  - Control Writes can leave non-zero values in EP_TRANSFER. If
    //    an EP0 transfer following the Control Write is a Control Read, 
    //    the NET2272 sees the non-zero EP_TRANSFER as an unexpected 
    //    pre-validation count. 
    //  - Setting EP_TRANSFER beyond the maximum EP0 transfer size ensures
    //    the pre-validation count cannot cause an unexpected validatation
    NETCHIP_WRITE(PAGESEL, EP0);
    NETCHIP_WRITE(EP_TRANSFER2, 0xff);
    NETCHIP_WRITE(EP_TRANSFER1, 0xff);
    NETCHIP_WRITE(EP_TRANSFER0, 0xff);

    // Get a copy of the host's eight-byte Setup Packet
    BMREQUESTTYPE = NETCHIP_READ(SETUP0);
    BREQUEST = NETCHIP_READ(SETUP1);
    WVALUE_LO = NETCHIP_READ(SETUP2);
    WVALUE_HI = NETCHIP_READ(SETUP3);
    WINDEX_LO = NETCHIP_READ(SETUP4);
    WINDEX_HI = NETCHIP_READ(SETUP5);
    WLENGTH_LO = NETCHIP_READ(SETUP6); 
    WLENGTH_HI = NETCHIP_READ(SETUP7);

    HISTO(DEFAULT_HISTORY, "SPk1", BMREQUESTTYPE, BREQUEST, WVALUE);
    HISTO(DEFAULT_HISTORY, "SPk2", WINDEX, WLENGTH, 0);
    NCDEBUG(SetupPacket_Msg[0] = '\0';)
    NCDEBUG(SetupPacket_PrintVolume = VOLUME_MEDIUM;)

    // Allow another Setup Packet Interrupt
    NETCHIP_WRITE(IRQSTAT0, 1<<SETUP_PACKET_INTERRUPT);

    // Parse host's eight-byte setup request:
    //  - The client gets the first opportunity to handle the request. If
    //    the client returns Unsuccessful, the API calls its Standard USB Request 
    //    handler. Endpoint Zero is stalled if the request is not handled by either.
    //  - Request handlers may optionally start a data phase for a control 
    //    transfer (USB Spec: 8.5.3). The client (or the app) effectively (or
    //    literally) calls the API Endpoint Transfer routine to specify a transfer
    //  - The API uses Endpoint Zero's Default Transfer Object for the data
    //    phase of control transfers for standard requests. If the client also
    //    performs data phase transfers, it should specify a separate Transfer 
    //    Object before starting an endpoint zero transfer
    //  - Standard requests are listed in USB Spec section 9.4
    //  - Non-standard requests are vendor or class specific requests. See USB 
    //    spec 9.3.1 and class documents (www.usb.org)
    PrivDeviceObject->EventCode = NC_DEVICE_EVENT_DEVICE_REQUEST;
    NcStatus = PrivDeviceObject->DeviceEventHandler(PrivDeviceObject);

    // Preserve client's Transfer Object between possible Standard Requests
    //  - The API's standard request handlers use private Transfer Objects, but 
    //    the client's *reference* to its Transfer Object must be preserved!
    //  - Even if requests alternate between standard (handled by the API) and non-
    //    standard (handled by client) the client will not require extra considerations
    ClientTransferZero = PrivDeviceObject->EndpointZero->Transfer;

    HISTO(DEFAULT_HISTORY, "Clie", NcStatus, 0, 0);
    if (NcStatus != NCSTATUS_SUCCESS)
    {   // Anything other than Success indicates that the API should handle the request
        //  - Try API's standard request handler
        // Switch Transfer Object to API's private transfer object
        // Assert: The API's private object is never expected to be the same as the client's!
        ASSERT(PhysicalEndpoints[EP0]->Transfer != &PrivateTransferZero);
        PhysicalEndpoints[EP0]->Transfer = &PrivateTransferZero;

        NcStatus = NCSTATUS_SUCCESS;
        StandardUsbRequestHandler(&NcStatus);
    }

    if (NcStatus == NCSTATUS_UNSUCCESSFUL)
    {   // Unable to fulfill host's request. The request may have been recognized (by the
        // client or the API) but it still failed. More likely, however, is that the
        // request was not recognized by either the client or the API
        //  - Stall endpoint zero
        //  - Return without starting a data or status phase
        HISTO(VOLUME_MINIMUM, "SpS!", (BMREQUESTTYPE<<8) | (BREQUEST<<0), WVALUE, WINDEX);
        NETCHIP_WRITE(PAGESEL, EP0);
        NETCHIP_WRITE(EP_RSPSET, 1<<ENDPOINT_HALT);

        NCPRINTF(VOLUME_MINIMUM, ("StandardUsbRequestHandler(): Stalled! Setup Packet:"
            "%2.2x %2.2x %4.4x %4.4x %4.4x\n",
            BMREQUESTTYPE,
            BREQUEST,
            WVALUE,
            WINDEX,
            WLENGTH
            ));

        // Restore client's transfer object
        PrivDeviceObject->EndpointZero->Transfer = ClientTransferZero;
        return;
    }

    ASSERT(NcStatus == NCSTATUS_SUCCESS);

    NCPRINTF(SetupPacket_PrintVolume, 
        ("Request: %2.2x %2.2x %4.4x %4.4x %4.4x  %s\n",
        BMREQUESTTYPE,
        BREQUEST,
        WVALUE,
        WINDEX,
        WLENGTH,
        SetupPacket_Msg
        ));

    if (WLENGTH != 0)
    {   // Host request includes a data phase
        //  - Set up transfer starting conditions (effectively like API's Endpoint Transfer routine)
        LogicalEndpoints[EP0].Priv.pPkt = (PBYTE)LogicalEndpoints[EP0].Transfer->TransferBuffer;
        LogicalEndpoints[EP0].Priv.BytesRemaining = LogicalEndpoints[EP0].Transfer->TransferSize;
        LogicalEndpoints[EP0].CompletionStatus = NCSTATUS_PENDING;
    }

    // Start data phase:
    //  - Data phase routine handles data as well as no-data (i.e. wLength zero) cases
    //  - Status phase may be started if data phase completes (or if there is no data phase)
    EpZero_DataPhase(PhysicalEndpoints[EP0]);

    HISTO(DEFAULT_HISTORY, ")SPk", NETCHIP_READ(EP_IRQENB), NETCHIP_READ(EP_STAT0), NETCHIP_READ(EP_CFG));
}

///////////////////////////////////////////////////////////////////////////////
void
NcDev_UsbState(
    PNC_DEVICE_OBJECT DeviceObject
    )
{   // USB state (VBUS, reset, suspend, resume) handler
    //  - State machine to manage USB states (VBUS TRUE, VBUS FALSE, Suspend)
    //  - USB Power state is visible to client
    //  - Rules based on "Device State Diagram", See USB 2.0, figure 9-1
    NCBYTE UsbCtl1 = NETCHIP_READ(USBCTL1);
    NCBYTE IrqStat1 = NETCHIP_READ(IRQSTAT1);
    HISTO(DEFAULT_HISTORY, "Stat", DeviceObject->UsbPowerState, UsbCtl1, IrqStat1);

    NETCHIP_WRITE(IRQSTAT1, (
        (1<<ROOT_PORT_RESET_INTERRUPT) |
        (1<<RESUME_INTERRUPT) |
        (1<<SUSPEND_REQUEST_CHANGE_INTERRUPT) |
        (1<<VBUS_INTERRUPT) |
        0));

    // State machine for managing the USB State:
    //  - The state machine *must* change the event code if there is a 
    //    change (It should assert if it doesn't!)
    NCDEBUG(DeviceObject->EventCode = NC_DEVICE_EVENT_UNKNOWN);
    if (!(UsbCtl1 & (1<<VBUS_PIN)))
    {   // VBUS Pin FALSE (USB cable unplugged or host powered down):
        NETCHIP_WRITE(IRQENB0, 0x00);
        NETCHIP_WRITE(IRQENB1, USB_STATE_IRQENB1);

        if (IrqStat1 & (1<<RESUME_INTERRUPT))
        {   // Chip has awakened
            //  - Not changing state
            DeviceObject->EventCode = NC_DEVICE_EVENT_CHIP_WAKEUP;
        }
        else if (DeviceObject->UsbPowerState == NC_USB_POWER_OFF)
        {   // We are already in Power OFF state:
            //  - Not changing state, not calling client event handler
            return;
        } 
        else
        {   // Change state due to VBUS pin
            //  - Going to Power OFF (due to VBUS Pin FALSE)
            DeviceObject->UsbPowerState = NC_USB_POWER_OFF;
            DeviceObject->EventCode = NC_DEVICE_EVENT_VBUS_FALSE;
        }
    } 
    else
    {   // VBUS Pin is TRUE
        //  - Connected to USB host
        switch(DeviceObject->UsbPowerState)
        {   
        case NC_USB_POWER_OFF:
            // VBUS Pin TRUE:
            //  - Going to Power ON (due to VBUS Pin TRUE)
            DeviceObject->UsbPowerState = NC_USB_POWER_ON;
            DeviceObject->EventCode = NC_DEVICE_EVENT_VBUS_TRUE;
            break;

        case NC_USB_POWER_ON:
            if (IrqStat1 & (1<<SUSPEND_REQUEST_INTERRUPT))
            {   // Suspend request:
                //  - Going to Suspend due to Suspend Request
                //  - Tip: To properly convey the state of the host, USB Power State 
                //    goes to Suspend, even if the client chooses to NOT actually 
                //    suspend the NET2272
                //  - Note: Unplugging USB cable slowly may cause a Suspend Request 
                //    *before* VBUS goes FALSE. (This is due to the design of the pins
                //    in USB cables.) If the client decides to suspend the chip
                //    on such an unplug/suspend event, the NET2272 will NOT be
                //    aware that VBUS will soon go FALSE (since it's suspended). This 
                //    means firmware may not accurately manage the USB Power State on 
                //    an unplug. Possible remedies include external circuitry to determine 
                //    the state of VBUS or perhaps wait for about 300mSec (in a non-interrupt 
                //    context so that a VBUS FALSE interrupt has a chance to run), *then* 
                //    suspend.
                ASSERT(IrqStat1 & (1<<SUSPEND_REQUEST_CHANGE_INTERRUPT));
                DeviceObject->UsbPowerState = NC_USB_POWER_SUSPEND;
                DeviceObject->EventCode = NC_DEVICE_EVENT_SUSPEND;
                break;
            }

            if ((IrqStat1 & ((1<<RESET_STATUS) | (1<<ROOT_PORT_RESET_INTERRUPT))) == (1<<ROOT_PORT_RESET_INTERRUPT))
            {   // USB Reset ending (Reset Interrupt is TRUE, and Reset Status is FALSE)
                //  - A USB Reset does not change USB State
                DeviceObject->EventCode = NC_DEVICE_EVENT_ROOT_PORT_RESET;
                HISTO(DEFAULT_HISTORY, "Rst", 0, 0, NETCHIP_READ(IRQSTAT1));
                break;
            }

            // Not changing state, not calling client event handler
            NCPRINTF(VOLUME_MINIMUM, ("NcDev_UsbState() (POWER_ON): No event: IRQSTAT1:0x%2.2x USBCTL1:0x%2.2x\n", 
                IrqStat1, 
                UsbCtl1
                ));
            return;

        case NC_USB_POWER_SUSPEND:
            // Coming out of suspend:
            //  - The chip may or may NOT have been asleep, but it's definitely awake 
            //    now. Possible conditions:
            //     - Chip was suspended and awoke when the host resumed: Go to Resume state
            //     - Chip was not suspended when the host resumed: Go to Resume state
            //     - Chip was suspended and awoke, but NOT due to a host resume. Usually this
            //       happens when firmware accessed a chip register, but it can happen when
            //       there is some sort of noise on the USB signal lines: Chip wakeup event (State 
            //       does NOT change.) Chip must be suspended with I/O Wakeup Enable TRUE 
            //       for chip access to wake it
            if ((IrqStat1 & ((1<<SUSPEND_REQUEST_CHANGE_INTERRUPT) | (1<<SUSPEND_REQUEST_INTERRUPT))) == (1<<SUSPEND_REQUEST_CHANGE_INTERRUPT))
            {   // Resume (Suspend Request Change TRUE AND Suspend Request is FALSE):
                //  - Going to Power ON due to Resume
                DeviceObject->EventCode = NC_DEVICE_EVENT_RESUME;
                DeviceObject->UsbPowerState = NC_USB_POWER_ON;
                break;
            }
            if ((IrqStat1 & ((1<<RESET_STATUS) | (1<<ROOT_PORT_RESET_INTERRUPT))) == (1<<ROOT_PORT_RESET_INTERRUPT))
            {   // End of Reset (Reset Interrupt is TRUE AND Reset Status is FALSE):
                //  - Going to Power ON due to Reset
                DeviceObject->EventCode = NC_DEVICE_EVENT_ROOT_PORT_RESET;
                DeviceObject->UsbPowerState = NC_USB_POWER_ON;
                break;
            }
            if (IrqStat1 & (1<<RESUME_INTERRUPT))
            {   // Chip has awakened
                //  - State does NOT change
                DeviceObject->EventCode = NC_DEVICE_EVENT_CHIP_WAKEUP;
                break;
            }

            // Not changing state, not calling client

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -