? packages/devs/usb/at91/current/src/usbs_at91.c_andrews_version Index: packages/devs/usb/at91/current/ChangeLog =================================================================== RCS file: /cvs/ecos/ecos/packages/devs/usb/at91/current/ChangeLog,v retrieving revision 1.3 diff -u -r1.3 ChangeLog --- packages/devs/usb/at91/current/ChangeLog 6 Jun 2006 13:30:11 -0000 1.3 +++ packages/devs/usb/at91/current/ChangeLog 9 Jun 2006 17:43:24 -0000 @@ -1,3 +1,8 @@ +2006-06-09 Oliver Munz + + * src/usbs_at91.c: Fixing wrong IMR-handling and fix the losing + of IMR-flag at enumeration problem via new booleans. + 2006-06-06 Andrew Lunn * cdl/usbs_at91.cdl: Allow EP0 to be enabled when there are no Index: packages/devs/usb/at91/current/src/usbs_at91.c =================================================================== RCS file: /cvs/ecos/ecos/packages/devs/usb/at91/current/src/usbs_at91.c,v retrieving revision 1.2 diff -u -r1.2 usbs_at91.c --- packages/devs/usb/at91/current/src/usbs_at91.c 2 Jun 2006 18:46:13 -0000 1.2 +++ packages/devs/usb/at91/current/src/usbs_at91.c 9 Jun 2006 17:43:25 -0000 @@ -87,14 +87,20 @@ AT91_UDP_RXRSM | AT91_UDP_RXSUSP | AT91_UDP_EPINT0 | \ AT91_UDP_EPINT1 | AT91_UDP_EPINT2 | AT91_UDP_EPINT3) +#define AT91_UDP_STANDARD_IRQs \ + (AT91_UDP_WAKEUP | AT91_UDP_ENDBUSRES | AT91_UDP_EXTRSM | \ + AT91_UDP_RXRSM | AT91_UDP_RXSUSP | AT91_UDP_EPINT0) + #define THERE_IS_A_NEW_PACKET_IN_THE_UDP 0xffff +#define DONT_USE_IMR_AS_TRANSFER_FLAG + // Fifo size for each end point. static const cyg_uint16 usbs_at91_endpoint_fifo_size[AT91_USB_ENDPOINTS] = { 8, 64, 64, - 64, + 8 }; // Does an endpoint support ping pong buffering? @@ -117,6 +123,11 @@ { THERE_IS_A_NEW_PACKET_IN_THE_UDP, THERE_IS_A_NEW_PACKET_IN_THE_UDP, THERE_IS_A_NEW_PACKET_IN_THE_UDP, THERE_IS_A_NEW_PACKET_IN_THE_UDP}; +#ifdef DONT_USE_IMR_AS_TRANSFER_FLAG +static bool usbs_at91_endpoint_transfer_aktive[AT91_USB_ENDPOINTS] = + { false, false, false, false }; +#endif + static cyg_interrupt usbs_at91_intr_data; static cyg_handle_t usbs_at91_intr_handle; @@ -231,17 +242,40 @@ EP0_LL_SET_ADDRESS, } ep0_low_level_status_t; -// Enable/Disable interrupts for a specific endpoint. static void -usbs_at91_endpoint_interrupt_enable (cyg_uint8 epn, bool enable) +usbs_at91_endpoint_transfer_start (cyg_uint8 epn) { - CYG_ASSERT (epn < AT91_USB_ENDPOINTS, "Invalid endpoint"); - - if (enable) { + CYG_ASSERT (epn < AT91_USB_ENDPOINTS, "Invalid endpoint"); + HAL_WRITE_UINT32 (pIER, 1 << epn); - } else { - HAL_WRITE_UINT32 (pIDR, 1 << epn); - } +#ifdef DONT_USE_IMR_AS_TRANSFER_FLAG + usbs_at91_endpoint_transfer_aktive[epn] = true; +#endif +} + +static void +usbs_at91_endpoint_transfer_end (cyg_uint8 epn, usbs_control_return returncode) +{ + usbs_rx_endpoint *pep; + + CYG_ASSERT (epn < AT91_USB_ENDPOINTS, "Invalid endpoint"); + +#ifdef DONT_USE_IMR_AS_TRANSFER_FLAG + if (usbs_at91_endpoint_transfer_aktive[epn]){ + usbs_at91_endpoint_transfer_aktive[epn] = false; +#else + if (BITS_ARE_SET (pIMR, 1 << epn)) { +#endif + // If the end point is transmitting, call the complete function + // to terminate to transfer + pep = (usbs_rx_endpoint *) usbs_at91_endpoints[epn]; + + // Disable interrupts from the endpoint + HAL_WRITE_UINT32 (pIDR, 1 << epn); + if (pep->complete_fn) { + (*pep->complete_fn) (pep->complete_data, returncode); + } + } } static cyg_uint8 * @@ -273,7 +307,7 @@ } /* Tell the host that the device is ready to start communication */ -static void +void usbs_at91_set_pullup (bool set) { @@ -314,20 +348,9 @@ usbs_end_all_transfers (usbs_control_return returncode) { cyg_uint32 epn; - usbs_rx_endpoint *pep; for (epn = 1; epn < AT91_USB_ENDPOINTS; epn++) { - if (BITS_ARE_SET (pIMR, 1 << epn)) { - // If the end point is transmitting, call the complete function - // to terminate to transfer - pep = (usbs_rx_endpoint *) usbs_at91_endpoints[epn]; - - if (pep->complete_fn) { - (*pep->complete_fn) (pep->complete_data, returncode); - } - // Disable interrupts from the endpoint - usbs_at91_endpoint_interrupt_enable (epn, false); - } + usbs_at91_endpoint_transfer_end(epn, returncode); } } @@ -336,11 +359,11 @@ usbs_state_notify (usbs_control_endpoint * pcep) { static int old_state = USBS_STATE_CHANGE_POWERED; - int state = pcep->state & USBS_STATE_MASK; + int state = pcep->state; if (pcep->state != old_state) { usbs_end_all_transfers (-EPIPE); - switch (state) { + switch (state & USBS_STATE_MASK) { case USBS_STATE_DETACHED: case USBS_STATE_ATTACHED: case USBS_STATE_POWERED: @@ -423,11 +446,7 @@ pep->halted = new_value; if (new_value && BITS_ARE_SET (pIMR, 1 << epn)) { - /* Ready to transmit */ - if (pep->complete_fn) { - (*pep->complete_fn) (pep->complete_data, -EAGAIN); - } - usbs_at91_endpoint_interrupt_enable (epn, false); + usbs_at91_endpoint_transfer_end(epn, -EAGAIN); SET_BITS (pCSR, AT91_UDP_CSR_FORCESTALL); } else { CLEAR_BITS (pCSR, AT91_UDP_CSR_FORCESTALL); @@ -445,7 +464,6 @@ CYG_ASSERT (AT91_USB_ENDPOINTS > epn, "Invalid end point"); - usbs_at91_endpoint_interrupt_enable (epn, false); /* Reset endpoint */ HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_RST_EP, 1 << epn); HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_RST_EP, 0); @@ -469,10 +487,6 @@ usbs_at91_handle_reset (void) { int epn; - const usb_endpoint_descriptor *usb_endpoints; - cyg_uint8 endpoint_type; - - usbs_end_all_transfers (-EPIPE); HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_IDR, 0xffffffff); HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_ICR, 0xffffffff); @@ -482,35 +496,18 @@ HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_FADDR, AT91_UDP_FADDR_FEN); HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_CSR0, AT91_UDP_CSR_EPEDS | AT91_UDP_CSR_EPTYPE_CTRL); - HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_IER, AT91_UDP_ALLOWED_IRQs); + HAL_WRITE_UINT32 (AT91_UDP + AT91_UDP_IER, AT91_UDP_STANDARD_IRQs); for (epn=1; epn < AT91_USB_ENDPOINTS; epn++) { usbs_at91_endpoint_init ((usbs_rx_endpoint *)usbs_at91_endpoints[epn], 0, false); } - - // Now walk the endpoints configuring them correctly. This only - // works if there is one interface. - usb_endpoints = usbs_at91_ep0.enumeration_data->endpoints; - - for (epn = 1; - epn <= usbs_at91_ep0.enumeration_data->total_number_endpoints; - epn++) { - - endpoint_type = (usb_endpoints[epn-1].attributes | - (usb_endpoints[epn-1].endpoint & - USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN ? - USB_ENDPOINT_DESCRIPTOR_ENDPOINT_IN : - USB_ENDPOINT_DESCRIPTOR_ENDPOINT_OUT)); - usbs_at91_endpoint_init((usbs_rx_endpoint *)usbs_at91_endpoints[epn], - endpoint_type, - true); - } } static void usbs_at91_ep0_start (usbs_control_endpoint * endpoint) { + usbs_at91_handle_reset (); // If there is additional platform-specific initialization to @@ -537,6 +534,7 @@ CYG_ASSERT (pep->complete_fn, "No complete_fn()"); cyg_drv_dsr_lock (); + if (usbs_at91_ep0.state != USBS_STATE_CONFIGURED) { /* If not configured it means there is nothing to do */ cyg_drv_dsr_unlock (); @@ -567,7 +565,18 @@ return; } - CYG_ASSERT (BITS_ARE_SET (pCSR, 1 << 9), "Wrong endpoint type"); *ppbegin = pep->buffer; /* Set the working pointers */ *ppend = (cyg_uint8 *) ((cyg_uint32) pep->buffer + pep->buffer_size); @@ -589,8 +598,8 @@ } } - usbs_at91_endpoint_interrupt_enable (epn, true); - + usbs_at91_endpoint_transfer_start (epn); + cyg_drv_dsr_unlock (); } @@ -738,17 +747,13 @@ CYG_ASSERT (AT91_USB_ENDPOINTS > epn && epn, "Invalid end point"); CYG_ASSERT (pep->complete_fn, "No complete_fn()"); - if (*ppend == *ppbegin) { /* Transmitted/Received ? */ - + if (*ppend == *ppbegin) { /* Transmitted ? */ pep->buffer_size = (cyg_uint32) * ppbegin - (cyg_uint32) pep->buffer; - if (pep->buffer_size && pep->complete_fn) { - if (!pep->halted) { - (*pep->complete_fn) (pep->complete_data, pep->buffer_size); - } else { - (*pep->complete_fn) (pep->complete_data, -EAGAIN); - } + if (!pep->halted) { + usbs_at91_endpoint_transfer_end(epn, pep->buffer_size); + } else { + usbs_at91_endpoint_transfer_end(epn, -EAGAIN); } - usbs_at91_endpoint_interrupt_enable (epn, false); } } @@ -879,7 +884,7 @@ usbs_at91_control_setup_send_ack(); status = EP0_LL_SEND_READY; - + switch (recipient) { case USB_DEVREQ_RECIPIENT_DEVICE: status = EP0_LL_STALL; @@ -913,12 +918,10 @@ cyg_uint8 **ppbegin = &usbs_at91_endpoint_pbegin[0]; cyg_uint8 **ppend = &usbs_at91_endpoint_pend[0]; usb_devreq *req = (usb_devreq *) usbs_at91_ep0.control_buffer; - cyg_uint8 protocol; cyg_uint16 length; bool dev_to_host; usbs_control_return usbcode; - bool handled = false; - + usbs_at91_ep0.buffer_size = 0; usbs_at91_ep0.fill_buffer_fn = 0; usbs_at91_ep0.complete_fn = 0; @@ -931,8 +934,6 @@ CLEAR_BITS (pCSR0, AT91_UDP_CSR_DTGLE); status = EP0_LL_REQUEST; - - protocol = req->type & (USB_DEVREQ_TYPE_MASK); // Set the next transfer direction if (dev_to_host) { @@ -940,33 +941,26 @@ } else { CLEAR_BITS (pCSR0, AT91_UDP_CSR_DIR); /* Set OUT direction */ } - - if (protocol == USB_DEVREQ_TYPE_STANDARD) { - handled = true; - switch (req->request) { - case USB_DEVREQ_GET_STATUS: - status = usbs_at91_control_setup_get_status(); - break; - case USB_DEVREQ_SET_ADDRESS: - // Most of the hard work is done by the hardware. We just need - // to send an ACK. - usbs_at91_control_setup_send_ack(); - status = EP0_LL_SEND_READY; - break; - case USB_DEVREQ_SET_FEATURE: - status = usbs_at91_control_setup_set_feature(); - break; - case USB_DEVREQ_CLEAR_FEATURE: - status = usbs_at91_control_setup_clear_feature(); - break; - default: - handled = false; - } - } - if ((protocol != USB_DEVREQ_TYPE_STANDARD) || !handled) { - // Ask the layer above to process the message - usbcode = usbs_parse_host_get_command (&usbs_at91_ep0); - usbs_at91_ep0.buffer_size = MIN (usbs_at91_ep0.buffer_size, length); + + switch (req->request) { + case USB_DEVREQ_GET_STATUS: + status = usbs_at91_control_setup_get_status(); + break; + case USB_DEVREQ_SET_ADDRESS: + // Most of the hard work is done by the hardware. We just need + // to send an ACK. + usbs_at91_control_setup_send_ack(); + status = EP0_LL_SEND_READY; + break; + case USB_DEVREQ_SET_FEATURE: + status = usbs_at91_control_setup_set_feature(); + break; + case USB_DEVREQ_CLEAR_FEATURE: + status = usbs_at91_control_setup_clear_feature(); + break; + default: + // Ask the layer above to process the message + usbcode = usbs_parse_host_get_command (&usbs_at91_ep0); *ppbegin = usbs_at91_ep0.buffer; *ppend = *ppbegin + usbs_at91_ep0.buffer_size; /* Ready to send... */