aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/host/hc_crisv10.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/hc_crisv10.c')
-rw-r--r--drivers/usb/host/hc_crisv10.c4550
1 files changed, 0 insertions, 4550 deletions
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
deleted file mode 100644
index 32f7caf2474..00000000000
--- a/drivers/usb/host/hc_crisv10.c
+++ /dev/null
@@ -1,4550 +0,0 @@
-/*
- * usb-host.c: ETRAX 100LX USB Host Controller Driver (HCD)
- *
- * Copyright (c) 2002, 2003 Axis Communications AB.
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/arch/svinto.h>
-
-#include <linux/usb.h>
-/* Ugly include because we don't live with the other host drivers. */
-#include <../drivers/usb/core/hcd.h>
-#include <../drivers/usb/core/usb.h>
-
-#include "hc_crisv10.h"
-
-#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR
-#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR
-#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR
-
-static const char *usb_hcd_version = "$Revision: 1.2 $";
-
-#undef KERN_DEBUG
-#define KERN_DEBUG ""
-
-
-#undef USB_DEBUG_RH
-#undef USB_DEBUG_EPID
-#undef USB_DEBUG_SB
-#undef USB_DEBUG_DESC
-#undef USB_DEBUG_URB
-#undef USB_DEBUG_TRACE
-#undef USB_DEBUG_BULK
-#undef USB_DEBUG_CTRL
-#undef USB_DEBUG_INTR
-#undef USB_DEBUG_ISOC
-
-#ifdef USB_DEBUG_RH
-#define dbg_rh(format, arg...) printk(KERN_DEBUG __FILE__ ": (RH) " format "\n" , ## arg)
-#else
-#define dbg_rh(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_EPID
-#define dbg_epid(format, arg...) printk(KERN_DEBUG __FILE__ ": (EPID) " format "\n" , ## arg)
-#else
-#define dbg_epid(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_SB
-#define dbg_sb(format, arg...) printk(KERN_DEBUG __FILE__ ": (SB) " format "\n" , ## arg)
-#else
-#define dbg_sb(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_CTRL
-#define dbg_ctrl(format, arg...) printk(KERN_DEBUG __FILE__ ": (CTRL) " format "\n" , ## arg)
-#else
-#define dbg_ctrl(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_BULK
-#define dbg_bulk(format, arg...) printk(KERN_DEBUG __FILE__ ": (BULK) " format "\n" , ## arg)
-#else
-#define dbg_bulk(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_INTR
-#define dbg_intr(format, arg...) printk(KERN_DEBUG __FILE__ ": (INTR) " format "\n" , ## arg)
-#else
-#define dbg_intr(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_ISOC
-#define dbg_isoc(format, arg...) printk(KERN_DEBUG __FILE__ ": (ISOC) " format "\n" , ## arg)
-#else
-#define dbg_isoc(format, arg...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_TRACE
-#define DBFENTER (printk(": Entering: %s\n", __FUNCTION__))
-#define DBFEXIT (printk(": Exiting: %s\n", __FUNCTION__))
-#else
-#define DBFENTER do {} while (0)
-#define DBFEXIT do {} while (0)
-#endif
-
-#define usb_pipeslow(pipe) (((pipe) >> 26) & 1)
-
-/*-------------------------------------------------------------------
- Virtual Root Hub
- -------------------------------------------------------------------*/
-
-static __u8 root_hub_dev_des[] =
-{
- 0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
- 0x00, /* __le16 bcdUSB; v1.0 */
- 0x01,
- 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
- 0x00, /* __u8 bDeviceSubClass; */
- 0x00, /* __u8 bDeviceProtocol; */
- 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
- 0x00, /* __le16 idVendor; */
- 0x00,
- 0x00, /* __le16 idProduct; */
- 0x00,
- 0x00, /* __le16 bcdDevice; */
- 0x00,
- 0x00, /* __u8 iManufacturer; */
- 0x02, /* __u8 iProduct; */
- 0x01, /* __u8 iSerialNumber; */
- 0x01 /* __u8 bNumConfigurations; */
-};
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x02, /* __u8 bDescriptorType; Configuration */
- 0x19, /* __le16 wTotalLength; */
- 0x00,
- 0x01, /* __u8 bNumInterfaces; */
- 0x01, /* __u8 bConfigurationValue; */
- 0x00, /* __u8 iConfiguration; */
- 0x40, /* __u8 bmAttributes; Bit 7: Bus-powered */
- 0x00, /* __u8 MaxPower; */
-
- /* interface */
- 0x09, /* __u8 if_bLength; */
- 0x04, /* __u8 if_bDescriptorType; Interface */
- 0x00, /* __u8 if_bInterfaceNumber; */
- 0x00, /* __u8 if_bAlternateSetting; */
- 0x01, /* __u8 if_bNumEndpoints; */
- 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
- 0x00, /* __u8 if_bInterfaceSubClass; */
- 0x00, /* __u8 if_bInterfaceProtocol; */
- 0x00, /* __u8 if_iInterface; */
-
- /* endpoint */
- 0x07, /* __u8 ep_bLength; */
- 0x05, /* __u8 ep_bDescriptorType; Endpoint */
- 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x08, /* __le16 ep_wMaxPacketSize; 8 Bytes */
- 0x00,
- 0xff /* __u8 ep_bInterval; 255 ms */
-};
-
-static __u8 root_hub_hub_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x29, /* __u8 bDescriptorType; Hub-descriptor */
- 0x02, /* __u8 bNbrPorts; */
- 0x00, /* __u16 wHubCharacteristics; */
- 0x00,
- 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
- 0x00, /* __u8 bHubContrCurrent; 0 mA */
- 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
- 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
-};
-
-static DEFINE_TIMER(bulk_start_timer, NULL, 0, 0);
-static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0);
-
-/* We want the start timer to expire before the eot timer, because the former might start
- traffic, thus making it unnecessary for the latter to time out. */
-#define BULK_START_TIMER_INTERVAL (HZ/10) /* 100 ms */
-#define BULK_EOT_TIMER_INTERVAL (HZ/10+2) /* 120 ms */
-
-#define OK(x) len = (x); dbg_rh("OK(%d): line: %d", x, __LINE__); break
-#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \
-{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);}
-
-#define SLAB_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
-#define KMALLOC_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL)
-
-/* Most helpful debugging aid */
-#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
-
-/* Alternative assert define which stops after a failed assert. */
-/*
-#define assert(expr) \
-{ \
- if (!(expr)) { \
- err("assert failed at line %d",__LINE__); \
- while (1); \
- } \
-}
-*/
-
-
-/* FIXME: Should RX_BUF_SIZE be a config option, or maybe we should adjust it dynamically?
- To adjust it dynamically we would have to get an interrupt when we reach the end
- of the rx descriptor list, or when we get close to the end, and then allocate more
- descriptors. */
-
-#define NBR_OF_RX_DESC 512
-#define RX_DESC_BUF_SIZE 1024
-#define RX_BUF_SIZE (NBR_OF_RX_DESC * RX_DESC_BUF_SIZE)
-
-/* The number of epids is, among other things, used for pre-allocating
- ctrl, bulk and isoc EP descriptors (one for each epid).
- Assumed to be > 1 when initiating the DMA lists. */
-#define NBR_OF_EPIDS 32
-
-/* Support interrupt traffic intervals up to 128 ms. */
-#define MAX_INTR_INTERVAL 128
-
-/* If periodic traffic (intr or isoc) is to be used, then one entry in the EP table
- must be "invalid". By this we mean that we shouldn't care about epid attentions
- for this epid, or at least handle them differently from epid attentions for "valid"
- epids. This define determines which one to use (don't change it). */
-#define INVALID_EPID 31
-/* A special epid for the bulk dummys. */
-#define DUMMY_EPID 30
-
-/* This is just a software cache for the valid entries in R_USB_EPT_DATA. */
-static __u32 epid_usage_bitmask;
-
-/* A bitfield to keep information on in/out traffic is needed to uniquely identify
- an endpoint on a device, since the most significant bit which indicates traffic
- direction is lacking in the ep_id field (ETRAX epids can handle both in and
- out traffic on endpoints that are otherwise identical). The USB framework, however,
- relies on them to be handled separately. For example, bulk IN and OUT urbs cannot
- be queued in the same list, since they would block each other. */
-static __u32 epid_out_traffic;
-
-/* DMA IN cache bug. Align the DMA IN buffers to 32 bytes, i.e. a cache line.
- Since RX_DESC_BUF_SIZE is 1024 is a multiple of 32, all rx buffers will be cache aligned. */
-static volatile unsigned char RxBuf[RX_BUF_SIZE] __attribute__ ((aligned (32)));
-static volatile USB_IN_Desc_t RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4)));
-
-/* Pointers into RxDescList. */
-static volatile USB_IN_Desc_t *myNextRxDesc;
-static volatile USB_IN_Desc_t *myLastRxDesc;
-static volatile USB_IN_Desc_t *myPrevRxDesc;
-
-/* EP descriptors must be 32-bit aligned. */
-static volatile USB_EP_Desc_t TxCtrlEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
-static volatile USB_EP_Desc_t TxBulkEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
-/* After each enabled bulk EP (IN or OUT) we put two disabled EP descriptors with the eol flag set,
- causing the DMA to stop the DMA channel. The first of these two has the intr flag set, which
- gives us a dma8_sub0_descr interrupt. When we receive this, we advance the DMA one step in the
- EP list and then restart the bulk channel, thus forcing a switch between bulk EP descriptors
- in each frame. */
-static volatile USB_EP_Desc_t TxBulkDummyEPList[NBR_OF_EPIDS][2] __attribute__ ((aligned (4)));
-
-static volatile USB_EP_Desc_t TxIsocEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4)));
-static volatile USB_SB_Desc_t TxIsocSB_zout __attribute__ ((aligned (4)));
-
-static volatile USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));
-static volatile USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));
-
-/* A zout transfer makes a memory access at the address of its buf pointer, which means that setting
- this buf pointer to 0 will cause an access to the flash. In addition to this, setting sw_len to 0
- results in a 16/32 bytes (depending on DMA burst size) transfer. Instead, we set it to 1, and point
- it to this buffer. */
-static int zout_buffer[4] __attribute__ ((aligned (4)));
-
-/* Cache for allocating new EP and SB descriptors. */
-static struct kmem_cache *usb_desc_cache;
-
-/* Cache for the registers allocated in the top half. */
-static struct kmem_cache *top_half_reg_cache;
-
-/* Cache for the data allocated in the isoc descr top half. */
-static struct kmem_cache *isoc_compl_cache;
-
-static struct usb_bus *etrax_usb_bus;
-
-/* This is a circular (double-linked) list of the active urbs for each epid.
- The head is never removed, and new urbs are linked onto the list as
- urb_entry_t elements. Don't reference urb_list directly; use the wrapper
- functions instead. Note that working with these lists might require spinlock
- protection. */
-static struct list_head urb_list[NBR_OF_EPIDS];
-
-/* Read about the need and usage of this lock in submit_ctrl_urb. */
-static spinlock_t urb_list_lock;
-
-/* Used when unlinking asynchronously. */
-static struct list_head urb_unlink_list;
-
-/* for returning string descriptors in UTF-16LE */
-static int ascii2utf (char *ascii, __u8 *utf, int utfmax)
-{
- int retval;
-
- for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
- *utf++ = *ascii++ & 0x7f;
- *utf++ = 0;
- }
- return retval;
-}
-
-static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
-{
- char buf [30];
-
- // assert (len > (2 * (sizeof (buf) + 1)));
- // assert (strlen (type) <= 8);
-
- // language ids
- if (id == 0) {
- *data++ = 4; *data++ = 3; /* 4 bytes data */
- *data++ = 0; *data++ = 0; /* some language id */
- return 4;
-
- // serial number
- } else if (id == 1) {
- sprintf (buf, "%x", serial);
-
- // product description
- } else if (id == 2) {
- sprintf (buf, "USB %s Root Hub", type);
-
- // id 3 == vendor description
-
- // unsupported IDs --> "stall"
- } else
- return 0;
-
- data [0] = 2 + ascii2utf (buf, data + 2, len - 2);
- data [1] = 3;
- return data [0];
-}
-
-/* Wrappers around the list functions (include/linux/list.h). */
-
-static inline int urb_list_empty(int epid)
-{
- return list_empty(&urb_list[epid]);
-}
-
-/* Returns first urb for this epid, or NULL if list is empty. */
-static inline struct urb *urb_list_first(int epid)
-{
- struct urb *first_urb = 0;
-
- if (!urb_list_empty(epid)) {
- /* Get the first urb (i.e. head->next). */
- urb_entry_t *urb_entry = list_entry((&urb_list[epid])->next, urb_entry_t, list);
- first_urb = urb_entry->urb;
- }
- return first_urb;
-}
-
-/* Adds an urb_entry last in the list for this epid. */
-static inline void urb_list_add(struct urb *urb, int epid)
-{
- urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG);
- assert(urb_entry);
-
- urb_entry->urb = urb;
- list_add_tail(&urb_entry->list, &urb_list[epid]);
-}
-
-/* Search through the list for an element that contains this urb. (The list
- is expected to be short and the one we are about to delete will often be
- the first in the list.) */
-static inline urb_entry_t *__urb_list_entry(struct urb *urb, int epid)
-{
- struct list_head *entry;
- struct list_head *tmp;
- urb_entry_t *urb_entry;
-
- list_for_each_safe(entry, tmp, &urb_list[epid]) {
- urb_entry = list_entry(entry, urb_entry_t, list);
- assert(urb_entry);
- assert(urb_entry->urb);
-
- if (urb_entry->urb == urb) {
- return urb_entry;
- }
- }
- return 0;
-}
-
-/* Delete an urb from the list. */
-static inline void urb_list_del(struct urb *urb, int epid)
-{
- urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
- assert(urb_entry);
-
- /* Delete entry and free. */
- list_del(&urb_entry->list);
- kfree(urb_entry);
-}
-
-/* Move an urb to the end of the list. */
-static inline void urb_list_move_last(struct urb *urb, int epid)
-{
- urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
- assert(urb_entry);
-
- list_move_tail(&urb_entry->list, &urb_list[epid]);
-}
-
-/* Get the next urb in the list. */
-static inline struct urb *urb_list_next(struct urb *urb, int epid)
-{
- urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
-
- assert(urb_entry);
-
- if (urb_entry->list.next != &urb_list[epid]) {
- struct list_head *elem = urb_entry->list.next;
- urb_entry = list_entry(elem, urb_entry_t, list);
- return urb_entry->urb;
- } else {
- return NULL;
- }
-}
-
-
-
-/* For debug purposes only. */
-static inline void urb_list_dump(int epid)
-{
- struct list_head *entry;
- struct list_head *tmp;
- urb_entry_t *urb_entry;
- int i = 0;
-
- info("Dumping urb list for epid %d", epid);
-
- list_for_each_safe(entry, tmp, &urb_list[epid]) {
- urb_entry = list_entry(entry, urb_entry_t, list);
- info(" entry %d, urb = 0x%lx", i, (unsigned long)urb_entry->urb);
- }
-}
-
-static void init_rx_buffers(void);
-static int etrax_rh_unlink_urb(struct urb *urb);
-static void etrax_rh_send_irq(struct urb *urb);
-static void etrax_rh_init_int_timer(struct urb *urb);
-static void etrax_rh_int_timer_do(unsigned long ptr);
-
-static int etrax_usb_setup_epid(struct urb *urb);
-static int etrax_usb_lookup_epid(struct urb *urb);
-static int etrax_usb_allocate_epid(void);
-static void etrax_usb_free_epid(int epid);
-
-static int etrax_remove_from_sb_list(struct urb *urb);
-
-static void* etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size,
- unsigned mem_flags, dma_addr_t *dma);
-static void etrax_usb_buffer_free(struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma);
-
-static void etrax_usb_add_to_bulk_sb_list(struct urb *urb, int epid);
-static void etrax_usb_add_to_ctrl_sb_list(struct urb *urb, int epid);
-static void etrax_usb_add_to_intr_sb_list(struct urb *urb, int epid);
-static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid);
-
-static int etrax_usb_submit_bulk_urb(struct urb *urb);
-static int etrax_usb_submit_ctrl_urb(struct urb *urb);
-static int etrax_usb_submit_intr_urb(struct urb *urb);
-static int etrax_usb_submit_isoc_urb(struct urb *urb);
-
-static int etrax_usb_submit_urb(struct urb *urb, unsigned mem_flags);
-static int etrax_usb_unlink_urb(struct urb *urb, int status);
-static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
-
-static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc);
-static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc);
-static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc);
-static void etrax_usb_hc_interrupt_bottom_half(void *data);
-
-static void etrax_usb_isoc_descr_interrupt_bottom_half(void *data);
-
-
-/* The following is a list of interrupt handlers for the host controller interrupts we use.
- They are called from etrax_usb_hc_interrupt_bottom_half. */
-static void etrax_usb_hc_isoc_eof_interrupt(void);
-static void etrax_usb_hc_bulk_eot_interrupt(int timer_induced);
-static void etrax_usb_hc_epid_attn_interrupt(usb_interrupt_registers_t *reg);
-static void etrax_usb_hc_port_status_interrupt(usb_interrupt_registers_t *reg);
-static void etrax_usb_hc_ctl_status_interrupt(usb_interrupt_registers_t *reg);
-
-static int etrax_rh_submit_urb (struct urb *urb);
-
-/* Forward declaration needed because they are used in the rx interrupt routine. */
-static void etrax_usb_complete_urb(struct urb *urb, int status);
-static void etrax_usb_complete_bulk_urb(struct urb *urb, int status);
-static void etrax_usb_complete_ctrl_urb(struct urb *urb, int status);
-static void etrax_usb_complete_intr_urb(struct urb *urb, int status);
-static void etrax_usb_complete_isoc_urb(struct urb *urb, int status);
-
-static int etrax_usb_hc_init(void);
-static void etrax_usb_hc_cleanup(void);
-
-static struct usb_operations etrax_usb_device_operations =
-{
- .get_frame_number = etrax_usb_get_frame_number,
- .submit_urb = etrax_usb_submit_urb,
- .unlink_urb = etrax_usb_unlink_urb,
- .buffer_alloc = etrax_usb_buffer_alloc,
- .buffer_free = etrax_usb_buffer_free
-};
-
-/* Note that these functions are always available in their "__" variants, for use in
- error situations. The "__" missing variants are controlled by the USB_DEBUG_DESC/
- USB_DEBUG_URB macros. */
-static void __dump_urb(struct urb* purb)
-{
- printk("\nurb :0x%08lx\n", (unsigned long)purb);
- printk("dev :0x%08lx\n", (unsigned long)purb->dev);
- printk("pipe :0x%08x\n", purb->pipe);
- printk("status :%d\n", purb->status);
- printk("transfer_flags :0x%08x\n", purb->transfer_flags);
- printk("transfer_buffer :0x%08lx\n", (unsigned long)purb->transfer_buffer);
- printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
- printk("actual_length :%d\n", purb->actual_length);
- printk("setup_packet :0x%08lx\n", (unsigned long)purb->setup_packet);
- printk("start_frame :%d\n", purb->start_frame);
- printk("number_of_packets :%d\n", purb->number_of_packets);
- printk("interval :%d\n", purb->interval);
- printk("error_count :%d\n", purb->error_count);
- printk("context :0x%08lx\n", (unsigned long)purb->context);
- printk("complete :0x%08lx\n\n", (unsigned long)purb->complete);
-}
-
-static void __dump_in_desc(volatile USB_IN_Desc_t *in)
-{
- printk("\nUSB_IN_Desc at 0x%08lx\n", (unsigned long)in);
- printk(" sw_len : 0x%04x (%d)\n", in->sw_len, in->sw_len);
- printk(" command : 0x%04x\n", in->command);
- printk(" next : 0x%08lx\n", in->next);
- printk(" buf : 0x%08lx\n", in->buf);
- printk(" hw_len : 0x%04x (%d)\n", in->hw_len, in->hw_len);
- printk(" status : 0x%04x\n\n", in->status);
-}
-
-static void __dump_sb_desc(volatile USB_SB_Desc_t *sb)
-{
- char tt = (sb->command & 0x30) >> 4;
- char *tt_string;
-
- switch (tt) {
- case 0:
- tt_string = "zout";
- break;
- case 1:
- tt_string = "in";
- break;
- case 2:
- tt_string = "out";
- break;
- case 3:
- tt_string = "setup";
- break;
- default:
- tt_string = "unknown (weird)";
- }
-
- printk("\n USB_SB_Desc at 0x%08lx\n", (unsigned long)sb);
- printk(" command : 0x%04x\n", sb->command);
- printk(" rem : %d\n", (sb->command & 0x3f00) >> 8);
- printk(" full : %d\n", (sb->command & 0x40) >> 6);
- printk(" tt : %d (%s)\n", tt, tt_string);
- printk(" intr : %d\n", (sb->command & 0x8) >> 3);
- printk(" eot : %d\n", (sb->command & 0x2) >> 1);
- printk(" eol : %d\n", sb->command & 0x1);
- printk(" sw_len : 0x%04x (%d)\n", sb->sw_len, sb->sw_len);
- printk(" next : 0x%08lx\n", sb->next);
- printk(" buf : 0x%08lx\n\n", sb->buf);
-}
-
-
-static void __dump_ep_desc(volatile USB_EP_Desc_t *ep)
-{
- printk("\nUSB_EP_Desc at 0x%08lx\n", (unsigned long)ep);
- printk(" command : 0x%04x\n", ep->command);
- printk(" ep_id : %d\n", (ep->command & 0x1f00) >> 8);
- printk(" enable : %d\n", (ep->command & 0x10) >> 4);
- printk(" intr : %d\n", (ep->command & 0x8) >> 3);
- printk(" eof : %d\n", (ep->command & 0x2) >> 1);
- printk(" eol : %d\n", ep->command & 0x1);
- printk(" hw_len : 0x%04x (%d)\n", ep->hw_len, ep->hw_len);
- printk(" next : 0x%08lx\n", ep->next);
- printk(" sub : 0x%08lx\n\n", ep->sub);
-}
-
-static inline void __dump_ep_list(int pipe_type)
-{
- volatile USB_EP_Desc_t *ep;
- volatile USB_EP_Desc_t *first_ep;
- volatile USB_SB_Desc_t *sb;
-
- switch (pipe_type)
- {
- case PIPE_BULK:
- first_ep = &TxBulkEPList[0];
- break;
- case PIPE_CONTROL:
- first_ep = &TxCtrlEPList[0];
- break;
- case PIPE_INTERRUPT:
- first_ep = &TxIntrEPList[0];
- break;
- case PIPE_ISOCHRONOUS:
- first_ep = &TxIsocEPList[0];
- break;
- default:
- warn("Cannot dump unknown traffic type");
- return;
- }
- ep = first_ep;
-
- printk("\n\nDumping EP list...\n\n");
-
- do {
- __dump_ep_desc(ep);
- /* Cannot phys_to_virt on 0 as it turns into 80000000, which is != 0. */
- sb = ep->sub ? phys_to_virt(ep->sub) : 0;
- while (sb) {
- __dump_sb_desc(sb);
- sb = sb->next ? phys_to_virt(sb->next) : 0;
- }
- ep = (volatile USB_EP_Desc_t *)(phys_to_virt(ep->next));
-
- } while (ep != first_ep);
-}
-
-static inline void __dump_ept_data(int epid)
-{
- unsigned long flags;
- __u32 r_usb_ept_data;
-
- if (epid < 0 || epid > 31) {
- printk("Cannot dump ept data for invalid epid %d\n", epid);
- return;
- }
-
- save_flags(flags);
- cli();
- *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
- nop();
- r_usb_ept_data = *R_USB_EPT_DATA;
- restore_flags(flags);
-
- printk("\nR_USB_EPT_DATA = 0x%x for epid %d :\n", r_usb_ept_data, epid);
- if (r_usb_ept_data == 0) {
- /* No need for more detailed printing. */
- return;
- }
- printk(" valid : %d\n", (r_usb_ept_data & 0x80000000) >> 31);
- printk(" hold : %d\n", (r_usb_ept_data & 0x40000000) >> 30);
- printk(" error_count_in : %d\n", (r_usb_ept_data & 0x30000000) >> 28);
- printk(" t_in : %d\n", (r_usb_ept_data & 0x08000000) >> 27);
- printk(" low_speed : %d\n", (r_usb_ept_data & 0x04000000) >> 26);
- printk(" port : %d\n", (r_usb_ept_data & 0x03000000) >> 24);
- printk(" error_code : %d\n", (r_usb_ept_data & 0x00c00000) >> 22);
- printk(" t_out : %d\n", (r_usb_ept_data & 0x00200000) >> 21);
- printk(" error_count_out : %d\n", (r_usb_ept_data & 0x00180000) >> 19);
- printk(" max_len : %d\n", (r_usb_ept_data & 0x0003f800) >> 11);
- printk(" ep : %d\n", (r_usb_ept_data & 0x00000780) >> 7);
- printk(" dev : %d\n", (r_usb_ept_data & 0x0000003f));
-}
-
-static inline void __dump_ept_data_list(void)
-{
- int i;
-
- printk("Dumping the whole R_USB_EPT_DATA list\n");
-
- for (i = 0; i < 32; i++) {
- __dump_ept_data(i);
- }
-}
-#ifdef USB_DEBUG_DESC
-#define dump_in_desc(...) __dump_in_desc(...)
-#define dump_sb_desc(...) __dump_sb_desc(...)
-#define dump_ep_desc(...) __dump_ep_desc(...)
-#else
-#define dump_in_desc(...) do {} while (0)
-#define dump_sb_desc(...) do {} while (0)
-#define dump_ep_desc(...) do {} while (0)
-#endif
-
-#ifdef USB_DEBUG_URB
-#define dump_urb(x) __dump_urb(x)
-#else
-#define dump_urb(x) do {} while (0)
-#endif
-
-static void init_rx_buffers(void)
-{
- int i;
-
- DBFENTER;
-
- for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) {
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].command = 0;
- RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]);
- RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
- RxDescList[i].hw_len = 0;
- RxDescList[i].status = 0;
-
- /* DMA IN cache bug. (struct etrax_dma_descr has the same layout as USB_IN_Desc
- for the relevant fields.) */
- prepare_rx_descriptor((struct etrax_dma_descr*)&RxDescList[i]);
-
- }
-
- RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
- RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes);
- RxDescList[i].next = virt_to_phys(&RxDescList[0]);
- RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE));
- RxDescList[i].hw_len = 0;
- RxDescList[i].status = 0;
-
- myNextRxDesc = &RxDescList[0];
- myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
- myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
-
- *R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc);
- *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start);
-
- DBFEXIT;
-}
-
-static void init_tx_bulk_ep(void)
-{
- int i;
-
- DBFENTER;
-
- for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {
- CHECK_ALIGN(&TxBulkEPList[i]);
- TxBulkEPList[i].hw_len = 0;
- TxBulkEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
- TxBulkEPList[i].sub = 0;
- TxBulkEPList[i].next = virt_to_phys(&TxBulkEPList[i + 1]);
-
- /* Initiate two EPs, disabled and with the eol flag set. No need for any
- preserved epid. */
-
- /* The first one has the intr flag set so we get an interrupt when the DMA
- channel is about to become disabled. */
- CHECK_ALIGN(&TxBulkDummyEPList[i][0]);
- TxBulkDummyEPList[i][0].hw_len = 0;
- TxBulkDummyEPList[i][0].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) |
- IO_STATE(USB_EP_command, eol, yes) |
- IO_STATE(USB_EP_command, intr, yes));
- TxBulkDummyEPList[i][0].sub = 0;
- TxBulkDummyEPList[i][0].next = virt_to_phys(&TxBulkDummyEPList[i][1]);
-
- /* The second one. */
- CHECK_ALIGN(&TxBulkDummyEPList[i][1]);
- TxBulkDummyEPList[i][1].hw_len = 0;
- TxBulkDummyEPList[i][1].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) |
- IO_STATE(USB_EP_command, eol, yes));
- TxBulkDummyEPList[i][1].sub = 0;
- /* The last dummy's next pointer is the same as the current EP's next pointer. */
- TxBulkDummyEPList[i][1].next = virt_to_phys(&TxBulkEPList[i + 1]);
- }
-
- /* Configure the last one. */
- CHECK_ALIGN(&TxBulkEPList[i]);
- TxBulkEPList[i].hw_len = 0;
- TxBulkEPList[i].command = (IO_STATE(USB_EP_command, eol, yes) |
- IO_FIELD(USB_EP_command, epid, i));
- TxBulkEPList[i].sub = 0;
- TxBulkEPList[i].next = virt_to_phys(&TxBulkEPList[0]);
-
- /* No need configuring dummy EPs for the last one as it will never be used for
- bulk traffic (i == INVALD_EPID at this point). */
-
- /* Set up to start on the last EP so we will enable it when inserting traffic
- for the first time (imitating the situation where the DMA has stopped
- because there was no more traffic). */
- *R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[i]);
- /* No point in starting the bulk channel yet.
- *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); */
- DBFEXIT;
-}
-
-static void init_tx_ctrl_ep(void)
-{
- int i;
-
- DBFENTER;
-
- for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {
- CHECK_ALIGN(&TxCtrlEPList[i]);
- TxCtrlEPList[i].hw_len = 0;
- TxCtrlEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
- TxCtrlEPList[i].sub = 0;
- TxCtrlEPList[i].next = virt_to_phys(&TxCtrlEPList[i + 1]);
- }
-
- CHECK_ALIGN(&TxCtrlEPList[i]);
- TxCtrlEPList[i].hw_len = 0;
- TxCtrlEPList[i].command = (IO_STATE(USB_EP_command, eol, yes) |
- IO_FIELD(USB_EP_command, epid, i));
-
- TxCtrlEPList[i].sub = 0;
- TxCtrlEPList[i].next = virt_to_phys(&TxCtrlEPList[0]);
-
- *R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[0]);
- *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
-
- DBFEXIT;
-}
-
-
-static void init_tx_intr_ep(void)
-{
- int i;
-
- DBFENTER;
-
- /* Read comment at zout_buffer declaration for an explanation to this. */
- TxIntrSB_zout.sw_len = 1;
- TxIntrSB_zout.next = 0;
- TxIntrSB_zout.buf = virt_to_phys(&zout_buffer[0]);
- TxIntrSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, zout) |
- IO_STATE(USB_SB_command, full, yes) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes));
-
- for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) {
- CHECK_ALIGN(&TxIntrEPList[i]);
- TxIntrEPList[i].hw_len = 0;
- TxIntrEPList[i].command =
- (IO_STATE(USB_EP_command, eof, yes) |
- IO_STATE(USB_EP_command, enable, yes) |
- IO_FIELD(USB_EP_command, epid, INVALID_EPID));
- TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
- TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[i + 1]);
- }
-
- CHECK_ALIGN(&TxIntrEPList[i]);
- TxIntrEPList[i].hw_len = 0;
- TxIntrEPList[i].command =
- (IO_STATE(USB_EP_command, eof, yes) |
- IO_STATE(USB_EP_command, eol, yes) |
- IO_STATE(USB_EP_command, enable, yes) |
- IO_FIELD(USB_EP_command, epid, INVALID_EPID));
- TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout);
- TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[0]);
-
- *R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]);
- *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
- DBFEXIT;
-}
-
-static void init_tx_isoc_ep(void)
-{
- int i;
-
- DBFENTER;
-
- /* Read comment at zout_buffer declaration for an explanation to this. */
- TxIsocSB_zout.sw_len = 1;
- TxIsocSB_zout.next = 0;
- TxIsocSB_zout.buf = virt_to_phys(&zout_buffer[0]);
- TxIsocSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) |
- IO_STATE(USB_SB_command, tt, zout) |
- IO_STATE(USB_SB_command, full, yes) |
- IO_STATE(USB_SB_command, eot, yes) |
- IO_STATE(USB_SB_command, eol, yes));
-
- /* The last isochronous EP descriptor is a dummy. */
-
- for (i = 0; i < (NBR_OF_EPIDS - 1); i++) {
- CHECK_ALIGN(&TxIsocEPList[i]);
- TxIsocEPList[i].hw_len = 0;
- TxIsocEPList[i].command = IO_FIELD(USB_EP_command, epid, i);
- TxIsocEPList[i].sub = 0;
- TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[i + 1]);
- }
-
- CHECK_ALIGN(&TxIsocEPList[i]);
- TxIsocEPList[i].hw_len = 0;
-
- /* Must enable the last EP descr to get eof interrupt. */
- TxIsocEPList[i].command = (IO_STATE(USB_EP_command, enable, yes) |
- IO_STATE(USB_EP_command, eof, yes) |
- IO_STATE(USB_EP_command, eol, yes) |
- IO_FIELD(USB_EP_command, epid, INVALID_EPID));
- TxIsocEPList[i].sub = virt_to_phys(&TxIsocSB_zout);
- TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[0]);
-
- *R_DMA_CH8_SUB3_EP = virt_to_phys(&TxIsocEPList[0]);
- *R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start);
-
- DBFEXIT;
-}
-
-static void etrax_usb_unlink_intr_urb(struct urb *urb)
-{
- volatile USB_EP_Desc_t *first_ep; /* First EP in the list. */
- volatile USB_EP_Desc_t *curr_ep; /* Current EP, the iterator. */
- volatile USB_EP_Desc_t *next_ep; /* The EP after current. */
- volatile USB_EP_Desc_t *unlink_ep; /* The one we should remove from the list. */
-
- int epid;
-
- /* Read 8.8.4 in Designer's Reference, "Removing an EP Descriptor from the List". */
-
- DBFENTER;
-
- epid = ((etrax_urb_priv_t *)urb->hcpriv)->epid;
-
- first_ep = &TxIntrEPList[0];
- curr_ep = first_ep;
-
-
- /* Note that this loop removes all EP descriptors with this epid. This assumes
- that all EP descriptors belong to the one and only urb for this epid. */
-
- do {
- next_ep = (USB_EP_Desc_t *)phys_to_virt(curr_ep->next);
-
- if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) {
-
- dbg_intr("Found EP to unlink for epid %d", epid);
-
- /* This is the one we should unlink. */
- unlink_ep = next_ep;
-
- /* Actually unlink the EP from the DMA list. */
- curr_ep->next = unlink_ep->next;
-
- /* Wait until the DMA is no longer at this descriptor. */
- while (*R_DMA_CH8_SUB2_EP == virt_to_phys(unlink_ep));
-
- /* Now we are free to remove it and its SB descriptor.
- Note that it is assumed here that there is only one sb in the
- sb list for this ep. */
- kmem_cache_free(usb_desc_cache, phys_to_virt(unlink_ep->sub));
- kmem_cache_free(usb_desc_cache, (USB_EP_Desc_t *)unlink_ep);
- }
-
- curr_ep = phys_to_virt(curr_ep->next);
-
- } while (curr_ep != first_ep);
- urb->hcpriv = NULL;
-}
-
-void etrax_usb_do_intr_recover(int epid)
-{
- USB_EP_Desc_t *first_ep, *tmp_ep;
-
- DBFENTER;
-
- first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP);
- tmp_ep = first_ep;
-
- /* What this does is simply to walk the list of interrupt
- ep descriptors and enable those that are disabled. */
-
- do {
- if (IO_EXTRACT(USB_EP_command, epid, tmp_ep->command) == epid &&
- !(tmp_ep->command & IO_MASK(USB_EP_command, enable))) {
- tmp_ep->command |= IO_STATE(USB_EP_command, enable, yes);
- }
-
- tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->next);
-
- } while (tmp_ep != first_ep);
-
-
- DBFEXIT;
-}
-
-static int etrax_rh_unlink_urb (struct urb *urb)
-{
- etrax_hc_t *hc;
-
- DBFENTER;
-
- hc = urb->dev->bus->hcpriv;
-
- if (hc->rh.urb == urb) {
- hc->rh.send = 0;
- del_timer(&hc->rh.rh_int_timer);
- }
-
- DBFEXIT;
- return 0;
-}
-
-static void etrax_rh_send_irq(struct urb *urb)
-{
- __u16 data = 0;
- etrax_hc_t *hc = urb->dev->bus->hcpriv;
- DBFENTER;
-
-/*
- dbg_rh("R_USB_FM_NUMBER : 0x%08X", *R_USB_FM_NUMBER);
- dbg_rh("R_USB_FM_REMAINING: 0x%08X", *R_USB_FM_REMAINING);
-*/
-
- data |= (hc->rh.wPortChange_1) ? (1 << 1) : 0;
- data |= (hc->rh.wPortChange_2) ? (1 << 2) : 0;
-
- *((__u16 *)urb->transfer_buffer) = cpu_to_le16(data);
- /* FIXME: Why is actual_length set to 1 when data is 2 bytes?
- Since only 1 byte is used, why not declare data as __u8? */
- urb->actual_length = 1;
- urb->status = 0;
-
- if (hc->rh.send && urb->complete) {
- dbg_rh("wPortChange_1: 0x%04X", hc->rh.wPortChange_1);
- dbg_rh("wPortChange_2: 0x%04X", hc->rh.wPortChange_2);
-
- urb->complete(urb, NULL);
- }
-
- DBFEXIT;
-}
-
-static void etrax_rh_init_int_timer(struct urb *urb)
-{
- etrax_hc_t *hc;
-
- DBFENTER;
-
- hc = urb->dev->bus->hcpriv;
- hc->rh.interval = urb->interval;
- init_timer(&hc->rh.rh_int_timer);
- hc->rh.rh_int_timer.function = etrax_rh_int_timer_do;
- hc->rh.rh_int_timer.data = (unsigned long)urb;
- /* FIXME: Is the jiffies resolution enough? All intervals < 10 ms will be mapped
- to 0, and the rest to the nearest lower 10 ms. */
- hc->rh.rh_int_timer.expires = jiffies + ((HZ * hc->rh.interval) / 1000);
- add_timer(&hc->rh.rh_int_timer);
-
- DBFEXIT;
-}
-
-static void etrax_rh_int_timer_do(unsigned long ptr)
-{
- struct urb *urb;
- etrax_hc_t *hc;
-
- DBFENTER;
-
- urb = (struct urb*)ptr;
- hc = urb->dev->bus->hcpriv;
-
- if (hc->rh.send) {
- etrax_rh_send_irq(urb);
- }
-
- DBFEXIT;
-}
-
-static int etrax_usb_setup_epid(struct urb *urb)
-{
- int epid;
- char devnum, endpoint, out_traffic, s