blob: 70a995cfafcc2036cb02ec5cbfd115c4a1d53fc2 [file] [log] [blame]
/*
* usb-host.c: ETRAX 100LX USB Host Controller Driver (HCD)
*
* Copyright (c) 2002, 2003 Axis Communications AB.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/unistd.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/version.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/svinto.h>
#include <linux/usb.h>
/* Ugly include because we don't live with the other host drivers. */
#include <../drivers/usb/hcd.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 4, 20)
typedef struct urb urb_t, *purb_t;
typedef struct iso_packet_descriptor iso_packet_descriptor_t;
typedef struct usb_ctrlrequest devrequest;
#endif
#include "usb-host.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.19 $";
#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(KERN_DEBUG __FILE__ ": Entering: " __FUNCTION__ "\n"))
#define DBFEXIT (printk(KERN_DEBUG __FILE__ ": Exiting: " __FUNCTION__ "\n"))
#else
#define DBFENTER do {} while (0)
#define DBFEXIT do {} while (0)
#endif
/*-------------------------------------------------------------------
Virtual Root Hub
-------------------------------------------------------------------*/
static __u8 root_hub_dev_des[] =
{
0x12, /* __u8 bLength; */
0x01, /* __u8 bDescriptorType; Device */
0x00, /* __u16 bcdUSB; v1.0 */
0x01,
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x00, /* __u8 bDeviceProtocol; */
0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
0x00, /* __u16 idVendor; */
0x00,
0x00, /* __u16 idProduct; */
0x00,
0x00, /* __u16 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, /* __u16 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, /* __u16 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 struct timer_list bulk_start_timer;
static struct timer_list bulk_eot_timer;
/* 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() ? SLAB_ATOMIC : SLAB_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 kmem_cache_t *usb_desc_cache;
/* Cache for the registers allocated in the top half. */
static kmem_cache_t *top_half_reg_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;
/* 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 urb_t *urb_list_first(int epid)
{
urb_t *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(urb_t *urb, int epid)
{
urb_entry_t *urb_entry = (urb_entry_t *)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(urb_t *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(urb_t *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(urb_t *urb, int epid)
{
urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
assert(urb_entry);
list_del(&urb_entry->list);
list_add_tail(&urb_entry->list, &urb_list[epid]);
}
/* 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(urb_t *urb);
static void etrax_rh_send_irq(urb_t *urb);
static void etrax_rh_init_int_timer(urb_t *urb);
static void etrax_rh_int_timer_do(unsigned long ptr);
static int etrax_usb_setup_epid(urb_t *urb);
static int etrax_usb_lookup_epid(urb_t *urb);
static int etrax_usb_allocate_epid(void);
static void etrax_usb_free_epid(int epid);
static int etrax_remove_from_sb_list(urb_t *urb);
static void etrax_usb_add_to_bulk_sb_list(urb_t *urb, int epid);
static void etrax_usb_add_to_ctrl_sb_list(urb_t *urb, int epid);
static void etrax_usb_add_to_intr_sb_list(urb_t *urb, int epid);
static void etrax_usb_add_to_isoc_sb_list(urb_t *urb, int epid);
static int etrax_usb_submit_bulk_urb(urb_t *urb);
static int etrax_usb_submit_ctrl_urb(urb_t *urb);
static int etrax_usb_submit_intr_urb(urb_t *urb);
static int etrax_usb_submit_isoc_urb(urb_t *urb);
static int etrax_usb_submit_urb(urb_t *urb);
static int etrax_usb_unlink_urb(urb_t *urb);
static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
static int etrax_usb_allocate_dev(struct usb_device *usb_dev);
static int etrax_usb_deallocate_dev(struct usb_device *usb_dev);
static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs);
static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);
static void etrax_usb_hc_interrupt_top_half(int irq, void *vhc, struct pt_regs *regs);
static void etrax_usb_hc_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 (urb_t *urb);
/* Forward declaration needed because they are used in the rx interrupt routine. */
static void etrax_usb_complete_urb(urb_t *urb, int status);
static void etrax_usb_complete_bulk_urb(urb_t *urb, int status);
static void etrax_usb_complete_ctrl_urb(urb_t *urb, int status);
static void etrax_usb_complete_intr_urb(urb_t *urb, int status);
static void etrax_usb_complete_isoc_urb(urb_t *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 =
{
etrax_usb_allocate_dev,
etrax_usb_deallocate_dev,
etrax_usb_get_frame_number,
etrax_usb_submit_urb,
etrax_usb_unlink_urb
};
/* 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(purb_t purb)
{
printk("\nurb :0x%08lx\n", (unsigned long)purb);
printk("next :0x%08lx\n", (unsigned long)purb->next);
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(urb_t *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);
}
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 (urb_t *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(urb_t *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 (data && 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);
}
/* DBFEXIT; */
}
static void etrax_rh_init_int_timer(urb_t *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)
{
urb_t *urb;
etrax_hc_t *hc;
/* DBFENTER; */
urb = (urb_t*)ptr;
hc = urb->dev->bus->hcpriv;
if (hc->rh.send) {
etrax_rh_send_irq(urb);
}
etrax_rh_init_int_timer(urb);
/* DBFEXIT; */
}
static int etrax_usb_setup_epid(urb_t *urb)
{
int epid;
char devnum, endpoint, out_traffic, slow;
int maxlen;
unsigned long flags;
DBFENTER;
epid = etrax_usb_lookup_epid(urb);
if ((epid != -1)){
/* An epid that fits this urb has been found. */
DBFEXIT;
return epid;
}
/* We must find and initiate a new epid for this urb. */
epid = etrax_usb_allocate_epid();
if (epid == -1) {
/* Failed to allocate a new epid. */
DBFEXIT;
return epid;
}
/* We now have a new epid to use. Initiate it. */
set_bit(epid, (void *)&epid_usage_bitmask);
devnum = usb_pipedevice(urb->pipe);
endpoint = usb_pipeendpoint(urb->pipe);
slow = usb_pipeslow(urb->pipe);
maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
/* We want both IN and OUT control traffic to be put on the same EP/SB list. */
out_traffic = 1;
} else {
out_traffic = usb_pipeout(urb->pipe);
}
save_flags(flags);
cli();
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
nop();
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
*R_USB_EPT_DATA_ISO = IO_STATE(R_USB_EPT_DATA_ISO, valid, yes) |
/* FIXME: Change any to the actual port? */
IO_STATE(R_USB_EPT_DATA_ISO, port, any) |
IO_FIELD(R_USB_EPT_DATA_ISO, max_len, maxlen) |
IO_FIELD(R_USB_EPT_DATA_ISO, ep, endpoint) |
IO_FIELD(R_USB_EPT_DATA_ISO, dev, devnum);
} else {
*R_USB_EPT_DATA = IO_STATE(R_USB_EPT_DATA, valid, yes) |
IO_FIELD(R_USB_EPT_DATA, low_speed, slow) |
/* FIXME: Change any to the actual port? */
IO_STATE(R_USB_EPT_DATA, port, any) |
IO_FIELD(R_USB_EPT_DATA, max_len, maxlen) |
IO_FIELD(R_USB_EPT_DATA, ep, endpoint) |
IO_FIELD(R_USB_EPT_DATA, dev, devnum);
}
restore_flags(flags);
if (out_traffic) {
set_bit(epid, (void *)&epid_out_traffic);
} else {
clear_bit(epid, (void *)&epid_out_traffic);
}
dbg_epid("Setting up epid %d with devnum %d, endpoint %d and max_len %d (%s)",
epid, devnum, endpoint, maxlen, out_traffic ? "OUT" : "IN");
DBFEXIT;
return epid;
}
static void etrax_usb_free_epid(int epid)
{
unsigned long flags;
DBFENTER;
if (!test_bit(epid, (void *)&epid_usage_bitmask)) {
warn("Trying to free unused epid %d", epid);
DBFEXIT;
return;
}
save_flags(flags);
cli();
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
nop();
while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold));
/* This will, among other things, set the valid field to 0. */
*R_USB_EPT_DATA = 0;
restore_flags(flags);
clear_bit(epid, (void *)&epid_usage_bitmask);
dbg_epid("Freed epid %d", epid);
DBFEXIT;
}
static int etrax_usb_lookup_epid(urb_t *urb)
{
int i;
__u32 data;
char devnum, endpoint, slow, out_traffic;
int maxlen;
unsigned long flags;
DBFENTER;
devnum = usb_pipedevice(urb->pipe);
endpoint = usb_pipeendpoint(urb->pipe);
slow = usb_pipeslow(urb->pipe);
maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
/* We want both IN and OUT control traffic to be put on the same EP/SB list. */
out_traffic = 1;
} else {
out_traffic = usb_pipeout(urb->pipe);
}
/* Step through att epids. */
for (i = 0; i < NBR_OF_EPIDS; i++) {
if (test_bit(i, (void *)&epid_usage_bitmask) &&
test_bit(i, (void *)&epid_out_traffic) == out_traffic) {
save_flags(flags);
cli();
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i);
nop();
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
data = *R_USB_EPT_DATA_ISO;
restore_flags(flags);
if ((IO_MASK(R_USB_EPT_DATA_ISO, valid) & data) &&
(IO_EXTRACT(R_USB_EPT_DATA_ISO, dev, data) == devnum) &&
(IO_EXTRACT(R_USB_EPT_DATA_ISO, ep, data) == endpoint) &&
(IO_EXTRACT(R_USB_EPT_DATA_ISO, max_len, data) == maxlen)) {
dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)",
i, devnum, endpoint, out_traffic ? "OUT" : "IN");
DBFEXIT;
return i;
}
} else {
data = *R_USB_EPT_DATA;
restore_flags(flags);
if ((IO_MASK(R_USB_EPT_DATA, valid) & data) &&
(IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) &&
(IO_EXTRACT(R_USB_EPT_DATA, ep, data) == endpoint) &&
(IO_EXTRACT(R_USB_EPT_DATA, low_speed, data) == slow) &&
(IO_EXTRACT(R_USB_EPT_DATA, max_len, data) == maxlen)) {
dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)",
i, devnum, endpoint, out_traffic ? "OUT" : "IN");
DBFEXIT;
return i;
}
}
}
}
DBFEXIT;
return -1;
}
static int etrax_usb_allocate_epid(void)
{
int i;
DBFENTER;
for (i = 0; i < NBR_OF_EPIDS; i++) {
if (!test_bit(i, (void *)&epid_usage_bitmask)) {
dbg_epid("Found free epid %d", i);
DBFEXIT;
return i;
}
}
dbg_epid("Found no free epids");
DBFEXIT;
return -1;
}
static int etrax_usb_submit_urb(urb_t *urb)
{
etrax_hc_t *hc;
int ret = -EINVAL;
DBFENTER;
if (!urb->dev || !urb->dev->bus) {
return -ENODEV;
}
if (urb->next != NULL) {
/* Is it possible for urb to be the head of a list of urbs (via the urb's
next pointer), used for example in drivers for isochronous traffic.
I haven't seen a device driver that relies on it being used for submit
or unlink, so we warn about it and ignore it. */
warn("Urbs are linked, ignoring.");
}
if (urb->timeout) {
/* FIXME. */
warn("urb->timeout specified, ignoring.");
}
hc = (etrax_hc_t*)urb->dev->bus->hcpriv;
if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
/* This request is for the Virtual Root Hub. */
ret = etrax_rh_submit_urb(urb);
} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
ret = etrax_usb_submit_bulk_urb(urb);
} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
ret = etrax_usb_submit_ctrl_urb(urb);
} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
int bustime;
if (urb->bandwidth == 0) {
bustime = usb_check_bandwidth(urb->dev, urb);
if (bustime < 0) {
ret = bustime;
} else {
ret = etrax_usb_submit_intr_urb(urb);
if (ret == 0)
usb_claim_bandwidth(urb->dev, urb, bustime, 0);
}
} else {
/* Bandwidth already set. */
ret = etrax_usb_submit_intr_urb(urb);
}
} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
int bustime;
if (urb->bandwidth == 0) {
bustime = usb_check_bandwidth(urb->dev, urb);
if (bustime < 0) {
ret = bustime;
} else {
ret = etrax_usb_submit_isoc_urb(urb);
if (ret == 0)
usb_claim_bandwidth(urb->dev, urb, bustime, 0);
}
} else {
/* Bandwidth already set. */
ret = etrax_usb_submit_isoc_urb(urb);
}
}
DBFEXIT;
return ret;
}
static int etrax_usb_unlink_urb(urb_t *urb)
{
etrax_hc_t *hc;
etrax_urb_priv_t *urb_priv;
int epid;
DBFENTER;
if (!urb) {
return -EINVAL;
}
if (!urb->dev || !urb->dev->bus) {
return -ENODEV;
}
if (!urb->hcpriv) {
/* This happens if a device driver calls unlink on an urb that
was never submitted (lazy driver). */
return 0;
}
if (urb->transfer_flags & USB_ASYNC_UNLINK) {
/* FIXME. */
/* If USB_ASYNC_UNLINK is set:
unlink
move to a separate urb list
call complete at next sof with ECONNRESET
If not:
wait 1 ms
unlink
call complete with ENOENT
*/
warn("USB_ASYNC_UNLINK set, ignoring.");
}
/* One might think that urb->status = -EINPROGRESS would be a requirement for unlinking,
but that doesn't work for interrupt and isochronous traffic since they are completed
repeatedly, and urb->status is set then. That may in itself be a bug though. */
hc = urb->dev->bus->hcpriv;
urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
epid = urb_priv->epid;
/* Set the urb status (synchronous unlink). */
urb->status = -ENOENT;
urb_priv->urb_state = UNLINK;
if (usb_pipedevice(urb->pipe) == hc->rh.devnum) {
int ret;
ret = etrax_rh_unlink_urb(urb);
DBFEXIT;
return ret;
} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
dbg_bulk("Unlink of bulk urb (0x%lx)", (unsigned long)urb);
if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
/* The EP was enabled, disable it and wait. */
TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
/* Ah, the luxury of busy-wait. */
while (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[epid]));
}
/* Kicking dummy list out of the party. */
TxBulkEPList[epid].next = virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]);
} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
dbg_ctrl("Unlink of ctrl urb (0x%lx)", (unsigned long)urb);
if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
/* The EP was enabled, disable it and wait. */
TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
/* Ah, the luxury of busy-wait. */
while (*R_DMA_CH8_SUB1_EP == virt_to_phys(&TxCtrlEPList[epid]));
}
} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
dbg_intr("Unlink of intr urb (0x%lx)", (unsigned long)urb);
/* Separate function because it's a tad more complicated. */
etrax_usb_unlink_intr_urb(urb);
} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
dbg_isoc("Unlink of isoc urb (0x%lx)", (unsigned long)urb);
if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) {
/* The EP was enabled, disable it and wait. */
TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable);
/* Ah, the luxury of busy-wait. */
while (*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid]));
}
}
/* Note that we need to remove the urb from the urb list *before* removing its SB
descriptors. (This means that the isoc eof handler might get a null urb when we
are unlinking the last urb.) */
urb_list_del(urb, epid);
if (usb_pipetype(urb->pipe) == PIPE_BULK) {
TxBulkEPList[epid].sub = 0;
etrax_remove_from_sb_list(urb);
} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
TxCtrlEPList[epid].sub = 0;
etrax_remove_from_sb_list(urb);
} else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
/* Sanity check (should never happen). */
assert(urb_list_empty(epid));
/* Release allocated bandwidth. */
usb_release_bandwidth(urb->dev, urb, 0);
} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
if (usb_pipeout(urb->pipe)) {
/* FIXME: If the SB list isn't empty at this point, we need to set up
the EP descriptor again. */
} else {
/* For in traffic there is only one SB descriptor for each EP even
though there may be several urbs (all urbs point at the same SB). */
if (urb_list_empty(epid)) {
/* No more urbs, remove the SB. */
TxIsocEPList[epid].sub = 0;
etrax_remove_from_sb_list(urb);
}
}
/* Release allocated bandwidth. */
usb_release_bandwidth(urb->dev, urb, 1);
}
/* Must be done before calling completion handler. */
kfree(urb_priv);
urb->hcpriv = 0;
if (urb->complete) {
urb->complete(urb);
}
/* Free the epid if urb list is empty. */
if (urb_list_empty(epid)) {
etrax_usb_free_epid(epid);
}
DBFEXIT;
return 0;
}
static int etrax_usb_get_frame_number(struct usb_device *usb_dev)
{
DBFENTER;
DBFEXIT;
return (*R_USB_FM_NUMBER & 0x7ff);
}
static int etrax_usb_allocate_dev(struct usb_device *usb_dev)
{
DBFENTER;
DBFEXIT;
return 0;
}
static int etrax_usb_deallocate_dev(struct usb_device *usb_dev)
{
DBFENTER;
DBFEXIT;
return 0;
}
static void etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs)
{
DBFENTER;
/* This interrupt handler could be used when unlinking EP descriptors. */
if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) {
USB_EP_Desc_t *ep;
//dbg_bulk("dma8_sub0_descr (BULK) intr.");
/* It should be safe clearing the interrupt here, since we don't expect to get a new
one until we restart the bulk channel. */
*R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do);
/* Wait while the DMA is running (though we don't expect it to be). */
while (*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd));
/* Advance the DMA to the next EP descriptor. */
ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB0_EP);
//dbg_bulk("descr intr: DMA is at 0x%lx", (unsigned long)ep);
/* ep->next is already a physical address; no need for a virt_to_phys. */
*R_DMA_CH8_SUB0_EP = ep->next;
/* Start the DMA bulk channel again. */
*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
}
if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) {
dbg_ctrl("dma8_sub1_descr (CTRL) intr.");
*R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do);
}
if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) {
dbg_intr("dma8_sub2_descr (INTR) intr.");
*R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do);
}
if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) {
dbg_isoc("dma8_sub3_descr (ISOC) intr.");
*R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do);
}
DBFEXIT;
}
static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs)
{
urb_t *urb;
etrax_urb_priv_t *urb_priv;
int epid = 0;
unsigned long flags;
/* Isoc diagnostics. */
static int curr_fm = 0;
static int prev_fm = 0;
DBFENTER;
/* Clear this interrupt. */
*R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);
/* Note that this while loop assumes that all packets span only
one rx descriptor. */
/* The reason we cli here is that we call the driver's callback functions. */
save_flags(flags);
cli();
while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) {
epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status);
urb = urb_list_first(epid);
//printk("eop for epid %d, first urb 0x%lx\n", epid, (unsigned long)urb);
if (!urb) {
err("No urb for epid %d in rx interrupt", epid);
__dump_ept_data(epid);
goto skip_out;
}
/* Note that we cannot indescriminately assert(usb_pipein(urb->pipe)) since
ctrl pipes are not. */
if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) {
__u32 r_usb_ept_data;
warn("error in rx desc->status, epid %d, first urb = 0x%lx",
epid, (unsigned long)urb);
__dump_in_desc(myNextRxDesc);
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
nop();
r_usb_ept_data = *R_USB_EPT_DATA;
warn("R_USB_EPT_DATA for epid %d = 0x%x", epid, r_usb_ept_data);
warn("R_USB_STATUS = 0x%x", *R_USB_STATUS);
etrax_usb_complete_urb(urb, -EPROTO);
goto skip_out;
}
urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
assert(urb_priv);
if ((usb_pipetype(urb->pipe) == PIPE_BULK) ||
(usb_pipetype(urb->pipe) == PIPE_CONTROL) ||
(usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {
/* We get nodata for empty data transactions, and the rx descriptor's
hw_len field is not valid in that case. No data to copy in other
words. */
} else {
/* Make sure the data fits in the buffer. */
assert(urb_priv->rx_offset + myNextRxDesc->hw_len
<= urb->transfer_buffer_length);
memcpy(urb->transfer_buffer + urb_priv->rx_offset,
phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len);
urb_priv->rx_offset += myNextRxDesc->hw_len;
}
if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) {
etrax_usb_complete_urb(urb, 0);
}
} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
iso_packet_descriptor_t *packet;
if (urb_priv->urb_state == UNLINK) {
info("Ignoring rx data for urb being unlinked.");
goto skip_out;
} else if (urb_priv->urb_state == NOT_STARTED) {
info("What? Got rx data for urb that isn't started?");
goto skip_out;
}
packet = &urb->iso_frame_desc[urb_priv->isoc_packet_counter];
packet->status = 0;
if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) {
/* We get nodata for empty data transactions, and the rx descriptor's
hw_len field is not valid in that case. We copy 0 bytes however to
stay in synch. */
packet->actual_length = 0;
} else {
packet->actual_length = myNextRxDesc->hw_len;
/* Make sure the data fits in the buffer. */
assert(packet->actual_length <= packet->length);
memcpy(urb->transfer_buffer + packet->offset,
phys_to_virt(myNextRxDesc->buf), packet->actual_length);
}
/* Increment the packet counter. */
urb_priv->isoc_packet_counter++;
/* Note that we don't care about the eot field in the rx descriptor's status.
It will always be set for isoc traffic. */
if (urb->number_of_packets == urb_priv->isoc_packet_counter) {
/* Out-of-synch diagnostics. */
curr_fm = (*R_USB_FM_NUMBER & 0x7ff);
if (((prev_fm + urb_priv->isoc_packet_counter) % (0x7ff + 1)) != curr_fm) {
warn("Out of synch? Previous frame = %d, current frame = %d",
prev_fm, curr_fm);
}
prev_fm = curr_fm;
/* Complete the urb with status OK. */
etrax_usb_complete_isoc_urb(urb, 0);
/* Must set this to 0 since this urb is still active after
completion. */
urb_priv->isoc_packet_counter = 0;
}
}
skip_out:
/* DMA IN cache bug. Flush the DMA IN buffer from the cache. (struct etrax_dma_descr
has the same layout as USB_IN_Desc for the relevant fields.) */
prepare_rx_descriptor((struct etrax_dma_descr*)myNextRxDesc);
myPrevRxDesc = myNextRxDesc;
myPrevRxDesc->command |= IO_MASK(USB_IN_command, eol);
myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol);
myLastRxDesc = myPrevRxDesc;
myNextRxDesc->status = 0;
myNextRxDesc = phys_to_virt(myNextRxDesc->next);
}
restore_flags(flags);
DBFEXIT;
}
/* This function will unlink the SB descriptors associated with this urb. */
static int etrax_remove_from_sb_list(urb_t *urb)
{
USB_SB_Desc_t *next_sb, *first_sb, *last_sb;
etrax_urb_priv_t *urb_priv;
int i = 0;
DBFENTER;
urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
assert(urb_priv);
/* Just a sanity check. Since we don't fiddle with the DMA list the EP descriptor
doesn't really need to be disabled, it's just that we expect it to be. */
if (usb_pipetype(urb->pipe) == PIPE_BULK) {
assert(!(TxBulkEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable)));
} else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) {
assert(!(TxCtrlEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable)));
}
first_sb = urb_priv->first_sb;
last_sb = urb_priv->last_sb;
assert(first_sb);
assert(last_sb);
while (first_sb != last_sb) {
next_sb = (USB_SB_Desc_t *)phys_to_virt(first_sb->next);
kmem_cache_free(usb_desc_cache, first_sb);
first_sb = next_sb;
i++;
}
kmem_cache_free(usb_desc_cache, last_sb);
i++;
dbg_sb("%d SB descriptors freed", i);
/* Compare i with urb->number_of_packets for Isoc traffic.
Should be same when calling unlink_urb */
DBFEXIT;
return i;
}
static int etrax_usb_submit_bulk_urb(urb_t *urb)
{
int epid;
int empty;
unsigned long flags;
DBFENTER;
/* Epid allocation, empty check and list add must be protected.
Read about this in etrax_usb_submit_ctrl_urb. */
spin_lock_irqsave(&urb_list_lock, flags);
epid = etrax_usb_setup_epid(urb);
if (epid == -1) {
DBFEXIT;
spin_unlock_irqrestore(&urb_list_lock, flags);
return -ENOMEM;
}
empty = urb_list_empty(epid);
urb_list_add(urb, epid);
spin_unlock_irqrestore(&urb_list_lock, flags);
/* USB_QUEUE_BULK is UHCI-specific, but we warn anyway. */
if (!(urb->transfer_flags & USB_QUEUE_BULK) && !empty) {
warn("USB_QUEUE_BULK is not set and urb queue is not empty, ignoring.");
}
dbg_bulk("Adding bulk %s urb 0x%lx to %s list, epid %d",
usb_pipein(urb->pipe) ? "IN" : "OUT", (unsigned long)urb, empty ? "empty" : "", epid);
/* Mark the urb as being in progress. */
urb->status = -EINPROGRESS;
if (empty) {
etrax_usb_add_to_bulk_sb_list(urb, epid);
}
DBFEXIT;
return 0;
}
static void etrax_usb_add_to_bulk_sb_list(urb_t *urb, int epid)
{
USB_SB_Desc_t *sb_desc;
etrax_urb_priv_t *urb_priv;
unsigned long flags;
char maxlen;
DBFENTER;
dbg_bulk("etrax_usb_add_to_bulk_sb_list, urb 0x%lx", (unsigned long)urb);
maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
assert(urb_priv != NULL);
/* This sets rx_offset to 0. */
memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(sb_desc != NULL);
memset(sb_desc, 0, sizeof(USB_SB_Desc_t));
if (usb_pipeout(urb->pipe)) {
dbg_bulk("Grabbing bulk OUT, urb 0x%lx, epid %d", (unsigned long)urb, epid);
/* This is probably a sanity check of the bulk transaction length
not being larger than 64 kB. */
if (urb->transfer_buffer_length > 0xffff) {
panic("urb->transfer_buffer_length > 0xffff");
}
sb_desc->sw_len = urb->transfer_buffer_length;
/* The rem field is don't care if it's not a full-length transfer, so setting
it shouldn't hurt. Also, rem isn't used for OUT traffic. */
sb_desc->command = (IO_FIELD(USB_SB_command, rem, 0) |
IO_STATE(USB_SB_command, tt, out) |
IO_STATE(USB_SB_command, eot, yes) |
IO_STATE(USB_SB_command, eol, yes));
/* The full field is set to yes, even if we don't actually check that this is
a full-length transfer (i.e., that transfer_buffer_length % maxlen = 0).
Setting full prevents the USB controller from sending an empty packet in
that case. However, if USB_ZERO_PACKET was set we want that. */
if (!(urb->transfer_flags & USB_ZERO_PACKET)) {
sb_desc->command |= IO_STATE(USB_SB_command, full, yes);
}
sb_desc->buf = virt_to_phys(urb->transfer_buffer);
sb_desc->next = 0;
} else if (usb_pipein(urb->pipe)) {
dbg_bulk("Grabbing bulk IN, urb 0x%lx, epid %d", (unsigned long)urb, epid);
sb_desc->sw_len = urb->transfer_buffer_length ?
(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
/* The rem field is don't care if it's not a full-length transfer, so setting
it shouldn't hurt. */
sb_desc->command =
(IO_FIELD(USB_SB_command, rem,
urb->transfer_buffer_length % maxlen) |
IO_STATE(USB_SB_command, tt, in) |
IO_STATE(USB_SB_command, eot, yes) |
IO_STATE(USB_SB_command, eol, yes));
sb_desc->buf = 0;
sb_desc->next = 0;
}
urb_priv->first_sb = sb_desc;
urb_priv->last_sb = sb_desc;
urb_priv->epid = epid;
urb->hcpriv = urb_priv;
/* Reset toggle bits and reset error count. */
save_flags(flags);
cli();
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
nop();
/* FIXME: Is this a special case since the hold field is checked,
or should we check hold in a lot of other cases as well? */
if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
panic("Hold was set in %s", __FUNCTION__);
}
/* Reset error counters (regardless of which direction this traffic is). */
*R_USB_EPT_DATA &=
~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
IO_MASK(R_USB_EPT_DATA, error_count_out));
/* Software must preset the toggle bits. */
if (usb_pipeout(urb->pipe)) {
char toggle =
usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out);
*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle);
} else {
char toggle =
usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
*R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in);
*R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle);
}
/* Assert that the EP descriptor is disabled. */
assert(!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)));
/* The reason we set the EP's sub pointer directly instead of
walking the SB list and linking it last in the list is that we only
have one active urb at a time (the rest are queued). */
/* Note that we cannot have interrupts running when we have set the SB descriptor
but the EP is not yet enabled. If a bulk eot happens for another EP, we will
find this EP disabled and with a SB != 0, which will make us think that it's done. */
TxBulkEPList[epid].sub = virt_to_phys(sb_desc);
TxBulkEPList[epid].hw_len = 0;
/* Note that we don't have to fill in the ep_id field since this
was done when we allocated the EP descriptors in init_tx_bulk_ep. */
/* Check if the dummy list is already with us (if several urbs were queued). */
if (TxBulkEPList[epid].next != virt_to_phys(&TxBulkDummyEPList[epid][0])) {
dbg_bulk("Inviting dummy list to the party for urb 0x%lx, epid %d",
(unsigned long)urb, epid);
/* The last EP in the dummy list already has its next pointer set to
TxBulkEPList[epid].next. */
/* We don't need to check if the DMA is at this EP or not before changing the
next pointer, since we will do it in one 32-bit write (EP descriptors are
32-bit aligned). */
TxBulkEPList[epid].next = virt_to_phys(&TxBulkDummyEPList[epid][0]);
}
/* Enable the EP descr. */
dbg_bulk("Enabling bulk EP for urb 0x%lx, epid %d", (unsigned long)urb, epid);
TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
/* Everything is set up, safe to enable interrupts again. */
restore_flags(flags);
/* If the DMA bulk channel isn't running, we need to restart it if it
has stopped at the last EP descriptor (DMA stopped because there was
no more traffic) or if it has stopped at a dummy EP with the intr flag
set (DMA stopped because we were too slow in inserting new traffic). */
if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) {
USB_EP_Desc_t *ep;
ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB0_EP);
dbg_bulk("DMA channel not running in add");
dbg_bulk("DMA is at 0x%lx", (unsigned long)ep);
if (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[NBR_OF_EPIDS - 1]) ||
(ep->command & 0x8) >> 3) {
*R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start);
/* Update/restart the bulk start timer since we just started the channel. */
mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL);
/* Update/restart the bulk eot timer since we just inserted traffic. */
mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);
}
}
DBFEXIT;
}
static void etrax_usb_complete_bulk_urb(urb_t *urb, int status)
{
etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
int epid = urb_priv->epid;
unsigned long flags;
DBFENTER;
if (status)
warn("Completing bulk urb with status %d.", status);
dbg_bulk("Completing bulk urb 0x%lx for epid %d", (unsigned long)urb, epid);
/* Update the urb list. */
urb_list_del(urb, epid);
/* For an IN pipe, we always set the actual length, regardless of whether there was
an error or not (which means the device driver can use the data if it wants to). */
if (usb_pipein(urb->pipe)) {
urb->actual_length = urb_priv->rx_offset;
} else {
/* Set actual_length for OUT urbs also; the USB mass storage driver seems
to want that. We wouldn't know of any partial writes if there was an error. */
if (status == 0) {
urb->actual_length = urb->transfer_buffer_length;
} else {
urb->actual_length = 0;
}
}
/* FIXME: Is there something of the things below we shouldn't do if there was an error?
Like, maybe we shouldn't toggle the toggle bits, or maybe we shouldn't insert more traffic. */
save_flags(flags);
cli();
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
nop();
/* We need to fiddle with the toggle bits because the hardware doesn't do it for us. */
if (usb_pipeout(urb->pipe)) {
char toggle =
IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA);
usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe), toggle);
} else {
char toggle =
IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA);
usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe), toggle);
}
restore_flags(flags);
/* Remember to free the SBs. */
etrax_remove_from_sb_list(urb);
kfree(urb_priv);
urb->hcpriv = 0;
/* If there are any more urb's in the list we'd better start sending */
if (!urb_list_empty(epid)) {
urb_t *new_urb;
/* Get the first urb. */
new_urb = urb_list_first(epid);
assert(new_urb);
dbg_bulk("More bulk for epid %d", epid);
etrax_usb_add_to_bulk_sb_list(new_urb, epid);
}
urb->status = status;
/* We let any non-zero status from the layer above have precedence. */
if (status == 0) {
/* USB_DISABLE_SPD means that short reads (shorter than the endpoint's max length)
is to be treated as an error. */
if (urb->transfer_flags & USB_DISABLE_SPD) {
if (usb_pipein(urb->pipe) &&
(urb->actual_length !=
usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))) {
urb->status = -EREMOTEIO;
}
}
}
if (urb->complete) {
urb->complete(urb);
}
if (urb_list_empty(epid)) {
/* This means that this EP is now free, deconfigure it. */
etrax_usb_free_epid(epid);
/* No more traffic; time to clean up.
Must set sub pointer to 0, since we look at the sub pointer when handling
the bulk eot interrupt. */
dbg_bulk("No bulk for epid %d", epid);
TxBulkEPList[epid].sub = 0;
/* Unlink the dummy list. */
dbg_bulk("Kicking dummy list out of party for urb 0x%lx, epid %d",
(unsigned long)urb, epid);
/* No need to wait for the DMA before changing the next pointer.
The modulo NBR_OF_EPIDS isn't actually necessary, since we will never use
the last one (INVALID_EPID) for actual traffic. */
TxBulkEPList[epid].next =
virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]);
}
DBFEXIT;
}
static int etrax_usb_submit_ctrl_urb(urb_t *urb)
{
int epid;
int empty;
unsigned long flags;
DBFENTER;
/* FIXME: Return -ENXIO if there is already a queued urb for this endpoint? */
/* Epid allocation, empty check and list add must be protected.
Epid allocation because if we find an existing epid for this endpoint an urb might be
completed (emptying the list) before we add the new urb to the list, causing the epid
to be de-allocated. We would then start the transfer with an invalid epid -> epid attn.
Empty check and add because otherwise we might conclude that the list is not empty,
after which it becomes empty before we add the new urb to the list, causing us not to
insert the new traffic into the SB list. */
spin_lock_irqsave(&urb_list_lock, flags);
epid = etrax_usb_setup_epid(urb);
if (epid == -1) {
spin_unlock_irqrestore(&urb_list_lock, flags);
DBFEXIT;
return -ENOMEM;
}
empty = urb_list_empty(epid);
urb_list_add(urb, epid);
spin_unlock_irqrestore(&urb_list_lock, flags);
dbg_ctrl("Adding ctrl urb 0x%lx to %s list, epid %d",
(unsigned long)urb, empty ? "empty" : "", epid);
/* Mark the urb as being in progress. */
urb->status = -EINPROGRESS;
if (empty) {
etrax_usb_add_to_ctrl_sb_list(urb, epid);
}
DBFEXIT;
return 0;
}
static void etrax_usb_add_to_ctrl_sb_list(urb_t *urb, int epid)
{
USB_SB_Desc_t *sb_desc_setup;
USB_SB_Desc_t *sb_desc_data;
USB_SB_Desc_t *sb_desc_status;
etrax_urb_priv_t *urb_priv;
unsigned long flags;
char maxlen;
DBFENTER;
maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
assert(urb_priv != NULL);
/* This sets rx_offset to 0. */
memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
sb_desc_setup = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(sb_desc_setup != NULL);
sb_desc_status = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(sb_desc_status != NULL);
/* Initialize the mandatory setup SB descriptor (used only in control transfers) */
sb_desc_setup->sw_len = 8;
sb_desc_setup->command = (IO_FIELD(USB_SB_command, rem, 0) |
IO_STATE(USB_SB_command, tt, setup) |
IO_STATE(USB_SB_command, full, yes) |
IO_STATE(USB_SB_command, eot, yes));
sb_desc_setup->buf = virt_to_phys(urb->setup_packet);
if (usb_pipeout(urb->pipe)) {
dbg_ctrl("Transfer for epid %d is OUT", epid);
/* If this Control OUT transfer has an optional data stage we add an OUT token
before the mandatory IN (status) token, hence the reordered SB list */
sb_desc_setup->next = virt_to_phys(sb_desc_status);
if (urb->transfer_buffer) {
dbg_ctrl("This OUT transfer has an extra data stage");
sb_desc_data = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(sb_desc_data != NULL);
sb_desc_setup->next = virt_to_phys(sb_desc_data);
sb_desc_data->sw_len = urb->transfer_buffer_length;
sb_desc_data->command = (IO_STATE(USB_SB_command, tt, out) |
IO_STATE(USB_SB_command, full, yes) |
IO_STATE(USB_SB_command, eot, yes));
sb_desc_data->buf = virt_to_phys(urb->transfer_buffer);
sb_desc_data->next = virt_to_phys(sb_desc_status);
}
sb_desc_status->sw_len = 1;
sb_desc_status->command = (IO_FIELD(USB_SB_command, rem, 0) |
IO_STATE(USB_SB_command, tt, in) |
IO_STATE(USB_SB_command, eot, yes) |
IO_STATE(USB_SB_command, eol, yes));
sb_desc_status->buf = 0;
sb_desc_status->next = 0;
} else if (usb_pipein(urb->pipe)) {
dbg_ctrl("Transfer for epid %d is IN", epid);
dbg_ctrl("transfer_buffer_length = %d", urb->transfer_buffer_length);
dbg_ctrl("rem is calculated to %d", urb->transfer_buffer_length % maxlen);
sb_desc_data = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(sb_desc_data != NULL);
sb_desc_setup->next = virt_to_phys(sb_desc_data);
sb_desc_data->sw_len = urb->transfer_buffer_length ?
(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
dbg_ctrl("sw_len got %d", sb_desc_data->sw_len);
sb_desc_data->command =
(IO_FIELD(USB_SB_command, rem,
urb->transfer_buffer_length % maxlen) |
IO_STATE(USB_SB_command, tt, in) |
IO_STATE(USB_SB_command, eot, yes));
sb_desc_data->buf = 0;
sb_desc_data->next = virt_to_phys(sb_desc_status);
/* Read comment at zout_buffer declaration for an explanation to this. */
sb_desc_status->sw_len = 1;
sb_desc_status->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));
sb_desc_status->buf = virt_to_phys(&zout_buffer[0]);
sb_desc_status->next = 0;
}
urb_priv->first_sb = sb_desc_setup;
urb_priv->last_sb = sb_desc_status;
urb_priv->epid = epid;
urb->hcpriv = urb_priv;
/* Reset toggle bits and reset error count, remeber to di and ei */
/* Warning: it is possible that this locking doesn't work with bottom-halves */
save_flags(flags);
cli();
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
nop();
if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) {
panic("Hold was set in %s", __FUNCTION__);
}
/* FIXME: Compare with etrax_usb_add_to_bulk_sb_list where the toggle bits
are set to a specific value. Why the difference? Read "Transfer and Toggle Bits
in Designer's Reference, p. 8 - 11. */
*R_USB_EPT_DATA &=
~(IO_MASK(R_USB_EPT_DATA, error_count_in) |
IO_MASK(R_USB_EPT_DATA, error_count_out) |
IO_MASK(R_USB_EPT_DATA, t_in) |
IO_MASK(R_USB_EPT_DATA, t_out));
/* Since we use the rx interrupt to complete ctrl urbs, we can enable interrupts now
(i.e. we don't check the sub pointer on an eot interrupt like we do for bulk traffic). */
restore_flags(flags);
/* Assert that the EP descriptor is disabled. */
assert(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)));
/* Set up and enable the EP descriptor. */
TxCtrlEPList[epid].sub = virt_to_phys(sb_desc_setup);
TxCtrlEPList[epid].hw_len = 0;
TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
/* We start the DMA sub channel without checking if it's running or not, because:
1) If it's already running, issuing the start command is a nop.
2) We avoid a test-and-set race condition. */
*R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start);
DBFEXIT;
}
static void etrax_usb_complete_ctrl_urb(urb_t *urb, int status)
{
etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
int epid = urb_priv->epid;
DBFENTER;
if (status)
warn("Completing ctrl urb with status %d.", status);
dbg_ctrl("Completing ctrl epid %d, urb 0x%lx", epid, (unsigned long)urb);
/* Remove this urb from the list. */
urb_list_del(urb, epid);
/* For an IN pipe, we always set the actual length, regardless of whether there was
an error or not (which means the device driver can use the data if it wants to). */
if (usb_pipein(urb->pipe)) {
urb->actual_length = urb_priv->rx_offset;
}
/* FIXME: Is there something of the things below we shouldn't do if there was an error?
Like, maybe we shouldn't insert more traffic. */
/* Remember to free the SBs. */
etrax_remove_from_sb_list(urb);
kfree(urb_priv);
urb->hcpriv = 0;
/* If there are any more urbs in the list we'd better start sending. */
if (!urb_list_empty(epid)) {
urb_t *new_urb;
/* Get the first urb. */
new_urb = urb_list_first(epid);
assert(new_urb);
dbg_ctrl("More ctrl for epid %d, first urb = 0x%lx", epid, (unsigned long)new_urb);
etrax_usb_add_to_ctrl_sb_list(new_urb, epid);
}
urb->status = status;
/* We let any non-zero status from the layer above have precedence. */
if (status == 0) {
/* USB_DISABLE_SPD means that short reads (shorter than the endpoint's max length)
is to be treated as an error. */
if (urb->transfer_flags & USB_DISABLE_SPD) {
if (usb_pipein(urb->pipe) &&
(urb->actual_length !=
usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))) {
urb->status = -EREMOTEIO;
}
}
}
if (urb->complete) {
urb->complete(urb);
}
if (urb_list_empty(epid)) {
/* No more traffic. Time to clean up. */
etrax_usb_free_epid(epid);
/* Must set sub pointer to 0. */
dbg_ctrl("No ctrl for epid %d", epid);
TxCtrlEPList[epid].sub = 0;
}
DBFEXIT;
}
static int etrax_usb_submit_intr_urb(urb_t *urb)
{
int epid;
DBFENTER;
if (usb_pipeout(urb->pipe)) {
/* Unsupported transfer type.
We don't support interrupt out traffic. (If we do, we can't support
intervals for neither in or out traffic, but are forced to schedule all
interrupt traffic in one frame.) */
return -EINVAL;
}
epid = etrax_usb_setup_epid(urb);
if (epid == -1) {
DBFEXIT;
return -ENOMEM;
}
if (!urb_list_empty(epid)) {
/* There is already a queued urb for this endpoint. */
etrax_usb_free_epid(epid);
return -ENXIO;
}
urb->status = -EINPROGRESS;
dbg_intr("Add intr urb 0x%lx, to list, epid %d", (unsigned long)urb, epid);
urb_list_add(urb, epid);
etrax_usb_add_to_intr_sb_list(urb, epid);
return 0;
DBFEXIT;
}
static void etrax_usb_add_to_intr_sb_list(urb_t *urb, int epid)
{
volatile USB_EP_Desc_t *tmp_ep;
volatile USB_EP_Desc_t *first_ep;
char maxlen;
int interval;
int i;
etrax_urb_priv_t *urb_priv;
DBFENTER;
maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
interval = urb->interval;
urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
assert(urb_priv != NULL);
memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
urb->hcpriv = urb_priv;
first_ep = &TxIntrEPList[0];
/* Round of the interval to 2^n, it is obvious that this code favours
smaller numbers, but that is actually a good thing */
/* FIXME: The "rounding error" for larger intervals will be quite
large. For in traffic this shouldn't be a problem since it will only
mean that we "poll" more often. */
for (i = 0; interval; i++) {
interval = interval >> 1;
}
interval = 1 << (i - 1);
dbg_intr("Interval rounded to %d", interval);
tmp_ep = first_ep;
i = 0;
do {
if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) {
if ((i % interval) == 0) {
/* Insert the traffic ep after tmp_ep */
USB_EP_Desc_t *ep_desc;
USB_SB_Desc_t *sb_desc;
dbg_intr("Inserting EP for epid %d", epid);
ep_desc = (USB_EP_Desc_t *)
kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
sb_desc = (USB_SB_Desc_t *)
kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(ep_desc != NULL);
CHECK_ALIGN(ep_desc);
assert(sb_desc != NULL);
ep_desc->sub = virt_to_phys(sb_desc);
ep_desc->hw_len = 0;
ep_desc->command = (IO_FIELD(USB_EP_command, epid, epid) |
IO_STATE(USB_EP_command, enable, yes));
/* Round upwards the number of packets of size maxlen
that this SB descriptor should receive. */
sb_desc->sw_len = urb->transfer_buffer_length ?
(urb->transfer_buffer_length - 1) / maxlen + 1 : 0;
sb_desc->next = 0;
sb_desc->buf = 0;
sb_desc->command =
(IO_FIELD(USB_SB_command, rem, urb->transfer_buffer_length % maxlen) |
IO_STATE(USB_SB_command, tt, in) |
IO_STATE(USB_SB_command, eot, yes) |
IO_STATE(USB_SB_command, eol, yes));
ep_desc->next = tmp_ep->next;
tmp_ep->next = virt_to_phys(ep_desc);
}
i++;
}
tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->next);
} while (tmp_ep != first_ep);
/* Note that first_sb/last_sb doesn't apply to interrupt traffic. */
urb_priv->epid = epid;
/* We start the DMA sub channel without checking if it's running or not, because:
1) If it's already running, issuing the start command is a nop.
2) We avoid a test-and-set race condition. */
*R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start);
DBFEXIT;
}
static void etrax_usb_complete_intr_urb(urb_t *urb, int status)
{
etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
int epid = urb_priv->epid;
DBFENTER;
if (status)
warn("Completing intr urb with status %d.", status);
dbg_intr("Completing intr epid %d, urb 0x%lx", epid, (unsigned long)urb);
urb->status = status;
urb->actual_length = urb_priv->rx_offset;
dbg_intr("interrupt urb->actual_length = %d", urb->actual_length);
/* We let any non-zero status from the layer above have precedence. */
if (status == 0) {
/* USB_DISABLE_SPD means that short reads (shorter than the endpoint's max length)
is to be treated as an error. */
if (urb->transfer_flags & USB_DISABLE_SPD) {
if (urb->actual_length !=
usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) {
urb->status = -EREMOTEIO;
}
}
}
if (urb->complete) {
urb->complete(urb);
}
/* Device driver has taken care of the data now. */
urb_priv->rx_offset = 0;
DBFEXIT;
}
static int etrax_usb_submit_isoc_urb(urb_t *urb)
{
int epid;
DBFENTER;
/* Is there an active epid for this urb ? */
epid = etrax_usb_setup_epid(urb);
if (epid == -1) {
DBFEXIT;
return -ENOMEM;
}
dbg_isoc("Submitting isoc urb = 0x%lx", (unsigned long)urb);
/* Ok, now we got valid endpoint, lets insert some traffic */
urb->status = -EINPROGRESS;
/* Find the last urb in the URB_List and add this urb after that one.
Also add the traffic, that is do an isoc_hw_add. This is important
to make this in "real time" since isochronous traffic is time sensitive. */
dbg_isoc("Adding isoc urb to (possibly empty) list");
urb_list_add(urb, epid);
etrax_usb_add_to_isoc_sb_list(urb, epid);
DBFEXIT;
return 0;
}
static void etrax_usb_add_to_isoc_sb_list(urb_t *urb, int epid)
{
int i = 0;
etrax_urb_priv_t *urb_priv;
USB_SB_Desc_t *prev_sb_desc, *next_sb_desc, *temp_sb_desc;
DBFENTER;
prev_sb_desc = next_sb_desc = temp_sb_desc = NULL;
urb_priv = kmalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG);
assert(urb_priv != NULL);
memset(urb_priv, 0, sizeof(etrax_urb_priv_t));
urb->hcpriv = urb_priv;
urb_priv->epid = epid;
if (usb_pipeout(urb->pipe)) {
/* Not implemented yet! */
dbg_isoc("Transfer for epid %d is OUT", epid);
/* Create one SB descriptor for each packet and link them together. */
for (i = 0; i < urb->number_of_packets; i++) {
next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(next_sb_desc != NULL);
next_sb_desc->command = (IO_STATE(USB_SB_command, tt, out) |
IO_STATE(USB_SB_command, eot, yes));
next_sb_desc->sw_len = urb->iso_frame_desc[i].length;
next_sb_desc->buf = virt_to_phys(urb->transfer_buffer + urb->iso_frame_desc[i].offset);
/* First SB descriptor that belongs to this urb */
if (i == 0)
urb_priv->first_sb = next_sb_desc;
else
prev_sb_desc->next = virt_to_phys(next_sb_desc);
prev_sb_desc = next_sb_desc;
}
/* Check if full length transfer. */
if (urb->iso_frame_desc[urb->number_of_packets - 1].length ==
usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) {
next_sb_desc->command |= IO_STATE(USB_SB_command, full, yes);
}
next_sb_desc->command |= IO_STATE(USB_SB_command, eol, yes);
next_sb_desc->next = 0;
urb_priv->last_sb = next_sb_desc;
} else if (usb_pipein(urb->pipe)) {
dbg_isoc("Transfer for epid %d is IN", epid);
dbg_isoc("transfer_buffer_length = %d", urb->transfer_buffer_length);
dbg_isoc("rem is calculated to %d", urb->iso_frame_desc[urb->number_of_packets - 1].length);
/* Note that in descriptors for periodic traffic are not consumed. This means that
the USB controller never propagates in the SB list. In other words, if there already
is an SB descriptor in the list for this EP we don't have to do anything. */
if (TxIsocEPList[epid].sub == 0) {
dbg_isoc("Isoc traffic not already running, allocating SB");
next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG);
assert(next_sb_desc != NULL);
next_sb_desc->command = (IO_STATE(USB_SB_command, tt, in) |
IO_STATE(USB_SB_command, eot, yes) |
IO_STATE(USB_SB_command, eol, yes));
next_sb_desc->sw_len = urb->number_of_packets;
next_sb_desc->buf = 0;
/* The rem field is don't care for isoc traffic, so we don't set it. */
/* Only one SB descriptor that belongs to this urb. */
urb_priv->first_sb = next_sb_desc;
urb_priv->last_sb = next_sb_desc;
} else {
dbg_isoc("Isoc traffic already running, just setting first/last_sb");
/* Each EP for isoc in will have only one SB descriptor, setup when submitting the
already active urb. Note that even though we may have several first_sb/last_sb
pointing at the same SB descriptor, they are freed only once (when the list has
become empty). */
urb_priv->first_sb = phys_to_virt(TxIsocEPList[epid].sub);
urb_priv->last_sb = phys_to_virt(TxIsocEPList[epid].sub);
return;
}
}
/* Find the spot to insert this urb and add it. */
if (TxIsocEPList[epid].sub == 0) {
/* First SB descriptor inserted in this list (in or out). */
dbg_isoc("Inserting SB desc first in list");
TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb);
} else {
/* Isochronous traffic is already running, insert new traffic last (only out). */
dbg_isoc("Inserting SB desc last in list");
temp_sb_desc = phys_to_virt(TxIsocEPList[epid].sub);
while (!(temp_sb_desc->command & IO_MASK(USB_SB_command, eol))) {
temp_sb_desc = phys_to_virt(temp_sb_desc->next);
}
/* Next pointer must be set before eol is removed. */
temp_sb_desc->next = virt_to_phys(urb_priv->first_sb);
/* Clear the previous end of list flag since there is a new in the
added SB descriptor list. */
temp_sb_desc->command &= ~IO_MASK(USB_SB_command, eol);
}
if (urb->transfer_flags & USB_ISO_ASAP) {
/* The isoc transfer should be started as soon as possible. The start_frame
field is a return value if URB_ISO_ASAP was set. Comparing R_USB_FM_NUMBER
with a USB Chief trace shows that the first isoc IN token is sent 2 frames
later. I'm not sure how this affects usage of the start_frame field by the
device driver, or how it affects things when USB_ISO_ASAP is not set, so
therefore there's no compensation for the 2 frame "lag" here. */
urb->start_frame = (*R_USB_FM_NUMBER & 0x7ff);
TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
urb_priv->urb_state = STARTED;
dbg_isoc("URB_ISO_ASAP set, urb->start_frame set to %d", urb->start_frame);
} else {
/* Not started yet. */
urb_priv->urb_state = NOT_STARTED;
}
/* We start the DMA sub channel without checking if it's running or not, because:
1) If it's already running, issuing the start command is a nop.
2) We avoid a test-and-set race condition. */
*R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start);
DBFEXIT;
}
static void etrax_usb_complete_isoc_urb(urb_t *urb, int status)
{
etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
int epid = urb_priv->epid;
DBFENTER;
if (status)
warn("Completing isoc urb with status %d.", status);
if (usb_pipein(urb->pipe)) {
/* Move this one down the list. */
urb_list_move_last(urb, epid);
/* Mark the now first urb as started (may already be). */
((etrax_urb_priv_t *)(urb_list_first(epid)->hcpriv))->urb_state = STARTED;
}
urb->status = status;
if (urb->complete) {
urb->complete(urb);
}
DBFEXIT;
}
static void etrax_usb_complete_urb(urb_t *urb, int status)
{
switch (usb_pipetype(urb->pipe)) {
case PIPE_BULK:
etrax_usb_complete_bulk_urb(urb, status);
break;
case PIPE_CONTROL:
etrax_usb_complete_ctrl_urb(urb, status);
break;
case PIPE_INTERRUPT:
etrax_usb_complete_intr_urb(urb, status);
break;
case PIPE_ISOCHRONOUS:
etrax_usb_complete_isoc_urb(urb, status);
break;
default:
err("Unknown pipetype");
}
}
static void etrax_usb_hc_interrupt_top_half(int irq, void *vhc, struct pt_regs *regs)
{
usb_interrupt_registers_t *reg;
unsigned long flags;
__u32 irq_mask;
__u8 status;
__u32 epid_attn;
__u16 port_status_1;
__u16 port_status_2;
__u32 fm_number;
DBFENTER;
/* Read critical registers into local variables, do kmalloc afterwards. */
save_flags(flags);
cli();
irq_mask = *R_USB_IRQ_MASK_READ;
/* Reading R_USB_STATUS clears the ctl_status interrupt. Note that R_USB_STATUS
must be read before R_USB_EPID_ATTN since reading the latter clears the
ourun and perror fields of R_USB_STATUS. */
status = *R_USB_STATUS;
/* Reading R_USB_EPID_ATTN clears the iso_eof, bulk_eot and epid_attn interrupts. */
epid_attn = *R_USB_EPID_ATTN;
/* Reading R_USB_RH_PORT_STATUS_1 and R_USB_RH_PORT_STATUS_2 clears the
port_status interrupt. */
port_status_1 = *R_USB_RH_PORT_STATUS_1;
port_status_2 = *R_USB_RH_PORT_STATUS_2;
/* Reading R_USB_FM_NUMBER clears the sof interrupt. */
/* Note: the lower 11 bits contain the actual frame number, sent with each sof. */
fm_number = *R_USB_FM_NUMBER;
restore_flags(flags);
reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, SLAB_ATOMIC);
assert(reg != NULL);
reg->hc = (etrax_hc_t *)vhc;
/* Now put register values into kmalloc'd area. */
reg->r_usb_irq_mask_read = irq_mask;
reg->r_usb_status = status;
reg->r_usb_epid_attn = epid_attn;
reg->r_usb_rh_port_status_1 = port_status_1;
reg->r_usb_rh_port_status_2 = port_status_2;
reg->r_usb_fm_number = fm_number;
reg->usb_bh.sync = 0;
reg->usb_bh.routine = etrax_usb_hc_interrupt_bottom_half;
reg->usb_bh.data = reg;
queue_task(&reg->usb_bh, &tq_immediate);
mark_bh(IMMEDIATE_BH);
DBFEXIT;
}
static void etrax_usb_hc_interrupt_bottom_half(void *data)
{
usb_interrupt_registers_t *reg = (usb_interrupt_registers_t *)data;
__u32 irq_mask = reg->r_usb_irq_mask_read;
DBFENTER;
/* Interrupts are handled in order of priority. */
if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, epid_attn)) {
etrax_usb_hc_epid_attn_interrupt(reg);
}
if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) {
etrax_usb_hc_port_status_interrupt(reg);
}
if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, ctl_status)) {
etrax_usb_hc_ctl_status_interrupt(reg);
}
if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, iso_eof)) {
etrax_usb_hc_isoc_eof_interrupt();
}
if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, bulk_eot)) {
/* Update/restart the bulk start timer since obviously the channel is running. */
mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL);
/* Update/restart the bulk eot timer since we just received an bulk eot interrupt. */
mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL);
etrax_usb_hc_bulk_eot_interrupt(0);
}
kmem_cache_free(top_half_reg_cache, reg);
DBFEXIT;
}
void etrax_usb_hc_isoc_eof_interrupt(void)
{
urb_t *urb;
etrax_urb_priv_t *urb_priv;
int epid;
DBFENTER;
/* Do not check the invalid epid (it has a valid sub pointer). */
for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) {
if (TxIsocEPList[epid].sub == 0) {
/* Nothing here to see. */
continue;
}
/* Get the first urb (if any). */
urb = urb_list_first(epid);
if (urb == 0) {
warn("Ignoring NULL urb");
continue;
}
/* Sanity check. */
assert(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS);
urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
assert(urb_priv);
if (urb_priv->urb_state == NOT_STARTED) {
/* If ASAP is not set and urb->start_frame is the current frame,
start the transfer. */
if (!(urb->transfer_flags & USB_ISO_ASAP) &&
(urb->start_frame == (*R_USB_FM_NUMBER & 0x7ff))) {
dbg_isoc("Enabling isoc IN EP descr for epid %d", epid);
TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes);
/* This urb is now active. */
urb_priv->urb_state = STARTED;
continue;
}
}
}
DBFEXIT;
}
void etrax_usb_hc_bulk_eot_interrupt(int timer_induced)
{
int epid;
/* The technique is to run one urb at a time, wait for the eot interrupt at which
point the EP descriptor has been disabled. */
DBFENTER;
dbg_bulk("bulk eot%s", timer_induced ? ", called by timer" : "");
for (epid = 0; epid < NBR_OF_EPIDS; epid++) {
if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) &&
(TxBulkEPList[epid].sub != 0)) {
urb_t *urb;
etrax_urb_priv_t *urb_priv;
unsigned long flags;
__u32 r_usb_ept_data;
/* Found a disabled EP descriptor which has a non-null sub pointer.
Verify that this ctrl EP descriptor got disabled no errors.
FIXME: Necessary to check error_code? */
dbg_bulk("for epid %d?", epid);
/* Get the first urb. */
urb = urb_list_first(epid);
/* FIXME: Could this happen for valid reasons? Why did it disappear? Because of
wrong unlinking? */
if (!urb) {
warn("NULL urb for epid %d", epid);
continue;
}
assert(urb);
urb_priv = (etrax_urb_priv_t *)urb->hcpriv;
assert(urb_priv);
/* Sanity checks. */
assert(usb_pipetype(urb->pipe) == PIPE_BULK);
if (phys_to_virt(TxBulkEPList[epid].sub) != urb_priv->last_sb) {
err("bulk endpoint got disabled before reaching last sb");
}
/* For bulk IN traffic, there seems to be a race condition between
between the bulk eot and eop interrupts, or rather an uncertainty regarding
the order in which they happen. Normally we expect the eop interrupt from
DMA channel 9 to happen before the eot interrupt.
Therefore, we complete the bulk IN urb in the rx interrupt handler instead. */
if (usb_pipein(urb->pipe)) {
dbg_bulk("in urb, continuing");
continue;
}
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);
if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) ==
IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) {
/* This means that the endpoint has no error, is disabled
and had inserted traffic, i.e. transfer successfully completed. */
etrax_usb_complete_bulk_urb(urb, 0);
} else {
/* Shouldn't happen. We expect errors to be caught by epid attention. */
err("Found disabled bulk EP desc, error_code != no_error");
}
}
}
/* Normally, we should find (at least) one disabled EP descriptor with a valid sub pointer.
However, because of the uncertainty in the deliverance of the eop/eot interrupts, we may
not. Also, we might find two disabled EPs when handling an eot interrupt, and then find
none the next time. */
DBFEXIT;
}
void etrax_usb_hc_epid_attn_interrupt(usb_interrupt_registers_t *reg)
{
/* This function handles the epid attention interrupt. There are a variety of reasons
for this interrupt to happen (Designer's Reference, p. 8 - 22 for the details):
invalid ep_id - Invalid epid in an EP (EP disabled).
stall - Not strictly an error condition (EP disabled).
3rd error - Three successive transaction errors (EP disabled).
buffer ourun - Buffer overrun or underrun (EP disabled).
past eof1 - Intr or isoc transaction proceeds past EOF1.
near eof - Intr or isoc transaction would not fit inside the frame.
zout transfer - If zout transfer for a bulk endpoint (EP disabled).
setup transfer - If setup transfer for a non-ctrl endpoint (EP disabled). */
int epid;
DBFENTER;
/* Note that we loop through all epids. We still want to catch errors for
the invalid one, even though we might handle them differently. */
for (epid = 0; epid < NBR_OF_EPIDS; epid++) {
if (test_bit(epid, (void *)&reg->r_usb_epid_attn)) {
urb_t *urb;
__u32 r_usb_ept_data;
unsigned long flags;
int error_code;
save_flags(flags);
cli();
*R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid);
nop();
/* Note that although there are separate R_USB_EPT_DATA and R_USB_EPT_DATA_ISO
registers, they are located at the same address and are of the same size.
In other words, this read should be ok for isoc also. */
r_usb_ept_data = *R_USB_EPT_DATA;
restore_flags(flags);
/* First some sanity checks. */
if (epid == INVALID_EPID) {
/* FIXME: What if it became disabled? Could seriously hurt interrupt
traffic. (Use do_intr_recover.) */
warn("Got epid_attn for INVALID_EPID (%d).", epid);
err("R_USB_EPT_DATA = 0x%x", r_usb_ept_data);
err("R_USB_STATUS = 0x%x", reg->r_usb_status);
continue;
} else if (epid == DUMMY_EPID) {
/* We definitely don't care about these ones. Besides, they are
always disabled, so any possible disabling caused by the
epid attention interrupt is irrelevant. */
warn("Got epid_attn for DUMMY_EPID (%d).", epid);
continue;
}
/* Get the first urb in the urb list for this epid. We blatantly assume
that only the first urb could have caused the epid attention.
(For bulk and ctrl, only one urb is active at any one time. For intr
and isoc we remove them once they are completed.) */
urb = urb_list_first(epid);
if (urb == NULL) {
err("Got epid_attn for epid %i with no urb.", epid);
err("R_USB_EPT_DA