/*! * mxc_gptcr_timer_int_hndlr() - timer interrupt * @param irq * @param dev_id * @param regs */ irqreturn_t mxc_gptcr_timer_int_hndlr (int irq, void *dev_id, struct pt_regs *regs) { u32 gptsr = *_reg_GPT_GPTSR; *_reg_GPT_GPTIR &= ~(0x04); if (gptsr & (0x01 << 2)){ TRACE_MSG7(OCD, "cnt: %08x match: %08x gptsr: %08x GPTCNT: %08x GPTCR: %08x GPTSR: %08x GPTOCR3: %08x\n", mxc_gptcr_ticks_set, mxc_gptcr_match_set, gptsr, *_reg_GPT_GPTCNT, *_reg_GPT_GPTCR, *_reg_GPT_GPTSR, *_reg_GPT_GPTOCR3); *_reg_GPT_GPTCR &= ~(0x7 << 26); *_reg_GPT_GPTOCR3 = 0; TRACE_MSG0(OCD, "OCM3"); TRACE_MSG1(OCD, "active: %x", mxc_gptcr_active); if (mxc_gptcr_active) { TRACE_MSG0(OCD, "calling otg_event"); mxc_gptcr_active = 0; otg_event(ocd_instance->otg, TMOUT, OCD, "TMOUT"); } else { TRACE_MSG0(OCD, "skipping otg_event"); } *_reg_GPT_GPTSR |= 0x4; return IRQ_HANDLED; } if (!mxc_shared_int) *_reg_GPT_GPTIR |= 0x4; return IRQ_NONE; }
/*! net_fd_start_xmit_nocrc * @brief - start sending a buffer * * @param function_instance - pointer to this function instance * @param buffer buffer containing data to send * @param len - length of data to send * @param data instance data * @return: 0 if all OK * -EINVAL, -EUNATCH, -ENOMEM * rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above) * Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped. */ int net_fd_start_xmit_nocrc (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data) { struct usb_network_private *npd = function_instance->privdata; struct usbd_urb *urb = NULL; int rc; int in_pkt_sz; u8 *cp; u32 crc; #ifndef CONFIG_OTG_NETWORK_DOUBLE_IN int xmit_index = 0; int endpoint_index = BULK_IN_A; #else /* CONFIG_OTG_NETWORK_DOUBLE_IN */ int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1])) ? 0 : 1; int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A; #endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */ TRACE_MSG7(NTT,"npd: %p function: %p flags: %04x len: %d endpoint_index: %d xmit_started: %d %d", npd, function_instance, npd->flags, len, endpoint_index, otg_atomic_read(&npd->xmit_urbs_started[0]), otg_atomic_read(&npd->xmit_urbs_started[1])); in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, endpoint_index, usbd_high_speed(function_instance)); /* allocate urb 5 bytes larger than required */ if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa); return -ENOMEM; } urb->actual_length = len; memcpy (urb->buffer, buffer, len); urb->function_privdata = data; urb->actual_length = len; otg_atomic_add(urb->actual_length, &npd->queued_bytes); otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]); if ((rc = usbd_start_in_urb (urb))) { TRACE_MSG1(NTT,"FAILED: %d", rc); printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc); urb->function_privdata = NULL; otg_atomic_sub(urb->actual_length, &npd->queued_bytes); otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]); usbd_free_urb (urb); return rc; } return 0; }
/*! net_fd_recv_urb_mdlm * @brief callback to process a received URB * * @param urb - pointer to received urb * @param rc - dummy parameter * @return non-zero for failure. */ int net_fd_recv_urb_mdlm(struct usbd_urb *urb, int rc) { struct usbd_function_instance *function_instance = urb->function_instance; struct usb_network_private *npd = function_instance->privdata; void *os_data = NULL; void *os_buffer = NULL; int crc_bad = 0; int trim = 0; int len; u32 crc; u32 temmp; len = urb->actual_length; trim = 0; //TRACE_MSG2(NTT, "status: %d actual_length: %d", urb->status, urb->actual_length); //RETURN_EINVAL_IF (urb->status == USBD_URB_OK); os_data = urb->function_privdata; //TRACE_MSG2(NTT, "os_data: %x os_buffer: %x", os_data, os_buffer); #if defined(CONFIG_OTG_NETWORK_BLAN_PADAFTER) { /* This version simply checks for a correct CRC along the * entire packet. Some UDC's have trouble with some packet * sizes, this allows us to add pad bytes after the CRC. */ u8 *src = urb->buffer; int copied; // XXX this should work, but the MIPS optimizer seems to get it wrong.... //copied = (len < urb->wMaxPacketSize) ? 0 : ((len / urb->wMaxPacketSize) - 1) * urb->wMaxPacketSize; if (len < urb->wMaxPacketSize*2) copied = 0; else { int pkts = ((len - urb->wMaxPacketSize) / urb->wMaxPacketSize); copied = (pkts - 1) * urb->wMaxPacketSize; } len -= copied; crc = CRC32_INIT; for (; copied-- > 0 ; crc = COMPUTE_FCS (crc, *os_buffer++ = *src++)); for (; (len-- > 0) && (CRC32_GOOD != crc); crc = COMPUTE_FCS (crc, *os_buffer++ = *src++)); trim = len + 4; if (CRC32_GOOD != crc) { TRACE_MSG1(NTT,"AAA frame: %03x", urb->framenum); THROW_IF(npd->seen_crc, crc_error); } else npd->seen_crc = 1; } //#else /* defined(CONFIG_OTG_NETWORK_BLAN_PADAFTER) */ #elif defined(CONFIG_OTG_NETWORK_BLAN_CRC) || defined(CONFIG_OTG_NETWORK_SAFE_CRC) /* * The CRC can be sent in two ways when the size of the transfer * ends up being a multiple of the packetsize: * * | * <data> <CRC><CRC><CRC><CRC>|<???> case 1 * <data> <NUL><CRC><CRC><CRC>|<CRC> case 2 * <data> <NUL><CRC><CRC><CRC><CRC>| case 3 * <data> <NUL><CRC><CRC><CRC>|<CRC> | case 4 * | * * This complicates CRC checking, there are four scenarios: * * 1. length is 1 more than multiple of packetsize with a trailing byte * 2. length is 1 more than multiple of packetsize * 3. length is multiple of packetsize * 4. none of the above * * Finally, even though we always compute CRC, we do not actually throw * things away until and unless we have previously seen a good CRC. * This allows backwards compatibility with hosts that do not support * adding a CRC to the frame. * */ // test if 1 more than packetsize multiple if (1 == (len % urb->wMaxPacketSize)) { u8 *cp = urb->buffer + len - 1 - 4; // copy and CRC up to the packetsize boundary crc = crc32_nocopy(urb->buffer, len - 1, CRC32_INIT); if (TRACE_VERBOSE) TRACE_MSG7(NTT,"A CRC nocopy: %08x %08x len: %d CRC: %02x %02x %02x %02x", CRC32_GOOD, crc, len, cp[0], cp[1], cp[2], cp[3]); // if the CRC is good then this is case 1 if (CRC32_GOOD != crc) { crc = crc32_nocopy(urb->buffer + len - 1, 1, crc); if (CRC32_GOOD != crc) { //crc_errors[len%64]++; TRACE_MSG3(NTT,"A CRC error %08x %08x %03x", CRC32_GOOD, crc, urb->framenum); printk(KERN_INFO"%s: A CRC\n", __FUNCTION__); npd->seen_crc_error = 1; THROW_IF(npd->seen_crc, crc_error); } else npd->seen_crc = 1; } else npd->seen_crc = 1; } else { u8 *cp = urb->buffer + len - 4; crc = crc32_nocopy(urb->buffer, len, CRC32_INIT); if (TRACE_VERBOSE) TRACE_MSG7(NTT,"B CRC nocopy: %08x %08x len: %d CRC: %02x %02x %02x %02x", CRC32_GOOD, crc, len, cp[0], cp[1], cp[2], cp[3]); if (CRC32_GOOD != crc) { //crc_errors[len%64]++; TRACE_MSG3(NTT,"B CRC error %08x %08x %03x", CRC32_GOOD, crc, urb->framenum); if (TRACE_VERBOSE) { TRACE_MSG2(NTT, "status: %d actual_length: %d", urb->status, urb->actual_length); TRACE_NRECV(NTT, 32, urb->buffer); TRACE_MSG0(NTT, "--"); TRACE_RECV(NTT, urb->actual_length, urb->buffer); } printk(KERN_INFO"%s: B CRC\n", __FUNCTION__); npd->seen_crc_error = 1; THROW_IF(npd->seen_crc, crc_error); } else npd->seen_crc = 1; // XXX shorten by 4 bytes? } // trim IFF we are paying attention to crc if (npd->seen_crc) trim = 4; #endif /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ if (net_fd_recv_buffer(function_instance, urb->buffer, len, os_data, crc_bad, trim)) { TRACE_MSG0(NTT, "FAILED"); net_os_dealloc_buffer(function_instance, os_data, os_buffer); } // catch a simple error, just increment missed error and general error CATCH(error) { //TRACE_MSG4(NTT,"CATCH(error) urb: %p status: %d len: %d function: %p", // urb, urb->status, urb->actual_length, function_instance); // catch a CRC error CATCH(crc_error) { crc_bad = 1; npd->seen_crc_error = 1; } } return 0; }
/*! net_fd_start_xmit_ecm * @brief - start sending to host * @param function_instance * @param buffer data storage area * @param len - length of data to transmit * @param data - instance private data * * @return: 0 if all OK * -EINVAL, -EUNATCH, -ENOMEM * rc from usbd_start_in_urb() if that fails (is != 0, may be one of err values above) * Note: -ECOMM is interpreted by calling routine as signal to leave IF stopped. */ int net_fd_start_xmit_ecm (struct usbd_function_instance *function_instance, u8 *buffer, int len, void *data) { struct usb_network_private *npd = function_instance->privdata; struct usbd_urb *urb = NULL; int rc; int in_pkt_sz; u32 crc; //#ifndef CONFIG_OTG_NETWORK_DOUBLE_IN int xmit_index = 0; int endpoint_index = BULK_IN_A; //#else /* CONFIG_OTG_NETWORK_DOUBLE_IN */ //int xmit_index = (otg_atomic_read(&npd->xmit_urbs_started[0]) <= otg_atomic_read(&npd->xmit_urbs_started[1])) // ? 0 : 1; //int endpoint_index = (xmit_index) ? BULK_IN_B : BULK_IN_A; //#endif /* CONFIG_OTG_NETWORK_DOUBLE_IN */ TRACE_MSG7(NTT,"npd: %p function: %p flags: %04x len: %d endpoint_index: %d xmit_started: %d %d", npd, function_instance, npd->flags, len, endpoint_index, otg_atomic_read(&npd->xmit_urbs_started[0]), otg_atomic_read(&npd->xmit_urbs_started[1])); in_pkt_sz = usbd_endpoint_wMaxPacketSize(function_instance, endpoint_index, usbd_high_speed(function_instance)); //TRACE_MSG0(NTT,"SIMPLE_CRC"); // allocate urb 5 bytes larger than required if (!(urb = usbd_alloc_urb (function_instance, endpoint_index, len + 5 + 4 + in_pkt_sz, net_fd_urb_sent_bulk ))) { u8 epa = usbd_endpoint_bEndpointAddress(function_instance, endpoint_index, usbd_high_speed(function_instance)); TRACE_MSG2(NTT,"urb alloc failed len: %d endpoint: %02x", len, epa); printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n", __FUNCTION__, len, epa); return -ENOMEM; } urb->actual_length = len; #if defined(CONFIG_OTG_NETWORK_BLAN_CRC) || defined(CONFIG_OTG_NETWORK_SAFE_CRC) // copy and crc len bytes crc = crc32_copy(urb->buffer, buffer, len, CRC32_INIT); if ((urb->actual_length % in_pkt_sz) == (in_pkt_sz - 4)) { #undef CONFIG_OTG_NETWORK_PADBYTE #ifdef CONFIG_OTG_NETWORK_PADBYTE // add a pad byte if required to ensure a short packet, usbdnet driver // will correctly handle pad byte before or after CRC, but the MCCI driver // wants it before the CRC. crc = crc32_pad(urb->buffer + urb->actual_length, 1, crc); urb->actual_length++; #else /* CONFIG_OTG_NETWORK_PADBYTE */ urb->flags |= USBD_URB_SENDZLP; TRACE_MSG2(NTT,"setting ZLP: urb: %p flags: %x", urb, urb->flags); #endif /* CONFIG_OTG_NETWORK_PADBYTE */ } crc = ~crc; urb->buffer[urb->actual_length++] = crc & 0xff; urb->buffer[urb->actual_length++] = (crc >> 8) & 0xff; urb->buffer[urb->actual_length++] = (crc >> 16) & 0xff; urb->buffer[urb->actual_length++] = (crc >> 24) & 0xff; #if defined(CONFIG_OTG_NETWORK_BLAN_FERMAT) if (npd->fermat) fermat_encode(urb->buffer, urb->actual_length); #endif #else /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ memcpy (urb->buffer, buffer, len); if ((urb->actual_length % in_pkt_sz) == (in_pkt_sz)) { /* no longer in Kconfig - change undef to define to active padbyte */ #undef CONFIG_OTG_NETWORK_PADBYTE #ifdef CONFIG_OTG_NETWORK_PADBYTE urb->actual_length++; #else /* CONFIG_OTG_NETWORK_PADBYTE */ urb->flags |= USBD_URB_SENDZLP; TRACE_MSG2(NTT,"setting ZLP: urb: %p flags: %x", urb, urb->flags); #endif /* CONFIG_OTG_NETWORK_PADBYTE */ } #endif /* defined(CONFIG_OTG_NETWORK_BLAN_CRC) ...*/ //TRACE_MSG3(NTT,"urb: %p buf: %p priv: %p", urb, data, urb->function_privdata); urb->function_privdata = data; otg_atomic_add(urb->actual_length, &npd->queued_bytes); otg_atomic_inc(&npd->xmit_urbs_started[xmit_index]); if ((rc = usbd_start_in_urb (urb))) { TRACE_MSG1(NTT,"FAILED: %d", rc); printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc); urb->function_privdata = NULL; otg_atomic_sub(urb->actual_length, &npd->queued_bytes); otg_atomic_dec(&npd->xmit_urbs_started[xmit_index]); usbd_free_urb (urb); return rc; } return 0; }