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

📄 usbs_upd985xx.c

📁 NEC的USB接口驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
static ep0_impl ep0 = {    common:    {        state:                  USBS_STATE_POWERED, // The hardware does not distinguish  between detached, attached and powered.        enumeration_data:       (usbs_enumeration_data*) 0,        start_fn:               &usbs_upd985xx_ep0_start,        poll_fn:                &usbs_upd985xx_poll,        interrupt_vector:       CYGNUM_HAL_INTERRUPT_USB,        control_buffer:         { 0, 0, 0, 0, 0, 0, 0, 0 },        state_change_fn:        (void (*)(usbs_control_endpoint*, void*, usbs_state_change, int)) 0,        state_change_data:      (void*) 0,        standard_control_fn:    (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,        standard_control_data:  (void*) 0,        class_control_fn:       (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,        class_control_data:     (void*) 0,        vendor_control_fn:      (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,        vendor_control_data:    (void*) 0,        reserved_control_fn:    (usbs_control_return (*)(usbs_control_endpoint*, void*)) 0,        reserved_control_data:  (void*) 0,        buffer:                 (unsigned char*) 0,        buffer_size:            0,        fill_buffer_fn:         (void (*)(usbs_control_endpoint*)) 0,        fill_data:              (void*) 0,        fill_index:             0,        complete_fn:            (usbs_control_return (*)(usbs_control_endpoint*, int)) 0    },    rx_expecting_data:          false,    rx_indicator_valid:         false,    rx_indicator:               { 0, (void*) 0 },    tx_indicator_valid:         false,    tx_indicator:               { 0 },    tx_needs_zero_transfer:     0};extern usbs_control_endpoint usbs_upd985xx_ep0 __attribute__((alias ("ep0")));// Endpoint 1, isochronous transmits. This endpoint is not yet// supported. Although the interface for bulk transmits should be// mostly re-usable, there are some additional error conditions if// either the host or the target fails to achieve the desired// throughput.// Endpoint 2, isochronous receives. Not yet supported for now, just// like endpoint 1.// Endpoints 3 and 5 can share some code.#if defined(CYGPKG_DEVS_USB_UPD985XX_EP3) || defined(CYGPKG_DEVS_USB_UPD985XX_EP5)// Endpoint 3, bulk transmits, and endpoint 5, either interrupt transmits// or emulation of bulk transmits. The hardware does most// of the work.typedef struct ep35_impl {    usbs_tx_endpoint        common;    cyg_bool                tx_indicator_valid;    TxMailbox               tx_indicator;    int                     send_command;    volatile cyg_uint32*    cr;    TxBufferDescriptor*     tx_bufdesc;} ep35_impl;# ifdef CYGPKG_DEVS_USB_UPD985XX_EP3static void ep3_start_tx(usbs_tx_endpoint*);static void ep3_set_halted(usbs_tx_endpoint*, cyg_bool);static ep35_impl ep3 = {    common: {        start_tx_fn:        &ep3_start_tx,        set_halted_fn:      &ep3_set_halted,        complete_fn:        (void (*)(void*, int)) 0,        complete_data:      (void*) 0,        buffer:             (const unsigned char*) 0,        buffer_size:        0,        halted:             0,    },    tx_indicator_valid: false,    tx_indicator:       { 0 },    send_command:       USBS_CMR_COMMAND_TX_EP3,    cr:                 EP3_CR,    tx_bufdesc:         0       // Needs run-time initialization};extern usbs_tx_endpoint usbs_upd985xx_ep3 __attribute__ ((alias ("ep3")));# endif# ifdef CYGPKG_DEVS_USB_UPD985XX_EP5static void ep5_start_tx(usbs_tx_endpoint*);static void ep5_set_halted(usbs_tx_endpoint*, cyg_bool);static ep35_impl ep5 = {    common: {        start_tx_fn:        &ep5_start_tx,        set_halted_fn:      &ep5_set_halted,        complete_fn:        (void (*)(void*, int)) 0,        complete_data:      (void*) 0,        buffer:             (const unsigned char*) 0,        buffer_size:        0,        halted:             0,    },    tx_indicator_valid: false,    tx_indicator:       { 0 },    send_command:       USBS_CMR_COMMAND_TX_EP5,    cr:                 EP5_CR,    tx_bufdesc:         0       // Needs run-time initialization};extern usbs_tx_endpoint usbs_upd985xx_ep5 __attribute__ ((alias ("ep5")));# endif#endif#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4// Endpoint 4, bulk receives. Again the hardware does the hard work.// Receive pool 2 is reserved for this endpoint.typedef struct ep4_impl {    usbs_rx_endpoint    common;    cyg_uint32          head_size;    cyg_uint32          direct_size;    cyg_uint32          tail_size;    cyg_bool            rx_indicator_valid;    RxMailbox           rx_indicator;    cyg_int32           tail_index;} ep4_impl;static void ep4_start_rx(usbs_rx_endpoint*);static void ep4_set_halted(usbs_rx_endpoint*, cyg_bool);static ep4_impl ep4 = {    common: {        start_rx_fn:        &ep4_start_rx,        set_halted_fn:      &ep4_set_halted,        complete_fn:        (void (*)(void*, int)) 0,        complete_data:      (void*) 0,        buffer:             (unsigned char*) 0,        buffer_size:        0,        halted:             0,    },    rx_indicator_valid:     false,    rx_indicator:           { 0, (void*) 0 },    tail_index:             -1};extern usbs_rx_endpoint usbs_upd985xx_ep4 __attribute__((alias ("ep4")));#endif// Endpoint 6, interrupt receives. Not yet implemented. There may// be conflicts because the hardware is shared with endpoint 0.// ----------------------------------------------------------------------------// Mailbox support.//// The transmit and receive mailboxes are shared between the// appropriate endpoints. This causes some complications if e.g.// transmits on several endpoints complete at the same time. For// example the tx mailbox might contain send indicators for endpoints// 3 and 0, but the DSR code will process endpoint 0 before endpoint// 3.//// This device driver works on the basis that there can be only one// transmit and/or receive in progress for any given endpoint, so the// relevant information can be extracted from the mailbox and put into// the per-endpoint structures. The routines below can be used to// move data from the mailboxes. They will be called in DSR context// so there is no need to worry about locking.static voiddrain_tx_mailbox(void){    TxMailbox*  tmra    = IBUS_SWAPPTR(TxMailbox, *USBS_TMRA);    TxMailbox*  tmwa    = IBUS_SWAPPTR(TxMailbox, *USBS_TMWA);    if (tmra != tmwa) {        do {            TxMailbox mbox = *tmra;            tmra++;            if (tmra == &(uncached->tx_mboxes[TXMBOX_COUNT])) {                tmra = &(uncached->tx_mboxes[0]);            }            switch(mbox.status & TXMBOX_STATUS_EPN_MASK) {              case TXMBOX_STATUS_EPN_EP0:                CYG_ASSERT(false == ep0.tx_indicator_valid, "Only one ep0 transmit should be in progress at a time");                ep0.tx_indicator        = mbox;                ep0.tx_indicator_valid  = true;                break;#ifdef CYGPKG_DEVS_USB_UPD985XX_EP3                              case TXMBOX_STATUS_EPN_EP3:                CYG_ASSERT(false == ep3.tx_indicator_valid, "Only one ep3 transmit should be in progress at a time");                ep3.tx_indicator        = mbox;                ep3.tx_indicator_valid  = true;                break;#endif                #ifdef CYGPKG_DEVS_USB_UPD985XX_EP5              case TXMBOX_STATUS_EPN_EP5:                CYG_ASSERT(false == ep5.tx_indicator_valid, "Only one ep5 transmit should be in progress at a time");                ep5.tx_indicator        = mbox;                ep5.tx_indicator_valid  = true;                break;#endif                              default:                break;            }        } while (tmra != tmwa);        *USBS_TMRA = IBUS_SWAPPTR(TxMailbox, tmra); FLUSH_IBUS();    }}static voiddrain_rx_mailbox(void){    RxMailbox*  rmra    = IBUS_SWAPPTR(RxMailbox, *USBS_RMRA);    RxMailbox*  rmwa    = IBUS_SWAPPTR(RxMailbox, *USBS_RMWA);        if (rmra != rmwa) {        do {            RxMailbox mbox = *rmra;            rmra++;            if (rmra == &(uncached->rx_mboxes[RXMBOX_COUNT])) {                rmra = &(uncached->rx_mboxes[0]);            }            switch(mbox.status & RXMBOX_STATUS_EPN_MASK) {              case RXMBOX_STATUS_EPN_EP0:                // Ignore zero-byte transfers. It is not clear why                // these happen, but they have been observed.                if (0 != (mbox.status & RXMBOX_STATUS_SIZE_MASK)) {                    CYG_ASSERT(false == ep0.rx_indicator_valid, "Only one ep0 receive should be in progress at a time");                    ep0.rx_indicator        = mbox;                    ep0.rx_indicator_valid  = true;                }                break;#ifdef CYGPKG_DEVS_USB_UPD985XX_EP4              case RXMBOX_STATUS_EPN_EP4:                // If an error occurs then the hardware may report                // multiple rx completions, each with an IBUS error                // indicator. For now only the last rx indicator is                // taken into account, which means we could lose                // a successful receive that happens to be followed                // by an error.                // NOTE: any possibility of improving on this?#if 1                                CYG_ASSERT(false == ep4.rx_indicator_valid, "Only one ep4 receive should be in progress at a time");#endif                                ep4.rx_indicator        = mbox;                ep4.rx_indicator_valid  = true;                break;#endif                              default:                break;            }         } while (rmra != rmwa);        *USBS_RMRA = IBUS_SWAPPTR(RxMailbox, rmra); FLUSH_IBUS();    }}// ----------------------------------------------------------------------------// Transmit locking.//// According to NEC errata U3 and U4 the hardware may exhibit// undesirable behaviour if there are concurrent transmissions. There// are various ways of resolving this, but the simplest is to perform// locking in software so that at most one transmit endpoint is in use// at any one time. This approach works fine if transmissions only// involve one tx endpoint plus the control endpoint because the// control endpoint generally only gets used during initialization and// the other endpoint only gets used after initialization. If multiple// transmit endpoints are used then locking in software becomes less// acceptable, especially if isochronous transfers are used because// timing is important for those.//// There is a theoretical problem if e.g. there is a very large bulk// transfer on a busy bus and it is necessary to respond to a control// message. The control reply would be delayed, possibly causing a// violation of the USB standard and a timeout on the host.#ifdef CYGIMP_DEVS_USB_UPD985XX_SERIALIZE_TRANSMITSstatic void ep0_start_tx(void);# if defined(CYGPKG_DEVS_USB_UPD985XX_EP3) || defined(CYGPKG_DEVS_USB_UPD985XX_EP5)static void ep35_start_tx(ep35_impl*);# endifstatic cyg_bool tx_in_progress  = false;static cyg_bool ep0_tx_pending  = false;# ifdef CYGPKG_DEVS_USB_UPD985XX_EP3static cyg_bool ep3_tx_pending  = false;# endif# ifdef CYGPKG_DEVS_USB_UPD985XX_EP5static cyg_bool ep5_tx_pending  = false;# endif// Invoked from ep?_start_tx(). Scheduling may or may not be locked.static cyg_booltx_try_lock(cyg_bool* which){    cyg_bool result;    cyg_drv_dsr_lock();    if (tx_in_progress) {

⌨️ 快捷键说明

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