diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt --- a/Documentation/devices.txt Mon Jan 21 12:28:40 2002 +++ b/Documentation/devices.txt Mon Jan 21 12:28:40 2002 @@ -2180,6 +2180,9 @@ ... 63 = /dev/usb/scanner15 16th USB scanner 64 = /dev/usb/rio500 Diamond Rio 500 + 80 = /dev/usb/auer0 1st auerswald ISDN device + ... + 95 = /dev/usb/auer15 16th auerswald ISDN device 181 char Conrad Electronic parallel port radio clocks 0 = /dev/pcfclock0 First Conrad radio clock diff -Nru a/arch/cris/drivers/usb-host.c b/arch/cris/drivers/usb-host.c --- a/arch/cris/drivers/usb-host.c Mon Jan 21 12:28:39 2002 +++ b/arch/cris/drivers/usb-host.c Mon Jan 21 12:28:39 2002 @@ -192,15 +192,15 @@ static USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4))); static USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4))); -static urb_t *URB_List[NBR_OF_EP_DESC]; +static struct urb *URB_List[NBR_OF_EP_DESC]; static kmem_cache_t *usb_desc_cache; static struct usb_bus *etrax_usb_bus; static void dump_urb (struct urb *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 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 void etrax_usb_setup_epid(char epid, char devnum, char endpoint, @@ -210,13 +210,13 @@ static void etrax_usb_free_epid(char epid); static void cleanup_sb(USB_SB_Desc_t *sb); -static int etrax_usb_do_ctrl_hw_add(urb_t *urb, char epid, char maxlen); -static int etrax_usb_do_bulk_hw_add(urb_t *urb, char epid, char maxlen); +static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen); +static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen); -static int etrax_usb_submit_ctrl_urb(urb_t *urb); +static int etrax_usb_submit_ctrl_urb(struct urb *urb); -static int etrax_usb_submit_urb(urb_t *urb); -static int etrax_usb_unlink_urb(urb_t *urb); +static int etrax_usb_submit_urb(struct urb *urb); +static int etrax_usb_unlink_urb(struct urb *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); @@ -225,7 +225,7 @@ static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs); static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs); -static int etrax_rh_submit_urb (urb_t *urb); +static int etrax_rh_submit_urb (struct urb *urb); static int etrax_usb_hc_init(void); static void etrax_usb_hc_cleanup(void); @@ -421,7 +421,7 @@ } -static int etrax_usb_unlink_intr_urb(urb_t *urb) +static int etrax_usb_unlink_intr_urb(struct urb *urb) { struct usb_device *usb_dev = urb->dev; etrax_hc_t *hc = usb_dev->bus->hcpriv; @@ -512,7 +512,7 @@ } while (tmp_ep != first_ep); } -static int etrax_usb_submit_intr_urb(urb_t *urb) +static int etrax_usb_submit_intr_urb(struct urb *urb) { USB_EP_Desc_t *tmp_ep; USB_EP_Desc_t *first_ep; @@ -643,7 +643,7 @@ static int handle_intr_transfer_attn(char epid, int status) { - urb_t *old_urb; + struct urb *old_urb; DBFENTER; @@ -696,7 +696,7 @@ DBFEXIT; } -static int etrax_rh_unlink_urb (urb_t *urb) +static int etrax_rh_unlink_urb (struct urb *urb) { etrax_hc_t *hc; @@ -713,7 +713,7 @@ return 0; } -static void etrax_rh_send_irq(urb_t *urb) +static void etrax_rh_send_irq(struct urb *urb) { __u16 data = 0; etrax_hc_t *hc = urb->dev->bus->hcpriv; @@ -746,7 +746,7 @@ /* DBFEXIT; */ } -static void etrax_rh_init_int_timer(urb_t *urb) +static void etrax_rh_init_int_timer(struct urb *urb) { etrax_hc_t *hc; @@ -765,12 +765,12 @@ static void etrax_rh_int_timer_do(unsigned long ptr) { - urb_t *urb; + struct urb *urb; etrax_hc_t *hc; /* DBFENTER; */ - urb = (urb_t*)ptr; + urb = (struct urb *)ptr; hc = urb->dev->bus->hcpriv; if (hc->rh.send) { @@ -904,7 +904,7 @@ return -1; } -static int etrax_usb_submit_bulk_urb(urb_t *urb) +static int etrax_usb_submit_bulk_urb(struct urb *urb) { char epid; char devnum; @@ -912,7 +912,7 @@ char maxlen; char slow; - urb_t *tmp_urb; + struct urb *tmp_urb; etrax_urb_priv_t *urb_priv; unsigned long flags; @@ -962,7 +962,7 @@ return 0; } -static int etrax_usb_do_bulk_hw_add(urb_t *urb, char epid, char maxlen) +static int etrax_usb_do_bulk_hw_add(struct urb *urb, char epid, char maxlen) { USB_SB_Desc_t *sb_desc_1; @@ -1080,7 +1080,7 @@ static int handle_bulk_transfer_attn(char epid, int status) { - urb_t *old_urb; + struct urb *old_urb; etrax_urb_priv_t *hc_priv; unsigned long flags; @@ -1159,7 +1159,7 @@ /* ---------------------------------------------------------------------------- */ -static int etrax_usb_submit_ctrl_urb(urb_t *urb) +static int etrax_usb_submit_ctrl_urb(struct urb *urb) { char epid; char devnum; @@ -1167,7 +1167,7 @@ char maxlen; char slow; - urb_t *tmp_urb; + struct urb *tmp_urb; etrax_urb_priv_t *urb_priv; unsigned long flags; @@ -1217,7 +1217,7 @@ return 0; } -static int etrax_usb_do_ctrl_hw_add(urb_t *urb, char epid, char maxlen) +static int etrax_usb_do_ctrl_hw_add(struct urb *urb, char epid, char maxlen) { USB_SB_Desc_t *sb_desc_1; USB_SB_Desc_t *sb_desc_2; @@ -1358,7 +1358,7 @@ DBFEXIT; } -static int etrax_usb_submit_urb(urb_t *urb) +static int etrax_usb_submit_urb(struct urb *urb) { etrax_hc_t *hc; int rval = -EINVAL; @@ -1403,7 +1403,7 @@ return rval; } -static int etrax_usb_unlink_urb(urb_t *urb) +static int etrax_usb_unlink_urb(struct urb *urb) { etrax_hc_t *hc = urb->dev->bus->hcpriv; int epid; @@ -1448,7 +1448,7 @@ cli(); for (epid = 0; epid < 32; epid++) { - urb_t *u = URB_List[epid]; + struct urb *u = URB_List[epid]; pos = 0; for (; u; u = u->next) { @@ -1474,7 +1474,7 @@ URB_List[epid] = u->next; } else { - urb_t *up; + struct urb *up; for (up = URB_List[epid]; up->next != u; up = up->next); up->next = u->next; } @@ -1522,7 +1522,7 @@ etrax_hc_t *hc = (etrax_hc_t *)vhc; int epid; char eol; - urb_t *urb; + struct urb *urb; USB_EP_Desc_t *tmp_ep; USB_SB_Desc_t *tmp_sb; @@ -1551,7 +1551,7 @@ static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs) { int epid = 0; - urb_t *urb; + struct urb *urb; etrax_urb_priv_t *urb_priv; *R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do); @@ -1649,7 +1649,7 @@ static int handle_control_transfer_attn(char epid, int status) { - urb_t *old_urb; + struct urb *old_urb; etrax_urb_priv_t *hc_priv; DBFENTER; @@ -1710,7 +1710,7 @@ static void etrax_usb_hc_intr_bottom_half(void *data) { struct usb_reg_context *reg = (struct usb_reg_context *)data; - urb_t *old_urb; + struct urb *old_urb; int error_code; int epid; @@ -1976,7 +1976,7 @@ DBFEXIT; } -static int etrax_rh_submit_urb(urb_t *urb) +static int etrax_rh_submit_urb(struct urb *urb) { struct usb_device *usb_dev = urb->dev; etrax_hc_t *hc = usb_dev->bus->hcpriv; diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c --- a/drivers/ieee1394/pcilynx.c Mon Jan 21 12:28:39 2002 +++ b/drivers/ieee1394/pcilynx.c Mon Jan 21 12:28:39 2002 @@ -794,7 +794,7 @@ static int mem_open(struct inode *inode, struct file *file) { - int cid = MINOR(inode->i_rdev); + int cid = minor(inode->i_rdev); enum { t_rom, t_aux, t_ram } type; struct memdata *md; diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c --- a/drivers/ieee1394/video1394.c Mon Jan 21 12:28:38 2002 +++ b/drivers/ieee1394/video1394.c Mon Jan 21 12:28:38 2002 @@ -850,7 +850,7 @@ struct video_card *p; list_for_each(lh, &video1394_cards) { p = list_entry(lh, struct video_card, list); - if (p->id == MINOR(inode->i_rdev)) { + if (p->id == minor(inode->i_rdev)) { video = p; ohci = video->ohci; break; @@ -860,7 +860,7 @@ spin_unlock_irqrestore(&video1394_cards_lock, flags); if (video == NULL) { - PRINT_G(KERN_ERR, __FUNCTION__": Unknown video card for minor %d", MINOR(inode->i_rdev)); + PRINT_G(KERN_ERR, __FUNCTION__": Unknown video card for minor %d", minor(inode->i_rdev)); return -EFAULT; } @@ -1328,7 +1328,7 @@ struct video_card *p; list_for_each(lh, &video1394_cards) { p = list_entry(lh, struct video_card, list); - if (p->id == MINOR(file->f_dentry->d_inode->i_rdev)) { + if (p->id == minor(file->f_dentry->d_inode->i_rdev)) { video = p; break; } @@ -1338,7 +1338,7 @@ if (video == NULL) { PRINT_G(KERN_ERR, __FUNCTION__": Unknown video card for minor %d", - MINOR(file->f_dentry->d_inode->i_rdev)); + minor(file->f_dentry->d_inode->i_rdev)); return -EFAULT; } @@ -1357,7 +1357,7 @@ static int video1394_open(struct inode *inode, struct file *file) { - int i = MINOR(inode->i_rdev); + int i = minor(inode->i_rdev); unsigned long flags; struct video_card *video = NULL; struct list_head *lh; @@ -1397,7 +1397,7 @@ struct video_card *p; list_for_each(lh, &video1394_cards) { p = list_entry(lh, struct video_card, list); - if (p->id == MINOR(inode->i_rdev)) { + if (p->id == minor(inode->i_rdev)) { video = p; break; } @@ -1407,7 +1407,7 @@ if (video == NULL) { PRINT_G(KERN_ERR, __FUNCTION__": Unknown device for minor %d", - MINOR(inode->i_rdev)); + minor(inode->i_rdev)); return 1; } diff -Nru a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h --- a/drivers/isdn/hisax/st5481.h Mon Jan 21 12:28:40 2002 +++ b/drivers/isdn/hisax/st5481.h Mon Jan 21 12:28:40 2002 @@ -478,7 +478,7 @@ if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) static void __attribute__((unused)) -dump_iso_packet(const char *name,urb_t *urb) +dump_iso_packet(const char *name, struct urb *urb) { int i,j; int len,ofs; diff -Nru a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c --- a/drivers/isdn/hisax/st5481_d.c Mon Jan 21 12:28:38 2002 +++ b/drivers/isdn/hisax/st5481_d.c Mon Jan 21 12:28:38 2002 @@ -297,7 +297,7 @@ unsigned int num_packets, packet_offset; int len, buf_size, bytes_sent; struct sk_buff *skb; - iso_packet_descriptor_t *desc; + struct usb_iso_packet_descriptor *desc; if (d_out->fsm.state != ST_DOUT_NORMAL) return; diff -Nru a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c --- a/drivers/isdn/hisax/st5481_usb.c Mon Jan 21 12:28:39 2002 +++ b/drivers/isdn/hisax/st5481_usb.c Mon Jan 21 12:28:39 2002 @@ -235,7 +235,7 @@ struct usb_interface_descriptor *altsetting; struct usb_endpoint_descriptor *endpoint; int status; - urb_t *urb; + struct urb *urb; u_char *buf; DBG(1,""); @@ -560,7 +560,7 @@ */ int st5481_isoc_flatten(struct urb *urb) { - iso_packet_descriptor_t *pipd,*pend; + struct usb_iso_packet_descriptor *pipd,*pend; unsigned char *src,*dst; unsigned int len; diff -Nru a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c --- a/drivers/isdn/isdn_common.c Mon Jan 21 12:28:40 2002 +++ b/drivers/isdn/isdn_common.c Mon Jan 21 12:28:40 2002 @@ -2253,7 +2253,7 @@ sprintf (buf, "isdn%d", k); dev->devfs_handle_isdnX[k] = devfs_register (devfs_handle, buf, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_B + k,0600 | S_IFCHR, + ISDN_MAJOR, k,0600 | S_IFCHR, &isdn_fops, NULL); sprintf (buf, "isdnctrl%d", k); dev->devfs_handle_isdnctrlX[k] = diff -Nru a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c --- a/drivers/media/video/cpia_usb.c Mon Jan 21 12:28:40 2002 +++ b/drivers/media/video/cpia_usb.c Mon Jan 21 12:28:40 2002 @@ -46,7 +46,7 @@ struct cpia_sbuf { char *data; - urb_t *urb; + struct urb *urb; }; #define FRAMEBUF_LEN (CPIA_MAX_FRAME_SIZE+100) @@ -168,7 +168,7 @@ static int cpia_usb_open(void *privdata) { struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - urb_t *urb; + struct urb *urb; int ret, retval = 0, fx, err; if (!ucpia) diff -Nru a/drivers/net/aironet4500_core.c b/drivers/net/aironet4500_core.c --- a/drivers/net/aironet4500_core.c Mon Jan 21 12:28:39 2002 +++ b/drivers/net/aironet4500_core.c Mon Jan 21 12:28:39 2002 @@ -2836,7 +2836,7 @@ return 0; final: printk(KERN_ERR "aironet init failed \n"); - return NODEV; + return -ENODEV; }; diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile --- a/drivers/usb/Makefile Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/Makefile Mon Jan 21 12:28:39 2002 @@ -46,6 +46,10 @@ obj-y += hcd/ehci-hcd.o endif +ifeq ($(CONFIG_USB_OHCI_HCD),y) + obj-y += hcd/ohci-hcd.o +endif + obj-$(CONFIG_USB_UHCI) += usb-uhci.o obj-$(CONFIG_USB_UHCI_ALT) += uhci.o obj-$(CONFIG_USB_OHCI) += usb-ohci.o @@ -85,6 +89,7 @@ mod-subdirs := serial hcd subdir-$(CONFIG_USB_EHCI_HCD) += hcd +subdir-$(CONFIG_USB_OHCI_HCD) += hcd subdir-$(CONFIG_USB_SERIAL) += serial subdir-$(CONFIG_USB_STORAGE) += storage diff -Nru a/drivers/usb/audio.c b/drivers/usb/audio.c --- a/drivers/usb/audio.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/audio.c Mon Jan 21 12:28:39 2002 @@ -297,13 +297,13 @@ #define FLG_CONNECTED 32 struct my_data_urb { - urb_t urb; - iso_packet_descriptor_t isoframe[DESCFRAMES]; + struct urb urb; + struct usb_iso_packet_descriptor isoframe[DESCFRAMES]; }; struct my_sync_urb { - urb_t urb; - iso_packet_descriptor_t isoframe[SYNCFRAMES]; + struct urb urb; + struct usb_iso_packet_descriptor isoframe[SYNCFRAMES]; }; diff -Nru a/drivers/usb/auerswald.c b/drivers/usb/auerswald.c --- a/drivers/usb/auerswald.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/auerswald.c Mon Jan 21 12:28:39 2002 @@ -176,7 +176,7 @@ typedef struct { struct auerchain *chain; /* pointer to the chain to which this element belongs */ - urb_t * urbp; /* pointer to attached urb */ + struct urb * urbp; /* pointer to attached urb */ void *context; /* saved URB context */ usb_complete_t complete; /* saved URB completion function */ struct list_head list; /* to include element into a list */ @@ -200,7 +200,7 @@ unsigned int len; /* number of characters in data buffer */ unsigned int retries; /* for urb retries */ struct usb_ctrlrequest *dr; /* for setup data in control messages */ - urb_t * urbp; /* USB urb */ + struct urb * urbp; /* USB urb */ struct auerbufctl *list; /* pointer to list */ struct list_head buff_list; /* reference to next buffer in list */ } auerbuf_t,*pauerbuf_t; @@ -237,7 +237,7 @@ int open_count; /* count the number of open character channels */ char dev_desc[AUSI_DLEN];/* for storing a textual description */ unsigned int maxControlLength; /* max. Length of control paket (without header) */ - urb_t * inturbp; /* interrupt urb */ + struct urb * inturbp; /* interrupt urb */ char * intbufp; /* data buffer for interrupt urb */ unsigned int irqsize; /* size of interrupt endpoint 1 */ struct auerchain controlchain; /* for chaining of control messages */ @@ -274,7 +274,7 @@ /*-------------------------------------------------------------------*/ /* Forwards */ -static void auerswald_ctrlread_complete (urb_t * urb); +static void auerswald_ctrlread_complete (struct urb * urb); static void auerswald_removeservice (pauerswald_t cp, pauerscon_t scp); @@ -283,7 +283,7 @@ /* -------------------------- */ /* completion function for chained urbs */ -static void auerchain_complete (urb_t * urb) +static void auerchain_complete (struct urb * urb) { unsigned long flags; int result; @@ -350,7 +350,7 @@ this function may be called from completion context or from user space! early = 1 -> submit in front of chain */ -static int auerchain_submit_urb_list (pauerchain_t acp, urb_t * urb, int early) +static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int early) { int result; unsigned long flags; @@ -424,7 +424,7 @@ /* submit function for chained urbs this function may be called from completion context or from user space! */ -static int auerchain_submit_urb (pauerchain_t acp, urb_t * urb) +static int auerchain_submit_urb (pauerchain_t acp, struct urb * urb) { return auerchain_submit_urb_list (acp, urb, 0); } @@ -433,10 +433,10 @@ the result is 0 if the urb is cancelled, or -EINPROGRESS if USB_ASYNC_UNLINK is set and the function is successfully started. */ -static int auerchain_unlink_urb (pauerchain_t acp, urb_t * urb) +static int auerchain_unlink_urb (pauerchain_t acp, struct urb * urb) { unsigned long flags; - urb_t * urbp; + struct urb * urbp; pauerchainelement_t acep; struct list_head *tmp; @@ -492,7 +492,7 @@ static void auerchain_unlink_all (pauerchain_t acp) { unsigned long flags; - urb_t * urbp; + struct urb * urbp; pauerchainelement_t acep; dbg ("auerchain_unlink_all called"); @@ -598,7 +598,7 @@ /* completion handler for synchronous chained URBs */ -static void auerchain_blocking_completion (urb_t *urb) +static void auerchain_blocking_completion (struct urb *urb) { wait_queue_head_t *wakeup = (wait_queue_head_t *)urb->context; wake_up (wakeup); @@ -606,7 +606,7 @@ /* Starts chained urb and waits for completion or timeout */ -static int auerchain_start_wait_urb (pauerchain_t acp, urb_t *urb, int timeout, int* actual_length) +static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length) { DECLARE_WAITQUEUE (wait, current); DECLARE_WAIT_QUEUE_HEAD (wqh); @@ -675,7 +675,7 @@ { int ret; struct usb_ctrlrequest *dr; - urb_t *urb; + struct urb *urb; int length; dbg ("auerchain_control_msg"); @@ -858,7 +858,7 @@ } /* Completion of asynchronous write block */ -static void auerchar_ctrlwrite_complete (urb_t * urb) +static void auerchar_ctrlwrite_complete (struct urb * urb) { pauerbuf_t bp = (pauerbuf_t) urb->context; pauerswald_t cp = ((pauerswald_t)((char *)(bp->list)-(unsigned long)(&((pauerswald_t)0)->bufctl))); @@ -871,7 +871,7 @@ } /* Completion handler for dummy retry packet */ -static void auerswald_ctrlread_wretcomplete (urb_t * urb) +static void auerswald_ctrlread_wretcomplete (struct urb * urb) { pauerbuf_t bp = (pauerbuf_t) urb->context; pauerswald_t cp; @@ -910,7 +910,7 @@ } /* completion handler for receiving of control messages */ -static void auerswald_ctrlread_complete (urb_t * urb) +static void auerswald_ctrlread_complete (struct urb * urb) { unsigned int serviceid; pauerswald_t cp; @@ -980,7 +980,7 @@ messages from the USB device. */ /* int completion handler. */ -static void auerswald_int_complete (urb_t * urb) +static void auerswald_int_complete (struct urb * urb) { unsigned long flags; unsigned int channelid; diff -Nru a/drivers/usb/devio.c b/drivers/usb/devio.c --- a/drivers/usb/devio.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/devio.c Mon Jan 21 12:28:39 2002 @@ -53,7 +53,7 @@ unsigned int signr; void *userbuffer; void *userurb; - urb_t urb; + struct urb urb; }; static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig) @@ -170,7 +170,7 @@ static struct async *alloc_async(unsigned int numisoframes) { - unsigned int assize = sizeof(struct async) + numisoframes * sizeof(iso_packet_descriptor_t); + unsigned int assize = sizeof(struct async) + numisoframes * sizeof(struct usb_iso_packet_descriptor); struct async *as = kmalloc(assize, GFP_KERNEL); if (!as) return NULL; diff -Nru a/drivers/usb/hcd/Config.in b/drivers/usb/hcd/Config.in --- a/drivers/usb/hcd/Config.in Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/hcd/Config.in Mon Jan 21 12:28:40 2002 @@ -2,6 +2,6 @@ # USB Host Controller Drivers # dep_tristate ' EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL -# dep_tristate ' OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL +dep_tristate ' OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL # dep_tristate ' UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL diff -Nru a/drivers/usb/hcd/Makefile b/drivers/usb/hcd/Makefile --- a/drivers/usb/hcd/Makefile Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/hcd/Makefile Mon Jan 21 12:28:39 2002 @@ -6,7 +6,7 @@ O_TARGET := obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o -# obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o +obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o # obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o # Extract lists of the multi-part drivers. diff -Nru a/drivers/usb/hcd/ehci-sched.c b/drivers/usb/hcd/ehci-sched.c --- a/drivers/usb/hcd/ehci-sched.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/hcd/ehci-sched.c Mon Jan 21 12:28:40 2002 @@ -630,7 +630,7 @@ if (!(urb->transfer_flags & EHCI_STATE_UNLINK) && ehci->hcd.state != USB_STATE_HALT) { int i; - iso_packet_descriptor_t *desc; + struct usb_iso_packet_descriptor *desc; struct ehci_itd *first_itd = urb->hcpriv; /* update status for this frame's transfers */ diff -Nru a/drivers/usb/hcd/ohci-dbg.c b/drivers/usb/hcd/ohci-dbg.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/hcd/ohci-dbg.c Mon Jan 21 12:28:40 2002 @@ -0,0 +1,236 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * This file is licenced under GPL + * $Id: ohci-dbg.c,v 1.2 2002/01/19 00:15:45 dbrownell Exp $ + */ + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG + +#define pipestring(pipe) ({ char *temp; \ + switch (usb_pipetype (pipe)) { \ + case PIPE_CONTROL: temp = "CTRL"; break; \ + case PIPE_BULK: temp = "BULK"; break; \ + case PIPE_INTERRUPT: temp = "INTR"; break; \ + default: temp = "ISOC"; break; \ + }; temp;}) + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header + */ +static void urb_print (struct urb * urb, char * str, int small) +{ + unsigned int pipe= urb->pipe; + + if (!urb->dev || !urb->dev->bus) { + dbg("%s URB: no dev", str); + return; + } + +#ifndef OHCI_VERBOSE_DEBUG + if (urb->status != 0) +#endif + dbg("%s:[%4x] dev:%d,ep=%d-%c,%s,flags:%4x,len:%d/%d,stat:%d", + str, + usb_get_current_frame_number (urb->dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + pipestring (pipe), + urb->transfer_flags, + urb->actual_length, + urb->transfer_buffer_length, + urb->status); + +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printk (KERN_DEBUG __FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printk (" %02x", ((__u8 *) urb->setup_packet) [i]); + printk ("\n"); + } + if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { + printk (KERN_DEBUG __FILE__ ": data(%d/%d):", + urb->actual_length, + urb->transfer_buffer_length); + len = usb_pipeout (pipe)? + urb->transfer_buffer_length: urb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]); + printk ("%s stat:%d\n", i < len? "...": "", urb->status); + } + } +#endif +} + +static inline struct ed * +dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma); + +/* print non-empty branches of the periodic ed tree */ +void ep_print_int_eds (struct ohci_hcd *ohci, char * str) +{ + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + ed_p = &(ohci->hcca->int_table [i]); + if (*ed_p == 0) + continue; + printk (KERN_DEBUG __FILE__ ": %s branch int %2d(%2x):", + str, i, i); + while (*ed_p != 0 && j--) { + struct ed *ed = dma_to_ed (ohci, le32_to_cpup(ed_p)); + printk (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printk ("\n"); + } +} + + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + if (value) + dbg ("%s %08x", label, value); +} + +static char *hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +// dump control and status registers +static void ohci_dump_status (struct ohci_hcd *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + // intrdisable always same as intrenable + // ohci_dump_intr_mask ("intrdisable", readl (®s->intrdisable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg_port (controller, "", i, temp); + } +} + +static void ohci_dump (struct ohci_hcd *controller, int verbose) +{ + dbg ("OHCI controller %s state", controller->hcd.bus_name); + + // dumps some of the state we know about + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); +} + + +#endif + diff -Nru a/drivers/usb/hcd/ohci-hcd.c b/drivers/usb/hcd/ohci-hcd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/hcd/ohci-hcd.c Mon Jan 21 12:28:40 2002 @@ -0,0 +1,973 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * [ Initialisation is based on Linus' ] + * [ uhci code and gregs ohci fragments ] + * [ (C) Copyright 1999 Linus Torvalds ] + * [ (C) Copyright 1999 Gregory P. Smith] + * + * + * History: + * + * 2002/01/18 package as a patch for 2.5.3; this should match the + * 2.4.17 kernel modulo some bugs being fixed. + * + * 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes + * from post-2.4.5 patches. + * 2001/09/20 USB_ZERO_PACKET support; hcca_dma portability, OPTi warning + * 2001/09/07 match PCI PM changes, errnos from Linus' tree + * 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify; + * pbook pci quirks gone (please fix pbook pci sw!) (db) + * + * 2001/04/08 Identify version on module load (gb) + * 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam); + pci_map_single (db) + * 2001/03/21 td and dev/ed allocation uses new pci_pool API (db) + * 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam) + * + * 2000/09/26 fixed races in removing the private portion of the urb + * 2000/09/07 disable bulk and control lists when unlinking the last + * endpoint descriptor in order to avoid unrecoverable errors on + * the Lucent chips. (rwc@sgi) + * 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some + * urb unlink probs, indentation fixes + * 2000/08/11 various oops fixes mostly affecting iso and cleanup from + * device unplugs. + * 2000/06/28 use PCI hotplug framework, for better power management + * and for Cardbus support (David Brownell) + * 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling + * when the controller loses power; handle UE; cleanup; ... + * + * v5.2 1999/12/07 URB 3rd preview, + * v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi) + * v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume + * i386: HUB, Keyboard, Mouse, Printer + * + * v4.3 1999/10/27 multiple HCs, bulk_request + * v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes + * v4.1 1999/08/27 Randy Dunlap's - ISO API first impl. + * v4.0 1999/08/18 + * v3.0 1999/06/25 + * v2.1 1999/05/09 code clean up + * v2.0 1999/05/04 + * v1.0 1999/04/27 initial release + * + * This file is licenced under GPL + * $Id: ohci-hcd.c,v 1.7 2002/01/19 00:20:56 dbrownell Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for in_interrupt () */ + +#ifndef CONFIG_USB_DEBUG + #define CONFIG_USB_DEBUG /* this is still experimental! */ +#endif + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + +#include +#include "../hcd.h" + +#include +#include +#include +#include + +#ifdef CONFIG_PMAC_PBOOK +#include +#include +#include +#ifndef CONFIG_PM +# define CONFIG_PM +#endif +#endif + +/* + * TO DO: + * + * - "disabled" should be the hcd state + * - bandwidth alloc to generic code + * - lots more testing!! + */ + +#define DRIVER_VERSION "$Revision: 1.7 $" +#define DRIVER_AUTHOR "Roman Weissgaerber , David Brownell" +#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" + +/*-------------------------------------------------------------------------*/ + +#define OHCI_USE_NPS // force NoPowerSwitching mode +// #define OHCI_VERBOSE_DEBUG /* not always helpful */ + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#define OHCI_UNLINK_TIMEOUT (HZ / 10) + +/*-------------------------------------------------------------------------*/ + +#include "ohci.h" + +#include "ohci-hub.c" +#include "ohci-dbg.c" +#include "ohci-mem.c" +#include "ohci-q.c" + +/*-------------------------------------------------------------------------*/ + +/* + * queue up an urb for anything except the root hub + */ +static int ohci_urb_enqueue ( + struct usb_hcd *hcd, + struct urb *urb, + int mem_flags +) { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct ed *ed; + urb_priv_t *urb_priv; + unsigned int pipe = urb->pipe; + int i, size = 0; + unsigned long flags; + int bustime = 0; + +#ifdef OHCI_VERBOSE_DEBUG + urb_print (urb, "SUB", usb_pipein (pipe)); +#endif + + /* every endpoint has a ed, locate and fill it */ + if (! (ed = ep_add_ed (urb->dev, pipe, urb->interval, 1, mem_flags))) { + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_CONTROL: + /* 1 TD for setup, 1 for ACK, plus ... */ + size = 2; + /* FALLTHROUGH */ + case PIPE_BULK: + /* one TD for every 4096 Bytes (can be upto 8K) */ + size += urb->transfer_buffer_length / 4096; + /* ... and for any remaining bytes ... */ + if ((urb->transfer_buffer_length % 4096) != 0) + size++; + /* ... and maybe a zero length packet to wrap it up */ + if (size == 0) + size++; + else if ((urb->transfer_flags & USB_ZERO_PACKET) != 0 + && (urb->transfer_buffer_length + % usb_maxpacket (urb->dev, pipe, + usb_pipeout (pipe))) != 0) + size++; + break; + case PIPE_ISOCHRONOUS: /* number of packets from URB */ + size = urb->number_of_packets; + if (size <= 0) { + usb_dec_dev_use (urb->dev); + return -EINVAL; + } + for (i = 0; i < urb->number_of_packets; i++) { + urb->iso_frame_desc [i].actual_length = 0; + urb->iso_frame_desc [i].status = -EXDEV; + } + break; + case PIPE_INTERRUPT: /* one TD */ + size = 1; + break; + } + + /* allocate the private part of the URB */ + urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (struct td *), + mem_flags); + if (!urb_priv) { + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *)); + + /* fill the private part of the URB */ + urb_priv->length = size; + urb_priv->ed = ed; + + /* allocate the TDs (updating hash chains) */ + spin_lock_irqsave (&ohci->lock, flags); + for (i = 0; i < size; i++) { + urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC); + if (!urb_priv->td [i]) { + urb_priv->length = i; + urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&ohci->lock, flags); + usb_dec_dev_use (urb->dev); + return -ENOMEM; + } + } + +// FIXME: much of this switch should be generic, move to hcd code ... + + /* allocate and claim bandwidth if needed; ISO + * needs start frame index if it was't provided. + */ + switch (usb_pipetype (pipe)) { + case PIPE_ISOCHRONOUS: + if (urb->transfer_flags & USB_ISO_ASAP) { + urb->start_frame = ( (ed->state == ED_OPER) + ? (ed->last_iso + 1) + : (le16_to_cpu (ohci->hcca->frame_no) + + 10)) & 0xffff; + } + /* FALLTHROUGH */ + case PIPE_INTERRUPT: + if (urb->bandwidth == 0) { + bustime = usb_check_bandwidth (urb->dev, urb); + } + if (bustime < 0) { + urb_free_priv (ohci, urb_priv); + spin_unlock_irqrestore (&ohci->lock, flags); + usb_dec_dev_use (urb->dev); + return bustime; + } + usb_claim_bandwidth (urb->dev, urb, + bustime, usb_pipeisoc (urb->pipe)); + } + + urb->hcpriv = urb_priv; + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) + ep_link (ohci, ed); + + /* fill the TDs and link it to the ed */ + td_submit_urb (urb); + + spin_unlock_irqrestore (&ohci->lock, flags); + + return 0; +} + +/* + * decouple the URB from the HC queues (TDs, urb_priv); it's + * already marked for deletion. reporting is always done + * asynchronously, and we might be dealing with an urb that's + * almost completed anyway... + */ +static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + +#ifdef DEBUG + urb_print (urb, "UNLINK", 1); +#endif + + if (!ohci->disabled) { + urb_priv_t *urb_priv; + + /* flag the urb's data for deletion in some upcoming + * SF interrupt's delete list processing + */ + spin_lock_irqsave (&ohci->lock, flags); + urb_priv = urb->hcpriv; + + if (!urb_priv || (urb_priv->state == URB_DEL)) { + spin_unlock_irqrestore (&ohci->lock, flags); + return 0; + } + + urb_priv->state = URB_DEL; + ed_unlink (urb->dev, urb_priv->ed); + spin_unlock_irqrestore (&ohci->lock, flags); + } else { + /* + * with HC dead, we won't respect hc queue pointers + * any more ... just clean up every urb's memory. + */ + finish_urb (ohci, urb); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static void +ohci_free_config (struct usb_hcd *hcd, struct usb_device *udev) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv; + int i; + unsigned long flags; + + /* free any eds, and dummy tds, still hanging around */ + spin_lock_irqsave (&ohci->lock, flags); + for (i = 0; i < 32; i++) { + struct ed *ed = dev->ep [i]; + struct td *tdTailP; + + if (!ed) + continue; + + ed->state &= ~ED_URB_DEL; + if (ohci->disabled && ed->state == ED_OPER) + ed->state = ED_UNLINK; + switch (ed->state) { + case ED_NEW: + break; + case ED_UNLINK: + tdTailP = dma_to_td (ohci, + le32_to_cpup (&ed->hwTailP) & 0xfffffff0); + td_free (ohci, tdTailP); /* free dummy td */ + hash_free_ed (ohci, ed); + break; + + case ED_OPER: + default: + err ("illegal ED %d state in free_config, %d", + i, ed->state); +#ifdef DEBUG + BUG (); +#endif + } + ed_free (ohci, ed); + } + spin_unlock_irqrestore (&ohci->lock, flags); +} + +static int ohci_get_frame (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + + dbg ("%s: ohci_get_frame", hcd->bus_name); + return le16_to_cpu (ohci->hcca->frame_no); +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset (struct ohci_hcd *ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_INTR_OC, &ohci->regs->intrenable); + writel (OHCI_OCR, &ohci->regs->cmdstatus); + dbg ("USB HC TakeOver from SMM"); + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms (10); + if (--smm_timeout == 0) { + err ("USB HC TakeOver failed!"); + return -1; + } + } + } + + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + + dbg ("USB HC reset_hc %s: ctrl = 0x%x ;", + ohci->hcd.bus_name, + readl (&ohci->regs->control)); + + /* Reset USB (needed by some controllers) */ + writel (0, &ohci->regs->control); + + /* HC Reset requires max 10 ms delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + if (--timeout == 0) { + err ("USB HC reset timed out!"); + return -1; + } + udelay (1); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub + */ +static int hc_start (struct ohci_hcd *ohci) +{ + __u32 mask; + unsigned int fminterval; + struct usb_device *udev; + + spin_lock_init (&ohci->lock); + ohci->disabled = 1; + ohci->sleeping = 0; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + /* a reset clears this */ + writel ((u32) ohci->hcca_dma, &ohci->regs->hcca); + + fminterval = 0x2edf; + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); + + /* start controller operations */ + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + ohci->disabled = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* Choose the interrupts we care about now, others later on demand */ + mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; + writel (mask, &ohci->regs->intrstatus); + writel (mask, &ohci->regs->intrenable); + +#ifdef OHCI_USE_NPS + /* required for AMD-756 and some Mac platforms */ + writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + &ohci->regs->roothub.a); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); +#endif /* OHCI_USE_NPS */ + + // POTPGT delay is bits 24-31, in 2 ms units. + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + + /* connect the virtual root hub */ + ohci->hcd.bus->root_hub = udev = usb_alloc_dev (NULL, ohci->hcd.bus); + ohci->hcd.state = USB_STATE_READY; + if (!udev) { + ohci->disabled = 1; +// FIXME cleanup + return -ENOMEM; + } + + usb_connect (udev); + udev->speed = USB_SPEED_FULL; + if (usb_new_device (udev) != 0) { + usb_free_dev (udev); + ohci->disabled = 1; +// FIXME cleanup + return -ENODEV; + } + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static void ohci_irq (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + struct ohci_regs *regs = ohci->regs; + int ints; + + if ((ohci->hcca->done_head != 0) + && ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { + ints = OHCI_INTR_WDH; + } else if ((ints = (readl (®s->intrstatus) + & readl (®s->intrenable))) == 0) { + return; + } + + // dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); + + if (ints & OHCI_INTR_UE) { + ohci->disabled++; + err ("OHCI Unrecoverable Error, %s disabled", hcd->bus_name); + // e.g. due to PCI Master/Target Abort + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + hc_reset (ohci); + } + + if (ints & OHCI_INTR_WDH) { + writel (OHCI_INTR_WDH, ®s->intrdisable); + dl_done_list (ohci, dl_reverse_done_list (ohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); + } + + if (ints & OHCI_INTR_SO) { + dbg ("USB Schedule overrun"); + writel (OHCI_INTR_SO, ®s->intrenable); + } + + // FIXME: this assumes SOF (1/ms) interrupts don't get lost... + if (ints & OHCI_INTR_SF) { + unsigned int frame = le16_to_cpu (ohci->hcca->frame_no) & 1; + writel (OHCI_INTR_SF, ®s->intrdisable); + if (ohci->ed_rm_list [!frame] != NULL) { + dl_del_list (ohci, !frame); + } + if (ohci->ed_rm_list [frame] != NULL) + writel (OHCI_INTR_SF, ®s->intrenable); + } + + writel (ints, ®s->intrstatus); + writel (OHCI_INTR_MIE, ®s->intrenable); +} + +/*-------------------------------------------------------------------------*/ + +static void ohci_stop (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + + dbg ("%s: stop %s controller%s", + hcd->bus_name, + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS), + ohci->disabled ? " (disabled)" : "" + ); +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + + if (!ohci->disabled) + hc_reset (ohci); + + ohci_mem_cleanup (ohci); + +#ifdef CONFIG_PCI + pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca, + ohci->hcca, ohci->hcca_dma); +#endif +} + +/*-------------------------------------------------------------------------*/ + +static int __devinit +ohci_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; + +#ifdef CONFIG_PCI + if (hcd->pdev) { + ohci->hcca = pci_alloc_consistent (hcd->pdev, + sizeof *ohci->hcca, &ohci->hcca_dma); + if (!ohci->hcca) + return -ENOMEM; + + /* AMD 756, for most chips (early revs), corrupts register + * values on read ... so enable the vendor workaround. + */ + if (hcd->pdev->vendor == 0x1022 + && hcd->pdev->device == 0x740c) { + ohci->flags = OHCI_QUIRK_AMD756; + info ("%s: AMD756 erratum 4 workaround", + hcd->bus_name); + } + + /* Apple's OHCI driver has a lot of bizarre workarounds + * for this chip. Evidently control and bulk lists + * can get confused. (B&W G3 models, and ...) + */ + else if (hcd->pdev->vendor == 0x1045 + && hcd->pdev->device == 0xc861) { + info ("%s: WARNING: OPTi workarounds unavailable", + hcd->bus_name); + } + } +#else +# error "where's hcca coming from?" +#endif /* CONFIG_PCI */ + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + if ((ret = ohci_mem_init (ohci)) < 0) { + ohci_stop (hcd); + return ret; + } + ohci->regs = hcd->regs; + + if (hc_reset (ohci) < 0) { + ohci_stop (hcd); + return -ENODEV; + } + + if (hc_start (ohci) < 0) { + err ("can't start %s", ohci->hcd.bus_name); + ohci_stop (hcd); + return -EBUSY; + } + +#ifdef DEBUG + ohci_dump (ohci, 1); +#endif + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PM + +static int ohci_suspend (struct usb_hcd *hcd, u32 state) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + u16 cmd; + + if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { + dbg ("can't suspend %s (state is %s)", hcd->bus_name, + hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); + return -EIO; + } + + /* act as if usb suspend can always be used */ + dbg ("%s: suspend to %d", hcd->bus_name, state); + ohci->sleeping = 1; + + /* First stop processing */ + spin_lock_irqsave (&ohci->lock, flags); + ohci->hc_control &= + ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); + writel (ohci->hc_control, &ohci->regs->control); + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + (void) readl (&ohci->regs->intrstatus); + spin_unlock_irqrestore (&ohci->lock, flags); + + /* Wait a frame or two */ + mdelay (1); + if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) + mdelay (1); + + #ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + disable_irq (ohci->irq); + /* else, 2.4 assumes shared irqs -- don't disable */ + #endif + + /* Enable remote wakeup */ + writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, + &ohci->regs->intrenable); + + /* Suspend chip and let things settle down a bit */ + ohci->hc_control = OHCI_USB_SUSPEND; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (500); /* No schedule here ! */ + + switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) { + case OHCI_USB_RESET: + dbg ("%s suspend->reset ?", hcd->bus_name); + break; + case OHCI_USB_RESUME: + dbg ("%s suspend->resume ?", hcd->bus_name); + break; + case OHCI_USB_OPER: + dbg ("%s suspend->operational ?", hcd->bus_name); + break; + case OHCI_USB_SUSPEND: + dbg ("%s suspended", hcd->bus_name); + break; + } + + /* In some rare situations, Apple's OHCI have happily trashed + * memory during sleep. We disable its bus master bit during + * suspend + */ + pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_MASTER; + pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Disable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (hcd->pdev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); + } +#endif + return 0; +} + + +// FIXME: this restart logic should be generic, +// and handle full hcd state cleanup + +/* controller died; cleanup debris, then restart */ +/* must not be called from interrupt context */ + +static int hc_restart (struct ohci_hcd *ohci) +{ + int temp; + int i; + + ohci->disabled = 1; + ohci->sleeping = 0; + if (ohci->hcd.bus->root_hub) + usb_disconnect (&ohci->hcd.bus->root_hub); + + /* empty the interrupt branches */ + for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load [i] = 0; + for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0; + + /* no EDs to remove */ + ohci->ed_rm_list [0] = NULL; + ohci->ed_rm_list [1] = NULL; + + /* empty control and bulk lists */ + ohci->ed_isotail = NULL; + ohci->ed_controltail = NULL; + ohci->ed_bulktail = NULL; + + if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) { + err ("can't restart %s, %d", ohci->hcd.bus_name, temp); + return temp; + } else + dbg ("restart %s completed", ohci->hcd.bus_name); + return 0; +} + +static int ohci_resume (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int temp; + int retval = 0; + unsigned long flags; + +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Re-enable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (hcd->pdev); + if (of_node) + pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); + } +#endif + /* did we suspend, or were we powered off? */ + ohci->hc_control = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + +#ifdef DEBUG + /* the registers may look crazy here */ + ohci_dump_status (ohci); +#endif + + /* Re-enable bus mastering */ + pci_set_master (ohci->hcd.pdev); + + switch (temp) { + + case OHCI_USB_RESET: // lost power + info ("USB restart: %s", hcd->bus_name); + retval = hc_restart (ohci); + break; + + case OHCI_USB_SUSPEND: // host wakeup + case OHCI_USB_RESUME: // remote wakeup + info ("USB continue: %s from %s wakeup", hcd->bus_name, + (temp == OHCI_USB_SUSPEND) + ? "host" : "remote"); + ohci->hc_control = OHCI_USB_RESUME; + writel (ohci->hc_control, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (20); /* no schedule here ! */ + /* Some controllers (lucent) need a longer delay here */ + mdelay (15); + + temp = readl (&ohci->regs->control); + temp = ohci->hc_control & OHCI_CTRL_HCFS; + if (temp != OHCI_USB_RESUME) { + err ("controller %s won't resume", hcd->bus_name); + ohci->disabled = 1; + retval = -EIO; + break; + } + + /* Some chips likes being resumed first */ + writel (OHCI_USB_OPER, &ohci->regs->control); + (void) readl (&ohci->regs->control); + mdelay (3); + + /* Then re-enable operations */ + spin_lock_irqsave (&ohci->lock, flags); + ohci->disabled = 0; + ohci->sleeping = 0; + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + if (!ohci->ed_rm_list [0] && !ohci->ed_rm_list [1]) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + } + hcd->state = USB_STATE_READY; + writel (ohci->hc_control, &ohci->regs->control); + + /* trigger a start-frame interrupt (why?) */ + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + + /* Check for a pending done list */ + writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); + (void) readl (&ohci->regs->intrdisable); + spin_unlock_irqrestore (&ohci->lock, flags); + + #ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + enable_irq (ohci->irq); + #endif + if (ohci->hcca->done_head) + dl_done_list (ohci, dl_reverse_done_list (ohci)); + writel (OHCI_INTR_WDH, &ohci->regs->intrenable); + +// writel (OHCI_BLF, &ohci->regs->cmdstatus); +// writel (OHCI_CLF, &ohci->regs->cmdstatus); +ohci_dump_status (ohci); +dbg ("sleeping = %d, disabled = %d", ohci->sleeping, ohci->disabled); + break; + + default: + warn ("odd PCI resume for %s", hcd->bus_name); + } + return retval; +} + +#endif /* CONFIG_PM */ + + +/*-------------------------------------------------------------------------*/ + +static const char hcd_name [] = "ohci-hcd"; + +static const struct hc_driver ohci_driver = { + description: hcd_name, + + /* + * generic hardware linkage + */ + irq: ohci_irq, + flags: HCD_MEMORY | HCD_USB11, + + /* + * basic lifecycle operations + */ + start: ohci_start, +#ifdef CONFIG_PM + suspend: ohci_suspend, + resume: ohci_resume, +#endif + stop: ohci_stop, + + /* + * memory lifecycle (except per-request) + */ + hcd_alloc: ohci_hcd_alloc, + hcd_free: ohci_hcd_free, + + /* + * managing i/o requests and associated device resources + */ + urb_enqueue: ohci_urb_enqueue, + urb_dequeue: ohci_urb_dequeue, + free_config: ohci_free_config, + + /* + * scheduling support + */ + get_frame_number: ohci_get_frame, + + /* + * root hub support + */ + hub_status_data: ohci_hub_status_data, + hub_control: ohci_hub_control, +}; + +#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC + +EXPORT_NO_SYMBOLS; +MODULE_AUTHOR (DRIVER_AUTHOR); +MODULE_DESCRIPTION (DRIVER_INFO); +MODULE_LICENSE ("GPL"); + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_PCI + +/* There do exist non-PCI implementations of OHCI ... + * Examples include the SA-1111 (ARM) and some MIPS + * and related hardware. + */ + +static const struct pci_device_id __devinitdata pci_ids [] = { { + + /* handle any USB OHCI controller */ + class: (PCI_CLASS_SERIAL_USB << 8) | 0x10, + class_mask: ~0, + driver_data: (unsigned long) &ohci_driver, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; +MODULE_DEVICE_TABLE (pci, pci_ids); + +/* pci driver glue; this is a "new style" PCI driver module */ +static struct pci_driver ohci_pci_driver = { + name: (char *) hcd_name, + id_table: pci_ids, + + probe: usb_hcd_pci_probe, + remove: usb_hcd_pci_remove, + +#ifdef CONFIG_PM + suspend: usb_hcd_pci_suspend, + resume: usb_hcd_pci_resume, +#endif +}; + + +static int __init ohci_hcd_init (void) +{ + dbg (DRIVER_INFO); + dbg ("block sizes: ed %d td %d", + sizeof (struct ed), sizeof (struct td)); + return pci_module_init (&ohci_pci_driver); +} +module_init (ohci_hcd_init); + +/*-------------------------------------------------------------------------*/ + +static void __exit ohci_hcd_cleanup (void) +{ + pci_unregister_driver (&ohci_pci_driver); +} +module_exit (ohci_hcd_cleanup); + +#endif /* CONFIG_PCI */ + diff -Nru a/drivers/usb/hcd/ohci-hub.c b/drivers/usb/hcd/ohci-hub.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/hcd/ohci-hub.c Mon Jan 21 12:28:40 2002 @@ -0,0 +1,267 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * This file is licenced under GPL + * $Id: ohci-hub.c,v 1.2 2002/01/19 00:21:49 dbrownell Exp $ + */ + +/*-------------------------------------------------------------------------*/ + +/* + * OHCI Root Hub ... the nonsharable stuff + * + * Registers don't need cpu_to_le32, that happens transparently + */ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci_hcd *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci_hcd *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci_hcd *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci_hcd *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + +/*-------------------------------------------------------------------------*/ + +#define dbg_port(hc,label,num,value) \ + dbg ("%s: %s roothub.portstatus [%d] " \ + "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", \ + hc->hcd.bus_name, label, num, temp, \ + (temp & RH_PS_PRSC) ? " PRSC" : "", \ + (temp & RH_PS_OCIC) ? " OCIC" : "", \ + (temp & RH_PS_PSSC) ? " PSSC" : "", \ + (temp & RH_PS_PESC) ? " PESC" : "", \ + (temp & RH_PS_CSC) ? " CSC" : "", \ + \ + (temp & RH_PS_LSDA) ? " LSDA" : "", \ + (temp & RH_PS_PPS) ? " PPS" : "", \ + (temp & RH_PS_PRS) ? " PRS" : "", \ + (temp & RH_PS_POCI) ? " POCI" : "", \ + (temp & RH_PS_PSS) ? " PSS" : "", \ + \ + (temp & RH_PS_PES) ? " PES" : "", \ + (temp & RH_PS_CCS) ? " CCS" : "" \ + ); + + +/*-------------------------------------------------------------------------*/ + +/* build "status change" packet (one or two bytes) from HC registers */ + +static int +ohci_hub_status_data (struct usb_hcd *hcd, char *buf) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ports, i, changed = 0, length = 1; + + ports = roothub_a (ohci) & RH_A_NDP; + if (ports > MAX_ROOT_PORTS) { + err ("%s: bogus NDP=%d", hcd->bus_name, ports); + err ("rereads as NDP=%d", + readl (&ohci->regs->roothub.a) & RH_A_NDP); + /* retry later; "should not happen" */ + return 0; + } + + /* init status */ + if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC)) + buf [0] = changed = 1; + else + buf [0] = 0; + if (ports > 7) { + buf [1] = 0; + length++; + } + + /* look at each port */ + for (i = 0; i < ports; i++) { + u32 status = roothub_portstatus (ohci, i); + + status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC + | RH_PS_OCIC | RH_PS_PRSC; + if (status) { + changed = 1; + set_bit (i + 1, buf); + } + } + return changed ? length : 0; +} + +/*-------------------------------------------------------------------------*/ + +static void +ohci_hub_descriptor ( + struct ohci_hcd *ohci, + struct usb_hub_descriptor *desc +) { + u32 rh = roothub_a (ohci); + int ports = rh & RH_A_NDP; + u16 temp; + + desc->bDescriptorType = 0x29; + desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24; + desc->bHubContrCurrent = 0; + + desc->bNbrPorts = ports; + temp = 1 + (ports / 8); + desc->bDescLength = 7 + 2 * temp; + + temp = 0; + if (rh & RH_A_PSM) /* per-port power switching? */ + temp |= 0x0001; + if (rh & RH_A_NOCP) /* no overcurrent reporting? */ + temp |= 0x0010; + else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */ + temp |= 0x0008; + desc->wHubCharacteristics = cpu_to_le16 (temp); + + /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ + rh = roothub_b (ohci); + desc->bitmap [0] = rh & RH_B_DR; + if (ports > 7) { + desc->bitmap [1] = (rh & RH_B_DR) >> 8; + desc->bitmap [2] = desc->bitmap [3] = 0xff; + } else + desc->bitmap [1] = 0xff; +} + +/*-------------------------------------------------------------------------*/ + +static int ohci_hub_control ( + struct usb_hcd *hcd, + u16 typeReq, + u16 wValue, + u16 wIndex, + char *buf, + u16 wLength +) { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ports; + u32 temp; + int retval = 0; + + // if (port request) + ports = roothub_a (ohci) & RH_A_NDP; + switch (typeReq) { + case ClearHubFeature: + switch (wValue) { + case C_HUB_OVER_CURRENT: + writel (RH_HS_OCIC, &ohci->regs->roothub.status); + case C_HUB_LOCAL_POWER: + break; + default: + goto error; + } + break; + case ClearPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + temp = RH_PS_CCS; + break; + case USB_PORT_FEAT_C_ENABLE: + temp = RH_PS_PESC; + break; + case USB_PORT_FEAT_SUSPEND: + temp = RH_PS_POCI; + break; + case USB_PORT_FEAT_C_SUSPEND: + temp = RH_PS_PSSC; + break; + case USB_PORT_FEAT_POWER: + temp = RH_PS_LSDA; + break; + case USB_PORT_FEAT_C_CONNECTION: + temp = RH_PS_CSC; + break; + case USB_PORT_FEAT_C_OVER_CURRENT: + temp = RH_PS_OCIC; + break; + case USB_PORT_FEAT_C_RESET: + temp = RH_PS_PRSC; + break; + default: + goto error; + } + writel (temp, &ohci->regs->roothub.portstatus [wIndex]); + // readl (&ohci->regs->roothub.portstatus [wIndex]); + break; + case GetHubDescriptor: + ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf); + break; + case GetHubStatus: + temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE); + *(u32 *) buf = cpu_to_le32 (temp); + break; + case GetPortStatus: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + temp = roothub_portstatus (ohci, wIndex); + *(u32 *) buf = cpu_to_le32 (temp); + +#ifndef OHCI_VERBOSE_DEBUG + if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ +#endif + dbg_port (ohci, "GetStatus", wIndex + 1, temp); + break; + case SetHubFeature: + switch (wValue) { + case C_HUB_OVER_CURRENT: + // FIXME: this can be cleared, yes? + case C_HUB_LOCAL_POWER: + break; + default: + goto error; + } + break; + case SetPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + writel (RH_PS_PSS, + &ohci->regs->roothub.portstatus [wIndex]); + break; + case USB_PORT_FEAT_POWER: + writel (RH_PS_PPS, + &ohci->regs->roothub.portstatus [wIndex]); + break; + case USB_PORT_FEAT_RESET: + temp = readl (&ohci->regs->roothub.portstatus [wIndex]); + if (temp & RH_PS_CCS) + writel (RH_PS_PRS, + &ohci->regs->roothub.portstatus [wIndex]); + break; + default: + goto error; + } + break; + + default: +error: + /* "protocol stall" on error */ + retval = -EPIPE; + } + return retval; +} + diff -Nru a/drivers/usb/hcd/ohci-mem.c b/drivers/usb/hcd/ohci-mem.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/hcd/ohci-mem.c Mon Jan 21 12:28:40 2002 @@ -0,0 +1,251 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * This file is licenced under GPL + * $Id: ohci-mem.c,v 1.2 2002/01/19 00:22:13 dbrownell Exp $ + */ + +/*-------------------------------------------------------------------------*/ + +/* + * There's basically three types of memory: + * - data used only by the HCD ... kmalloc is fine + * - async and periodic schedules, shared by HC and HCD ... these + * need to use pci_pool or pci_alloc_consistent + * - driver buffers, read/written by HC ... single shot DMA mapped + * + * There's also PCI "register" data, which is memory mapped. + * No memory seen by this driver is pagable. + */ + +/*-------------------------------------------------------------------------*/ + +static struct usb_hcd *ohci_hcd_alloc (void) +{ + struct ohci_hcd *ohci; + + ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL); + if (ohci != 0) { + memset (ohci, 0, sizeof (struct ohci_hcd)); + return &ohci->hcd; + } + return 0; +} + +static void ohci_hcd_free (struct usb_hcd *hcd) +{ + kfree (hcd_to_ohci (hcd)); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +# define OHCI_MEM_FLAGS SLAB_POISON +#else +# define OHCI_MEM_FLAGS 0 +#endif + +#ifndef CONFIG_PCI +# error "usb-ohci currently requires PCI-based controllers" + /* to support non-PCI OHCIs, you need custom bus/mem/... glue */ +#endif + + +/* Recover a TD/ED using its collision chain */ +static inline void * +dma_to_ed_td (struct hash_list_t * entry, dma_addr_t dma) +{ + struct hash_t * scan = entry->head; + while (scan && scan->dma != dma) + scan = scan->next; + return scan->virt; +} + +static inline struct ed * +dma_to_ed (struct ohci_hcd *hc, dma_addr_t ed_dma) +{ + return (struct ed *) dma_to_ed_td(&(hc->ed_hash [ED_HASH_FUNC(ed_dma)]), + ed_dma); +} + +static inline struct td * +dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma) +{ + return (struct td *) dma_to_ed_td(&(hc->td_hash [TD_HASH_FUNC(td_dma)]), + td_dma); +} + +// FIXME: when updating the hashtables this way, mem_flags is unusable... + +/* Add a hash entry for a TD/ED; return true on success */ +static int +hash_add_ed_td ( + struct hash_list_t *entry, + void *virt, + dma_addr_t dma, + int mem_flags +) +{ + struct hash_t * scan; + + scan = (struct hash_t *) kmalloc (sizeof *scan, mem_flags); + if (!scan) + return 0; + + if (!entry->tail) { + entry->head = entry->tail = scan; + } else { + entry->tail->next = scan; + entry->tail = scan; + } + + scan->virt = virt; + scan->dma = dma; + scan->next = NULL; + return 1; +} + +static inline int +hash_add_ed (struct ohci_hcd *hc, struct ed *ed, int mem_flags) +{ + return hash_add_ed_td (&(hc->ed_hash [ED_HASH_FUNC (ed->dma)]), + ed, ed->dma, mem_flags); +} + +static inline int +hash_add_td (struct ohci_hcd *hc, struct td *td, int mem_flags) +{ + return hash_add_ed_td (&(hc->td_hash [TD_HASH_FUNC (td->td_dma)]), + td, td->td_dma, mem_flags); +} + + +static void +hash_free_ed_td (struct hash_list_t *entry, void *virt) +{ + struct hash_t *scan, *prev; + scan = prev = entry->head; + + // Find and unlink hash entry + while (scan && scan->virt != virt) { + prev = scan; + scan = scan->next; + } + if (scan) { + if (scan == entry->head) { + if (entry->head == entry->tail) + entry->head = entry->tail = NULL; + else + entry->head = scan->next; + } else if (scan == entry->tail) { + entry->tail = prev; + prev->next = NULL; + } else + prev->next = scan->next; + kfree(scan); + } +} + +static inline void +hash_free_ed (struct ohci_hcd *hc, struct ed * ed) +{ + hash_free_ed_td (&(hc->ed_hash[ED_HASH_FUNC(ed->dma)]), ed); +} + +static inline void +hash_free_td (struct ohci_hcd *hc, struct td * td) +{ + hash_free_ed_td (&(hc->td_hash[TD_HASH_FUNC(td->td_dma)]), td); +} + + +static int ohci_mem_init (struct ohci_hcd *ohci) +{ + ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev, + sizeof (struct td), + 32 /* byte alignment */, + 0 /* no page-crossing issues */, + GFP_KERNEL | OHCI_MEM_FLAGS); + if (!ohci->td_cache) + return -ENOMEM; + ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev, + sizeof (struct ed), + 16 /* byte alignment */, + 0 /* no page-crossing issues */, + GFP_KERNEL | OHCI_MEM_FLAGS); + if (!ohci->ed_cache) { + pci_pool_destroy (ohci->td_cache); + return -ENOMEM; + } + return 0; +} + +static void ohci_mem_cleanup (struct ohci_hcd *ohci) +{ + if (ohci->td_cache) { + pci_pool_destroy (ohci->td_cache); + ohci->td_cache = 0; + } + if (ohci->ed_cache) { + pci_pool_destroy (ohci->ed_cache); + ohci->ed_cache = 0; + } +} + +/* TDs ... */ +static struct td * +td_alloc (struct ohci_hcd *hc, int mem_flags) +{ + dma_addr_t dma; + struct td *td; + + td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); + if (td) { + td->td_dma = dma; + /* hash it for later reverse mapping */ + if (!hash_add_td (hc, td, mem_flags)) { + pci_pool_free (hc->td_cache, td, dma); + return NULL; + } + } + return td; +} + +static inline void +td_free (struct ohci_hcd *hc, struct td *td) +{ + hash_free_td (hc, td); + pci_pool_free (hc->td_cache, td, td->td_dma); +} + + +/* EDs ... */ +static struct ed * +ed_alloc (struct ohci_hcd *hc, int mem_flags) +{ + dma_addr_t dma; + struct ed *ed; + + ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma); + if (ed) { + memset (ed, 0, sizeof (*ed)); + ed->dma = dma; + /* hash it for later reverse mapping */ + if (!hash_add_ed (hc, ed, mem_flags)) { + pci_pool_free (hc->ed_cache, ed, dma); + return NULL; + } + } + return ed; +} + +static inline void +ed_free (struct ohci_hcd *hc, struct ed *ed) +{ + hash_free_ed (hc, ed); + pci_pool_free (hc->ed_cache, ed, ed->dma); +} + diff -Nru a/drivers/usb/hcd/ohci-q.c b/drivers/usb/hcd/ohci-q.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/hcd/ohci-q.c Mon Jan 21 12:28:40 2002 @@ -0,0 +1,1000 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * This file is licenced under GPL + * $Id: ohci-q.c,v 1.6 2002/01/19 00:23:15 dbrownell Exp $ + */ + +static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv) +{ + int last = urb_priv->length - 1; + + if (last >= 0) { + int i; + struct td *td = urb_priv->td [0]; +#ifdef CONFIG_PCI + int len = td->urb->transfer_buffer_length; + int dir = usb_pipeout (td->urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE; + + /* unmap CTRL URB setup buffer (always td 0) */ + if (usb_pipecontrol (td->urb->pipe)) { + pci_unmap_single (hc->hcd.pdev, + td->data_dma, 8, PCI_DMA_TODEVICE); + + /* CTRL data buffer starts at td 1 if len > 0 */ + if (len && last > 0) + td = urb_priv->td [1]; + } + /* else: ISOC, BULK, INTR data buffer starts at td 0 */ + + /* unmap data buffer */ + if (len && td->data_dma) + pci_unmap_single (hc->hcd.pdev, + td->data_dma, len, dir); +#else +# warning "assuming no buffer unmapping is needed" +#endif + + for (i = 0; i <= last; i++) { + td = urb_priv->td [i]; + if (td) + td_free (hc, td); + } + } + + kfree (urb_priv); +} + +/*-------------------------------------------------------------------------*/ + +/* + * URB goes back to driver, and isn't reissued. + * It's completely gone from HC data structures, so no locking + * is needed ... or desired! (Giveback can call back to hcd.) + */ +static inline void finish_urb (struct ohci_hcd *ohci, struct urb *urb) +{ + if (urb->hcpriv) { + urb_free_priv (ohci, urb->hcpriv); + urb->hcpriv = NULL; + } + usb_hcd_giveback_urb (&ohci->hcd, urb); +} + +static void td_submit_urb (struct urb *urb); + +/* + * URB is reported to driver, is reissued if it's periodic. + */ +static int return_urb (struct ohci_hcd *hc, struct urb *urb) +{ + urb_priv_t *urb_priv = urb->hcpriv; + struct urb *urbt; + unsigned long flags; + int i; + +#ifdef DEBUG + if (!urb_priv) { + err ("already unlinked!"); + BUG (); + } + + /* just to be sure */ + if (!urb->complete) { + err ("no completion!"); + BUG (); + } +#endif + +#ifdef OHCI_VERBOSE_DEBUG + urb_print (urb, "RET", usb_pipeout (urb->pipe)); +#endif + +// FIXME: but if urb->status says it was was unlinked ... + + switch (usb_pipetype (urb->pipe)) { + case PIPE_INTERRUPT: +#ifdef CONFIG_PCI + pci_unmap_single (hc->hcd.pdev, + urb_priv->td [0]->data_dma, + urb->transfer_buffer_length, + usb_pipeout (urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE); +#endif + urb->complete (urb); + + /* implicitly requeued */ + urb->actual_length = 0; + urb->status = -EINPROGRESS; + if (urb_priv->state != URB_DEL) { + spin_lock_irqsave (&hc->lock, flags); + td_submit_urb (urb); + spin_unlock_irqrestore (&hc->lock, flags); + } + break; + + case PIPE_ISOCHRONOUS: + for (urbt = urb->next; + urbt && (urbt != urb); + urbt = urbt->next) + continue; + if (urbt) { /* send the reply and requeue URB */ +#ifdef CONFIG_PCI +// FIXME this style unmap is only done on this route ... + pci_unmap_single (hc->hcd.pdev, + urb_priv->td [0]->data_dma, + urb->transfer_buffer_length, + usb_pipeout (urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE); +#endif + urb->complete (urb); + spin_lock_irqsave (&hc->lock, flags); + urb->actual_length = 0; + urb->status = -EINPROGRESS; + urb->start_frame = urb_priv->ed->last_iso + 1; + if (urb_priv->state != URB_DEL) { + for (i = 0; i < urb->number_of_packets; + i++) { + urb->iso_frame_desc [i] + .actual_length = 0; + urb->iso_frame_desc [i] + .status = -EXDEV; + } + td_submit_urb (urb); + } +// FIXME if not deleted, should have been "finished" + spin_unlock_irqrestore (&hc->lock, flags); + + } else { /* not reissued */ + finish_urb (hc, urb); + } + break; + + /* + * C/B requests that get here are never reissued. + */ + case PIPE_BULK: + case PIPE_CONTROL: + finish_urb (hc, urb); + break; + } + return 0; +} + + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* search for the right branch to insert an interrupt ed into the int tree + * do some load balancing; + * returns the branch and + * sets the interval to interval = 2^integer (ld (interval)) + */ +static int ep_int_balance (struct ohci_hcd *ohci, int interval, int load) +{ + int i, branch = 0; + + /* search for the least loaded interrupt endpoint branch */ + for (i = 0; i < NUM_INTS ; i++) + if (ohci->ohci_int_load [branch] > ohci->ohci_int_load [i]) + branch = i; + + branch = branch % interval; + for (i = branch; i < NUM_INTS; i += interval) + ohci->ohci_int_load [i] += load; + + return branch; +} + +/*-------------------------------------------------------------------------*/ + +/* 2^int ( ld (inter)) */ + +static int ep_2_n_interval (int inter) +{ + int i; + + for (i = 0; ((inter >> i) > 1 ) && (i < 5); i++) + continue; + return 1 << i; +} + +/*-------------------------------------------------------------------------*/ + +/* the int tree is a binary tree + * in order to process it sequentially the indexes of the branches have + * to be mapped the mapping reverses the bits of a word of num_bits length + */ +static int ep_rev (int num_bits, int word) +{ + int i, wout = 0; + + for (i = 0; i < num_bits; i++) + wout |= (( (word >> i) & 1) << (num_bits - i - 1)); + return wout; +} + +/*-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (struct ohci_hcd *ohci, struct ed *edi) +{ + int int_branch, i; + int inter, interval, load; + __u32 *ed_p; + volatile struct ed *ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel (ed->dma, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail + && !ohci->ed_rm_list [0] + && !ohci->ed_rm_list [1] + && !ohci->sleeping + ) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = edi; + break; + + case PIPE_BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel (ed->dma, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail + && !ohci->ed_rm_list [0] + && !ohci->ed_rm_list [1] + && !ohci->sleeping + ) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + + case PIPE_INTERRUPT: + load = ed->int_load; + interval = ep_2_n_interval (ed->int_period); + ed->int_interval = interval; + int_branch = ep_int_balance (ohci, interval, load); + ed->int_branch = int_branch; + + for (i = 0; i < ep_rev (6, interval); i += inter) { + inter = 1; + for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i) + int_branch]); + (*ed_p != 0) && ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval >= interval); + ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) + inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); + ed->hwNextED = *ed_p; + *ed_p = cpu_to_le32 (ed->dma); + } +#ifdef DEBUG + ep_print_int_eds (ohci, "LINK_INT"); +#endif + break; + + case PIPE_ISOCHRONOUS: + ed->hwNextED = 0; + ed->int_interval = 1; + if (ohci->ed_isotail != NULL) { + ohci->ed_isotail->hwNextED = cpu_to_le32 (ed->dma); + ed->ed_prev = ohci->ed_isotail; + } else { + for ( i = 0; i < NUM_INTS; i += inter) { + inter = 1; + for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i)]); + *ed_p != 0; + ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) + inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); + *ed_p = cpu_to_le32 (ed->dma); + } + ed->ed_prev = NULL; + } + ohci->ed_isotail = edi; +#ifdef DEBUG + ep_print_int_eds (ohci, "LINK_ISO"); +#endif + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* unlink an ed from one of the HC chains. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed + */ +static int ep_unlink (struct ohci_hcd *ohci, struct ed *ed) +{ + int int_branch; + int i; + int inter; + int interval; + __u32 *ed_p; + + ed->hwINFO |= __constant_cpu_to_le32 (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (le32_to_cpup (&ed->hwNextED), + &ohci->regs->ed_controlhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_controltail == ed) { + ohci->ed_controltail = ed->ed_prev; + } else { + (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) + ->ed_prev = ed->ed_prev; + } + break; + + case PIPE_BULK: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (le32_to_cpup (&ed->hwNextED), + &ohci->regs->ed_bulkhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_bulktail == ed) { + ohci->ed_bulktail = ed->ed_prev; + } else { + (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) + ->ed_prev = ed->ed_prev; + } + break; + + case PIPE_INTERRUPT: + int_branch = ed->int_branch; + interval = ed->int_interval; + + for (i = 0; i < ep_rev (6, interval); i += inter) { + for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i) + int_branch]), inter = 1; + (*ed_p != 0) && (*ed_p != ed->hwNextED); + ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED), + inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval)) { + if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { + *ed_p = ed->hwNextED; + break; + } + } + } + for (i = int_branch; i < NUM_INTS; i += interval) + ohci->ohci_int_load [i] -= ed->int_load; +#ifdef DEBUG + ep_print_int_eds (ohci, "UNLINK_INT"); +#endif + break; + + case PIPE_ISOCHRONOUS: + if (ohci->ed_isotail == ed) + ohci->ed_isotail = ed->ed_prev; + if (ed->hwNextED != 0) + (dma_to_ed (ohci, le32_to_cpup (&ed->hwNextED))) + ->ed_prev = ed->ed_prev; + + if (ed->ed_prev != NULL) { + ed->ed_prev->hwNextED = ed->hwNextED; + } else { + for (i = 0; i < NUM_INTS; i++) { + for (ed_p = & (ohci->hcca->int_table [ep_rev (5, i)]); + *ed_p != 0; + ed_p = & ((dma_to_ed (ohci, le32_to_cpup (ed_p)))->hwNextED)) { + // inter = ep_rev (6, (dma_to_ed (ohci, le32_to_cpup (ed_p)))->int_interval); + if ((dma_to_ed (ohci, le32_to_cpup (ed_p))) == ed) { + *ed_p = ed->hwNextED; + break; + } + } + } + } +#ifdef DEBUG + ep_print_int_eds (ohci, "UNLINK_ISO"); +#endif + break; + } + ed->state = ED_UNLINK; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* (re)init an endpoint; this _should_ be done once at the + * usb_set_configuration command, but the USB stack is a bit stateless + * so we do it at every transaction. + * if the state of the ed is ED_NEW then a dummy td is added and the + * state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are set even though most of them should + * not change + */ +static struct ed *ep_add_ed ( + struct usb_device *udev, + unsigned int pipe, + int interval, + int load, + int mem_flags +) { + struct ohci_hcd *ohci = hcd_to_ohci (udev->bus->hcpriv); + struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv; + struct td *td; + struct ed *ed; + unsigned ep; + unsigned long flags; + + spin_lock_irqsave (&ohci->lock, flags); + + ep = usb_pipeendpoint (pipe) << 1; + if (!usb_pipecontrol (pipe) && usb_pipeout (pipe)) + ep |= 1; + if (!(ed = dev->ep [ep])) { + ed = ed_alloc (ohci, SLAB_ATOMIC); + if (!ed) { + /* out of memory */ + spin_unlock_irqrestore (&ohci->lock, flags); + return NULL; + } + dev->ep [ep] = ed; + } + + if (ed->state & ED_URB_DEL) { + /* pending unlink request */ + spin_unlock_irqrestore (&ohci->lock, flags); + return NULL; + } + + if (ed->state == ED_NEW) { + ed->hwINFO = __constant_cpu_to_le32 (OHCI_ED_SKIP); + /* dummy td; end of td list for ed */ + td = td_alloc (ohci, SLAB_ATOMIC); + if (!td) { + /* out of memory */ + spin_unlock_irqrestore (&ohci->lock, flags); + return NULL; + } + ed->hwTailP = cpu_to_le32 (td->td_dma); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + } + + ohci->dev [usb_pipedevice (pipe)] = udev; + +// FIXME: don't do this if it's linked to the HC, +// we might clobber data toggle or other state ... + + ed->hwINFO = cpu_to_le32 (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe) + ? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | (udev->speed == USB_SPEED_LOW) << 13 + | usb_maxpacket (udev, pipe, usb_pipeout (pipe)) + << 16); + + if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { + ed->int_period = interval; + ed->int_load = load; + } + + spin_unlock_irqrestore (&ohci->lock, flags); + return ed; +} + +/*-------------------------------------------------------------------------*/ + +/* request unlinking of an endpoint from an operational HC. + * put the ep on the rm_list and stop the bulk or ctrl list + * real work is done at the next start frame (SF) hardware interrupt + */ +static void ed_unlink (struct usb_device *usb_dev, struct ed *ed) +{ + unsigned int frame; + struct ohci_hcd *ohci = hcd_to_ohci (usb_dev->bus->hcpriv); + + /* already pending? */ + if (ed->state & ED_URB_DEL) + return; + ed->state |= ED_URB_DEL; + + ed->hwINFO |= __constant_cpu_to_le32 (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: /* stop control list */ + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, + &ohci->regs->control); + break; + case PIPE_BULK: /* stop bulk list */ + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, + &ohci->regs->control); + break; + } + + frame = le16_to_cpu (ohci->hcca->frame_no) & 0x1; + ed->ed_rm_list = ohci->ed_rm_list [frame]; + ohci->ed_rm_list [frame] = ed; + + /* enable SOF interrupt */ + if (!ohci->sleeping) { + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + } +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void +td_fill (struct ohci_hcd *ohci, unsigned int info, + dma_addr_t data, int len, + struct urb *urb, int index) +{ + volatile struct td *td, *td_pt; + urb_priv_t *urb_priv = urb->hcpriv; + + if (index >= urb_priv->length) { + err ("internal OHCI error: TD index > length"); + return; + } + + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + td_pt->hwNextTD = 0; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = dma_to_td (ohci, + le32_to_cpup (&urb_priv->ed->hwTailP) & ~0xf); + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->urb = urb; + td->data_dma = data; + if (!len) + data = 0; + + td->hwINFO = cpu_to_le32 (info); + if ((td->ed->type) == PIPE_ISOCHRONOUS) { + td->hwCBP = cpu_to_le32 (data & 0xFFFFF000); + td->ed->last_iso = info & 0xffff; + } else { + td->hwCBP = cpu_to_le32 (data); + } + if (data) + td->hwBE = cpu_to_le32 (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = cpu_to_le32 (td_pt->td_dma); + td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000); + + /* append to queue */ + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ + +static void td_submit_urb (struct urb *urb) +{ + urb_priv_t *urb_priv = urb->hcpriv; + struct ohci_hcd *ohci = hcd_to_ohci (urb->dev->bus->hcpriv); + dma_addr_t data; + int data_len = urb->transfer_buffer_length; + int cnt = 0; + __u32 info = 0; + unsigned int toggle = 0; + + /* OHCI handles the DATA-toggles itself, we just use the + * USB-toggle bits for resetting + */ + if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe))) { + toggle = TD_T_TOGGLE; + } else { + toggle = TD_T_DATA0; + usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe), 1); + } + + urb_priv->td_cnt = 0; + + if (data_len) { +#ifdef CONFIG_PCI + data = pci_map_single (ohci->hcd.pdev, + urb->transfer_buffer, data_len, + usb_pipeout (urb->pipe) + ? PCI_DMA_TODEVICE + : PCI_DMA_FROMDEVICE + ); +#else +# error "what dma addr to use" +#endif + } else + data = 0; + + switch (usb_pipetype (urb->pipe)) { + case PIPE_BULK: + info = usb_pipeout (urb->pipe) + ? TD_CC | TD_DP_OUT + : TD_CC | TD_DP_IN ; + while (data_len > 4096) { + td_fill (ohci, + info | (cnt? TD_T_TOGGLE:toggle), + data, 4096, urb, cnt); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (urb->pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), + data, data_len, urb, cnt); + cnt++; + if ((urb->transfer_flags & USB_ZERO_PACKET) + && cnt < urb_priv->length) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), + 0, 0, urb, cnt); + cnt++; + } + /* start bulk list */ + if (!ohci->sleeping) + writel (OHCI_BLF, &ohci->regs->cmdstatus); + break; + + case PIPE_INTERRUPT: + info = TD_CC | toggle; + info |= usb_pipeout (urb->pipe) + ? TD_DP_OUT + : TD_R | TD_DP_IN; + td_fill (ohci, info, data, data_len, urb, cnt++); + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, +#ifdef CONFIG_PCI + pci_map_single (ohci->hcd.pdev, + urb->setup_packet, 8, + PCI_DMA_TODEVICE), +#else +# error "what dma addr to use" +#endif + 8, urb, cnt++); + if (data_len > 0) { + info = TD_CC | TD_R | TD_T_DATA1; + info |= usb_pipeout (urb->pipe) + ? TD_DP_OUT + : TD_DP_IN; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, + urb, cnt++); + } + info = usb_pipeout (urb->pipe) + ? TD_CC | TD_DP_IN | TD_T_DATA1 + : TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, urb, cnt++); + /* start control list */ + if (!ohci->sleeping) + writel (OHCI_CLF, &ohci->regs->cmdstatus); + break; + + case PIPE_ISOCHRONOUS: + for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + td_fill (ohci, TD_CC | TD_ISO + | ((urb->start_frame + cnt) & 0xffff), + data + urb->iso_frame_desc [cnt].offset, + urb->iso_frame_desc [cnt].length, urb, cnt); + } + break; + } + if (urb_priv->length != cnt) + dbg ("TD LENGTH %d != CNT %d", urb_priv->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length (struct td *td) +{ + __u32 tdINFO, tdBE, tdCBP; + __u16 tdPSW; + struct urb *urb = td->urb; + urb_priv_t *urb_priv = urb->hcpriv; + int dlen = 0; + int cc = 0; + + tdINFO = le32_to_cpup (&td->hwINFO); + tdBE = le32_to_cpup (&td->hwBE); + tdCBP = le32_to_cpup (&td->hwCBP); + + + if (tdINFO & TD_ISO) { + tdPSW = le16_to_cpu (td->hwPSW [0]); + cc = (tdPSW >> 12) & 0xF; + if (cc < 0xE) { + if (usb_pipeout (urb->pipe)) { + dlen = urb->iso_frame_desc [td->index].length; + } else { + dlen = tdPSW & 0x3ff; + } + urb->actual_length += dlen; + urb->iso_frame_desc [td->index].actual_length = dlen; + if (! (urb->transfer_flags & USB_DISABLE_SPD) + && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + + urb->iso_frame_desc [td->index].status + = cc_to_error [cc]; + } + } else { /* BULK, INT, CONTROL DATA */ + if (! (usb_pipetype (urb->pipe) == PIPE_CONTROL && + ((td->index == 0) + || (td->index == urb_priv->length - 1)))) { + if (tdBE != 0) { + urb->actual_length += (td->hwCBP == 0) + ? (tdBE - td->data_dma + 1) + : (tdCBP - td->data_dma); + } + } + } +} + +/*-------------------------------------------------------------------------*/ + +/* replies to the request have to be on a FIFO basis so + * we unreverse the hc-reversed done-list + */ +static struct td *dl_reverse_done_list (struct ohci_hcd *ohci) +{ + __u32 td_list_hc; + struct td *td_rev = NULL; + struct td *td_list = NULL; + urb_priv_t *urb_priv = NULL; + unsigned long flags; + + spin_lock_irqsave (&ohci->lock, flags); + + td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; + ohci->hcca->done_head = 0; + + while (td_list_hc) { + td_list = dma_to_td (ohci, td_list_hc); + + if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) { + urb_priv = (urb_priv_t *) td_list->urb->hcpriv; + dbg (" USB-error/status: %x : %p", + TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), + td_list); + if (td_list->ed->hwHeadP + & __constant_cpu_to_le32 (0x1)) { + if (urb_priv && ((td_list->index + 1) + < urb_priv->length)) { + td_list->ed->hwHeadP = + (urb_priv->td [urb_priv->length - 1]->hwNextTD + & __constant_cpu_to_le32 (0xfffffff0)) + | (td_list->ed->hwHeadP + & __constant_cpu_to_le32 (0x2)); + urb_priv->td_cnt += urb_priv->length + - td_list->index - 1; + } else + td_list->ed->hwHeadP &= + __constant_cpu_to_le32 (0xfffffff2); + } + } + + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0; + } + spin_unlock_irqrestore (&ohci->lock, flags); + return td_list; +} + +/*-------------------------------------------------------------------------*/ + +/* there are some pending requests to unlink + * - some URBs/TDs if urb_priv->state == URB_DEL + */ +static void dl_del_list (struct ohci_hcd *ohci, unsigned int frame) +{ + unsigned long flags; + struct ed *ed; + __u32 edINFO; + __u32 tdINFO; + struct td *td = NULL, *td_next = NULL, + *tdHeadP = NULL, *tdTailP; + __u32 *td_p; + int ctrl = 0, bulk = 0; + + spin_lock_irqsave (&ohci->lock, flags); + + for (ed = ohci->ed_rm_list [frame]; ed != NULL; ed = ed->ed_rm_list) { + + tdTailP = dma_to_td (ohci, + le32_to_cpup (&ed->hwTailP) & 0xfffffff0); + tdHeadP = dma_to_td (ohci, + le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); + edINFO = le32_to_cpup (&ed->hwINFO); + td_p = &ed->hwHeadP; + + for (td = tdHeadP; td != tdTailP; td = td_next) { + struct urb *urb = td->urb; + urb_priv_t *urb_priv = td->urb->hcpriv; + + td_next = dma_to_td (ohci, + le32_to_cpup (&td->hwNextTD) & 0xfffffff0); + if ((urb_priv->state == URB_DEL)) { + tdINFO = le32_to_cpup (&td->hwINFO); + if (TD_CC_GET (tdINFO) < 0xE) + dl_transfer_length (td); + *td_p = td->hwNextTD | (*td_p + & __constant_cpu_to_le32 (0x3)); + + /* URB is done; clean up */ + if (++ (urb_priv->td_cnt) == urb_priv->length) +// FIXME: we shouldn't hold ohci->lock here, else the +// completion function can't talk to this hcd ... + finish_urb (ohci, urb); + } else { + td_p = &td->hwNextTD; + } + } + + ed->state &= ~ED_URB_DEL; + tdHeadP = dma_to_td (ohci, + le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); + + if (tdHeadP == tdTailP) { + if (ed->state == ED_OPER) + ep_unlink (ohci, ed); + td_free (ohci, tdTailP); + ed->hwINFO = __constant_cpu_to_le32 (OHCI_ED_SKIP); + ed->state = ED_NEW; + } else + ed->hwINFO &= ~__constant_cpu_to_le32 (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: + ctrl = 1; + break; + case PIPE_BULK: + bulk = 1; + break; + } + } + + /* maybe reenable control and bulk lists */ + if (!ohci->disabled) { + if (ctrl) /* reset control list */ + writel (0, &ohci->regs->ed_controlcurrent); + if (bulk) /* reset bulk list */ + writel (0, &ohci->regs->ed_bulkcurrent); + if (!ohci->ed_rm_list [!frame]) { + if (ohci->ed_controltail) + ohci->hc_control |= OHCI_CTRL_CLE; + if (ohci->ed_bulktail) + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + } + + ohci->ed_rm_list [frame] = NULL; + spin_unlock_irqrestore (&ohci->lock, flags); +} + + + +/*-------------------------------------------------------------------------*/ + +/* + * process normal completions (error or success) and some unlinked eds + * this is the main path for handing urbs back to drivers + */ +static void dl_done_list (struct ohci_hcd *ohci, struct td *td_list) +{ + struct td *td_list_next = NULL; + struct ed *ed; + int cc = 0; + struct urb *urb; + urb_priv_t *urb_priv; + __u32 tdINFO, edHeadP, edTailP; + + unsigned long flags; + + while (td_list) { + td_list_next = td_list->next_dl_td; + + urb = td_list->urb; + urb_priv = urb->hcpriv; + tdINFO = le32_to_cpup (&td_list->hwINFO); + + ed = td_list->ed; + + dl_transfer_length (td_list); + + /* error code of transfer */ + cc = TD_CC_GET (tdINFO); + if (cc == TD_CC_STALL) + usb_endpoint_halt (urb->dev, + usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)); + + if (! (urb->transfer_flags & USB_DISABLE_SPD) + && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + + if (++ (urb_priv->td_cnt) == urb_priv->length) { + /* + * Except for periodic transfers, both branches do + * the same thing. Periodic urbs get reissued until + * they're "deleted" with usb_unlink_urb. + */ + if ((ed->state & (ED_OPER | ED_UNLINK)) + && (urb_priv->state != URB_DEL)) { + spin_lock (&urb->lock); + if (urb->status == -EINPROGRESS) + urb->status = cc_to_error [cc]; + spin_unlock (&urb->lock); + return_urb (ohci, urb); + } else + finish_urb (ohci, urb); + } + + spin_lock_irqsave (&ohci->lock, flags); + if (ed->state != ED_NEW) { + edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0; + edTailP = le32_to_cpup (&ed->hwTailP); + +// FIXME: ED_UNLINK is very fuzzy w.r.t. what the hc knows... + + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink (ohci, ed); + } + spin_unlock_irqrestore (&ohci->lock, flags); + + td_list = td_list_next; + } +} + diff -Nru a/drivers/usb/hcd/ohci.h b/drivers/usb/hcd/ohci.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/hcd/ohci.h Mon Jan 21 12:28:40 2002 @@ -0,0 +1,360 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * This file is licenced under GPL + * $Id: ohci.h,v 1.5 2002/01/19 00:24:01 dbrownell Exp $ + */ + +static const int cc_to_error [16] = { + +/* map OHCI status to errno values */ + /* No Error */ 0, + /* CRC Error */ -EILSEQ, + /* Bit Stuff */ -EPROTO, + /* Data Togg */ -EILSEQ, + /* Stall */ -EPIPE, + /* DevNotResp */ -ETIMEDOUT, + /* PIDCheck */ -EPROTO, + /* UnExpPID */ -EPROTO, + /* DataOver */ -EOVERFLOW, + /* DataUnder */ -EREMOTEIO, + /* (for hw) */ -EIO, + /* (for hw) */ -EIO, + /* BufferOver */ -ECOMM, + /* BuffUnder */ -ENOSR, + /* (for HCD) */ -EALREADY, + /* (for HCD) */ -EALREADY +}; + + +/* ED States */ + +#define ED_NEW 0x00 /* unused, no dummy td */ +#define ED_UNLINK 0x01 /* dummy td, maybe linked to hc */ +#define ED_OPER 0x02 /* dummy td, _is_ linked to hc */ + +#define ED_URB_DEL 0x08 /* masked in */ + +/* usb_ohci_ed */ +struct ed { + /* first fields are hardware-specified */ + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed * ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; // ED_{NEW,UNLINK,OPER} + __u8 type; + __u16 last_iso; + struct ed * ed_rm_list; + + dma_addr_t dma; + __u32 unused [3]; +} __attribute((aligned(16))); + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 + /* 0x0A, 0x0B reserved for hardware */ +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D + /* 0x0E, 0x0F reserved for HCD */ +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +struct td { + /* first hardware fields are in all tds */ + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + __u16 hwPSW [MAXPSW]; /* PSW is only for ISO */ + + __u8 unused; + __u8 index; + struct ed *ed; + struct td *next_dl_td; + struct urb *urb; + + dma_addr_t td_dma; + dma_addr_t data_dma; + __u32 unused2 [2]; +} __attribute((aligned(32))); /* iso needs 32 */ + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. The host controller is + * told the base address of it. It must be 256-byte aligned. + */ +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table [NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc [116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus [MAX_ROOT_PORTS]; + } roothub; + + /* and some optional registers for legacy compatibility */ +} __attribute((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + + +/* urb */ +typedef struct urb_priv +{ + struct ed *ed; + __u16 length; // # tds in this request + __u16 td_cnt; // tds already serviced + int state; + struct td *td [0]; // all TDs in this request + +} urb_priv_t; + +#define URB_DEL 1 + + +/* Hash struct used for TD/ED hashing */ +struct hash_t { + void *virt; + dma_addr_t dma; + struct hash_t *next; // chaining for collision cases +}; + +/* List of TD/ED hash entries */ +struct hash_list_t { + struct hash_t *head; + struct hash_t *tail; +}; + +#define TD_HASH_SIZE 64 /* power'o'two */ +#define ED_HASH_SIZE 64 /* power'o'two */ + +#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 5)) % TD_HASH_SIZE) +#define ED_HASH_FUNC(ed_dma) ((ed_dma ^ (ed_dma >> 5)) % ED_HASH_SIZE) + + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + +struct ohci_hcd { + spinlock_t lock; + + /* + * I/O memory used to communicate with the HC (uncached); + */ + struct ohci_regs *regs; + + /* + * main memory used to communicate with the HC (uncached) + */ + struct ohci_hcca *hcca; + dma_addr_t hcca_dma; + + struct ed *ed_rm_list [2]; /* to be removed */ + + struct ed *ed_bulktail; /* last in bulk list */ + struct ed *ed_controltail; /* last in ctrl list */ + struct ed *ed_isotail; /* last in iso list */ + +#ifdef CONFIG_PCI + struct pci_pool *td_cache; + struct pci_pool *ed_cache; + struct hash_list_t td_hash [TD_HASH_SIZE]; + struct hash_list_t ed_hash [ED_HASH_SIZE]; +#endif + + /* + * driver state + */ + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + int ohci_int_load [NUM_INTS]; + u32 hc_control; /* copy of hc control reg */ + struct usb_device *dev [128]; + + unsigned long flags; /* for HC bugs */ +#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ + + /* + * framework state + */ + struct usb_hcd hcd; +}; + +#define hcd_to_ohci(hcd_ptr) list_entry(hcd_ptr, struct ohci_hcd, hcd) + diff -Nru a/drivers/usb/hcd.c b/drivers/usb/hcd.c --- a/drivers/usb/hcd.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/hcd.c Mon Jan 21 12:28:40 2002 @@ -606,7 +606,7 @@ return retval; } } - dev->driver_data = hcd; + pci_set_drvdata(dev, hcd); hcd->driver = driver; hcd->description = driver->description; hcd->pdev = dev; @@ -689,7 +689,7 @@ struct usb_hcd *hcd; struct usb_device *hub; - hcd = (struct usb_hcd *) dev->driver_data; + hcd = pci_get_drvdata(dev); if (!hcd) return; info ("remove: %s, state %x", hcd->bus_name, hcd->state); @@ -769,7 +769,7 @@ struct usb_hcd *hcd; int retval; - hcd = (struct usb_hcd *) dev->driver_data; + hcd = pci_get_drvdata(dev); info ("suspend %s to state %d", hcd->bus_name, state); pci_save_state (dev, hcd->pci_state); @@ -798,7 +798,7 @@ struct usb_hcd *hcd; int retval; - hcd = (struct usb_hcd *) dev->driver_data; + hcd = pci_get_drvdata(dev); info ("resume %s", hcd->bus_name); /* guard against multiple resumes (APM bug?) */ diff -Nru a/drivers/usb/ibmcam.h b/drivers/usb/ibmcam.h --- a/drivers/usb/ibmcam.h Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/ibmcam.h Mon Jan 21 12:28:39 2002 @@ -147,7 +147,7 @@ struct ibmcam_sbuf { char *data; - urb_t *urb; + struct urb *urb; }; struct ibmcam_frame { diff -Nru a/drivers/usb/kaweth.c b/drivers/usb/kaweth.c --- a/drivers/usb/kaweth.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/kaweth.c Mon Jan 21 12:28:39 2002 @@ -953,7 +953,7 @@ /*-------------------------------------------------------------------* * completion handler for compatibility wrappers (sync control/bulk) * *-------------------------------------------------------------------*/ -static void usb_api_blocking_completion(urb_t *urb) +static void usb_api_blocking_completion(struct urb *urb) { struct usb_api_data *awd = (struct usb_api_data *)urb->context; @@ -966,7 +966,7 @@ *-------------------------------------------------------------------*/ // Starts urb and waits for completion or timeout -static int usb_start_wait_urb(urb_t *urb, int timeout, int* actual_length) +static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) { DECLARE_WAITQUEUE(wait, current); struct usb_api_data awd; @@ -1017,7 +1017,7 @@ struct usb_ctrlrequest *cmd, void *data, int len, int timeout) { - urb_t *urb; + struct urb *urb; int retv; int length; diff -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c --- a/drivers/usb/ov511.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/ov511.c Mon Jan 21 12:28:40 2002 @@ -3875,7 +3875,7 @@ **********************************************************************/ static int -ov511_move_data(struct usb_ov511 *ov511, urb_t *urb) +ov511_move_data(struct usb_ov511 *ov511, struct urb *urb) { unsigned char *cdata; int data_size, num, offset, i, totlen = 0; @@ -4108,7 +4108,7 @@ } static int -ov518_move_data(struct usb_ov511 *ov511, urb_t *urb) +ov518_move_data(struct usb_ov511 *ov511, struct urb *urb) { unsigned char *cdata; int i, data_size, totlen = 0; @@ -4369,7 +4369,7 @@ static int ov511_init_isoc(struct usb_ov511 *ov511) { - urb_t *urb; + struct urb *urb; int fx, err, n, size; PDEBUG(3, "*** Initializing capture ***"); diff -Nru a/drivers/usb/ov511.h b/drivers/usb/ov511.h --- a/drivers/usb/ov511.h Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/ov511.h Mon Jan 21 12:28:39 2002 @@ -366,7 +366,7 @@ struct ov511_sbuf { char *data; - urb_t *urb; + struct urb *urb; }; enum { diff -Nru a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c --- a/drivers/usb/pegasus.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/pegasus.c Mon Jan 21 12:28:39 2002 @@ -94,7 +94,7 @@ static int update_eth_regs_async( pegasus_t * ); /* Aargh!!! I _really_ hate such tweaks */ -static void ctrl_callback( urb_t *urb ) +static void ctrl_callback( struct urb *urb ) { pegasus_t *pegasus = urb->context; diff -Nru a/drivers/usb/se401.c b/drivers/usb/se401.c --- a/drivers/usb/se401.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/se401.c Mon Jan 21 12:28:40 2002 @@ -610,7 +610,7 @@ */ static int se401_start_stream(struct usb_se401 *se401) { - urb_t *urb; + struct urb *urb; int err=0, i; se401->streaming=1; diff -Nru a/drivers/usb/se401.h b/drivers/usb/se401.h --- a/drivers/usb/se401.h Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/se401.h Mon Jan 21 12:28:40 2002 @@ -197,8 +197,8 @@ char *fbuf; /* Videodev buffer area */ - urb_t *urb[SE401_NUMSBUF]; - urb_t *inturb; + struct urb *urb[SE401_NUMSBUF]; + struct urb *inturb; int button; int buttonpressed; diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c --- a/drivers/usb/serial/ftdi_sio.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/serial/ftdi_sio.c Mon Jan 21 12:28:40 2002 @@ -138,6 +138,7 @@ static __devinitdata struct usb_device_id id_table_8U232AM [] = { { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, + { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, { } /* Terminating entry */ }; @@ -145,6 +146,7 @@ static __devinitdata struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, + { USB_DEVICE(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID) }, { } /* Terminating entry */ }; diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h --- a/drivers/usb/serial/ftdi_sio.h Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/serial/ftdi_sio.h Mon Jan 21 12:28:40 2002 @@ -22,6 +22,8 @@ #define FTDI_VID 0x0403 /* Vendor Id */ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ +#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ +#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c --- a/drivers/usb/serial/io_edgeport.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/serial/io_edgeport.c Mon Jan 21 12:28:40 2002 @@ -2456,7 +2456,7 @@ { struct edgeport_serial *edge_serial = (struct edgeport_serial *)edge_port->port->serial->private; int status = 0; - urb_t *urb; + struct urb *urb; int timeout; usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer); diff -Nru a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c --- a/drivers/usb/serial/keyspan.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/serial/keyspan.c Mon Jan 21 12:28:40 2002 @@ -109,11 +109,11 @@ const keyspan_device_details *device_details; - urb_t *instat_urb; + struct urb *instat_urb; char instat_buf[INSTAT_BUFLEN]; /* XXX this one probably will need a lock */ - urb_t *glocont_urb; + struct urb *glocont_urb; char glocont_buf[GLOCONT_BUFLEN]; }; @@ -128,18 +128,18 @@ const keyspan_device_details *device_details; /* Input endpoints and buffer for this port */ - urb_t *in_urbs[2]; + struct urb *in_urbs[2]; char in_buffer[2][64]; /* Output endpoints and buffer for this port */ - urb_t *out_urbs[2]; + struct urb *out_urbs[2]; char out_buffer[2][64]; /* Input ack endpoint */ - urb_t *inack_urb; + struct urb *inack_urb; char inack_buffer[1]; /* Output control endpoint */ - urb_t *outcont_urb; + struct urb *outcont_urb; char outcont_buffer[64]; /* Settings for the port */ @@ -324,7 +324,7 @@ const keyspan_device_details *d_details; int flip; int left, todo; - urb_t *this_urb; + struct urb *this_urb; int err; p_priv = (struct keyspan_port_private *)(port->private); @@ -853,7 +853,7 @@ struct usb_serial *serial = port->serial; const keyspan_device_details *d_details; int i, already_active, err; - urb_t *urb; + struct urb *urb; s_priv = (struct keyspan_serial_private *)(serial->private); p_priv = (struct keyspan_port_private *)(port->private); @@ -890,7 +890,7 @@ return (0); } -static inline void stop_urb(urb_t *urb) +static inline void stop_urb(struct urb *urb) { if (urb && urb->status == -EINPROGRESS) { urb->transfer_flags &= ~USB_ASYNC_UNLINK; @@ -1041,11 +1041,11 @@ } /* Helper functions used by keyspan_setup_urbs */ -static urb_t *keyspan_setup_urb(struct usb_serial *serial, int endpoint, - int dir, void *ctx, char *buf, int len, - void (*callback)(urb_t *)) +static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, + int dir, void *ctx, char *buf, int len, + void (*callback)(struct urb *)) { - urb_t *urb; + struct urb *urb; if (endpoint == -1) return NULL; /* endpoint not needed */ @@ -1066,12 +1066,12 @@ } static struct callbacks { - void (*instat_callback)(urb_t *); - void (*glocont_callback)(urb_t *); - void (*indat_callback)(urb_t *); - void (*outdat_callback)(urb_t *); - void (*inack_callback)(urb_t *); - void (*outcont_callback)(urb_t *); + void (*instat_callback)(struct urb *); + void (*glocont_callback)(struct urb *); + void (*indat_callback)(struct urb *); + void (*outdat_callback)(struct urb *); + void (*inack_callback)(struct urb *); + void (*outcont_callback)(struct urb *); } keyspan_callbacks[] = { { /* msg_usa26 callbacks */ @@ -1295,7 +1295,7 @@ struct keyspan_port_private *p_priv; const keyspan_device_details *d_details; int outcont_urb; - urb_t *this_urb; + struct urb *this_urb; int err; dbg ("%s reset=%d\n", __FUNCTION__, reset_port); @@ -1430,7 +1430,7 @@ struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; const keyspan_device_details *d_details; - urb_t *this_urb; + struct urb *this_urb; int err; s_priv = (struct keyspan_serial_private *)(serial->private); @@ -1516,7 +1516,7 @@ struct keyspan_port_private *p_priv; const keyspan_device_details *d_details; int glocont_urb; - urb_t *this_urb; + struct urb *this_urb; int err; int device_port; diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/storage/transport.c Mon Jan 21 12:28:39 2002 @@ -369,7 +369,7 @@ /* This is the completion handler which will wake us up when an URB * completes. */ -static void usb_stor_blocking_completion(urb_t *urb) +static void usb_stor_blocking_completion(struct urb *urb) { struct completion *urb_done_ptr = (struct completion *)urb->context; diff -Nru a/drivers/usb/stv680.c b/drivers/usb/stv680.c --- a/drivers/usb/stv680.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/stv680.c Mon Jan 21 12:28:39 2002 @@ -766,7 +766,7 @@ static int stv680_start_stream (struct usb_stv *stv680) { - urb_t *urb; + struct urb *urb; int err = 0, i; stv680->streaming = 1; diff -Nru a/drivers/usb/stv680.h b/drivers/usb/stv680.h --- a/drivers/usb/stv680.h Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/stv680.h Mon Jan 21 12:28:39 2002 @@ -118,7 +118,7 @@ int removed; /* device disconnected */ int streaming; /* Are we streaming video? */ char *fbuf; /* Videodev buffer area */ - urb_t *urb[STV680_NUMSBUF]; /* # of queued bulk transfers */ + struct urb *urb[STV680_NUMSBUF]; /* # of queued bulk transfers */ int curframe; /* Current receiving frame */ struct stv680_frame frame[STV680_NUMFRAMES]; /* # frames supported by v4l part */ int readcount; diff -Nru a/drivers/usb/uhci.c b/drivers/usb/uhci.c --- a/drivers/usb/uhci.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/uhci.c Mon Jan 21 12:28:40 2002 @@ -520,7 +520,8 @@ lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list); - uhci_fixup_toggle(urb, uhci_toggle(lltd->info) ^ 1); + usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), + uhci_fixup_toggle(urb, uhci_toggle(lltd->info) ^ 1)); /* All qh's in the queue need to link to the next queue */ urbp->qh->link = eurbp->qh->link; @@ -556,6 +557,7 @@ /* Fix up the toggle for the next URB's */ if (!urbp->queued) + /* We set the toggle when we unlink */ toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); else { /* If we're in the middle of the queue, grab the toggle */ @@ -1683,8 +1685,8 @@ /* Control and Isochronous ignore the toggle, so this */ /* is safe for all types */ - if (!(td->status & TD_CTRL_ACTIVE) && - (uhci_actual_length(td->status) < uhci_expected_length(td->info) || + if ((!(td->status & TD_CTRL_ACTIVE) && + (uhci_actual_length(td->status) < uhci_expected_length(td->info)) || tmp == head)) { usb_settoggle(urb->dev, uhci_endpoint(td->info), uhci_packetout(td->info), diff -Nru a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c --- a/drivers/usb/usb-ohci.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/usb-ohci.c Mon Jan 21 12:28:39 2002 @@ -173,7 +173,7 @@ kfree (urb_priv); } -static void urb_rm_priv_locked (urb_t * urb) +static void urb_rm_priv_locked (struct urb * urb) { urb_priv_t * urb_priv = urb->hcpriv; @@ -207,7 +207,7 @@ } } -static void urb_rm_priv (urb_t * urb) +static void urb_rm_priv (struct urb * urb) { unsigned long flags; @@ -224,7 +224,7 @@ /* debug| print the main components of an URB * small: 0) header + data packets 1) just header */ -static void urb_print (urb_t * urb, char * str, int small) +static void urb_print (struct urb * urb, char * str, int small) { unsigned int pipe= urb->pipe; @@ -453,10 +453,10 @@ /* return a request to the completion handler */ -static int sohci_return_urb (struct ohci *hc, urb_t * urb) +static int sohci_return_urb (struct ohci *hc, struct urb * urb) { urb_priv_t * urb_priv = urb->hcpriv; - urb_t * urbt; + struct urb * urbt; unsigned long flags; int i; @@ -532,7 +532,7 @@ /* get a transfer request */ -static int sohci_submit_urb (urb_t * urb) +static int sohci_submit_urb (struct urb * urb) { ohci_t * ohci; ed_t * ed; @@ -716,7 +716,7 @@ /* deactivate all TDs and remove the private part of the URB */ /* interrupt callers must use async unlink mode */ -static int sohci_unlink_urb (urb_t * urb) +static int sohci_unlink_urb (struct urb * urb) { unsigned long flags; ohci_t * ohci; @@ -1295,7 +1295,7 @@ static void td_fill (ohci_t * ohci, unsigned int info, dma_addr_t data, int len, - urb_t * urb, int index) + struct urb * urb, int index) { volatile td_t * td, * td_pt; urb_priv_t * urb_priv = urb->hcpriv; @@ -1343,7 +1343,7 @@ /* prepare all TDs of a transfer */ -static void td_submit_urb (urb_t * urb) +static void td_submit_urb (struct urb * urb) { urb_priv_t * urb_priv = urb->hcpriv; ohci_t * ohci = (ohci_t *) urb->dev->bus->hcpriv; @@ -1452,7 +1452,7 @@ { __u32 tdINFO, tdBE, tdCBP; __u16 tdPSW; - urb_t * urb = td->urb; + struct urb * urb = td->urb; urb_priv_t * urb_priv = urb->hcpriv; int dlen = 0; int cc = 0; @@ -1493,7 +1493,7 @@ /* handle an urb that is being unlinked */ -static void dl_del_urb (urb_t * urb) +static void dl_del_urb (struct urb * urb) { wait_queue_head_t * wait_head = ((urb_priv_t *)(urb->hcpriv))->wait; @@ -1582,7 +1582,7 @@ td_p = &ed->hwHeadP; for (td = tdHeadP; td != tdTailP; td = td_next) { - urb_t * urb = td->urb; + struct urb * urb = td->urb; urb_priv_t * urb_priv = td->urb->hcpriv; td_next = dma_to_td (ohci, le32_to_cpup (&td->hwNextTD) & 0xfffffff0); @@ -1670,7 +1670,7 @@ td_t * td_list_next = NULL; ed_t * ed; int cc = 0; - urb_t * urb; + struct urb * urb; urb_priv_t * urb_priv; __u32 tdINFO, edHeadP, edTailP; @@ -1846,7 +1846,7 @@ { int len; - urb_t * urb = (urb_t *) ptr; + struct urb * urb = (struct urb *) ptr; ohci_t * ohci = urb->dev->bus->hcpriv; if (ohci->disabled) @@ -1875,7 +1875,7 @@ /* Root Hub INTs are polled by this timer */ -static int rh_init_int_timer (urb_t * urb) +static int rh_init_int_timer (struct urb * urb) { ohci_t * ohci = urb->dev->bus->hcpriv; @@ -1900,7 +1900,7 @@ /* request to virtual root hub */ -static int rh_submit_urb (urb_t * urb) +static int rh_submit_urb (struct urb * urb) { struct usb_device * usb_dev = urb->dev; ohci_t * ohci = usb_dev->bus->hcpriv; @@ -2106,7 +2106,7 @@ /*-------------------------------------------------------------------------*/ -static int rh_unlink_urb (urb_t * urb) +static int rh_unlink_urb (struct urb * urb) { ohci_t * ohci = urb->dev->bus->hcpriv; diff -Nru a/drivers/usb/usb-ohci.h b/drivers/usb/usb-ohci.h --- a/drivers/usb/usb-ohci.h Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/usb-ohci.h Mon Jan 21 12:28:39 2002 @@ -111,7 +111,7 @@ __u8 index; struct ed * ed; struct td * next_dl_td; - urb_t * urb; + struct urb * urb; dma_addr_t td_dma; dma_addr_t data_dma; @@ -430,12 +430,12 @@ static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load, int mem_flags); static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed); /* td */ -static void td_fill(ohci_t * ohci, unsigned int info, dma_addr_t data, int len, urb_t * urb, int index); -static void td_submit_urb(urb_t * urb); +static void td_fill(ohci_t * ohci, unsigned int info, dma_addr_t data, int len, struct urb * urb, int index); +static void td_submit_urb(struct urb * urb); /* root hub */ -static int rh_submit_urb(urb_t * urb); -static int rh_unlink_urb(urb_t * urb); -static int rh_init_int_timer(urb_t * urb); +static int rh_submit_urb(struct urb * urb); +static int rh_unlink_urb(struct urb * urb); +static int rh_init_int_timer(struct urb * urb); /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c --- a/drivers/usb/usb-uhci.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/usb-uhci.c Mon Jan 21 12:28:39 2002 @@ -113,12 +113,12 @@ // Suppress HC interrupt error messages for 5s #define ERROR_SUPPRESSION_TIME (HZ*5) -_static int rh_submit_urb (urb_t *urb); -_static int rh_unlink_urb (urb_t *urb); +_static int rh_submit_urb (struct urb *urb); +_static int rh_unlink_urb (struct urb *urb); _static int delete_qh (uhci_t *s, uhci_desc_t *qh); -_static int process_transfer (uhci_t *s, urb_t *urb, int mode); -_static int process_interrupt (uhci_t *s, urb_t *urb); -_static int process_iso (uhci_t *s, urb_t *urb, int force); +_static int process_transfer (uhci_t *s, struct urb *urb, int mode); +_static int process_interrupt (uhci_t *s, struct urb *urb); +_static int process_iso (uhci_t *s, struct urb *urb, int force); // How much URBs with ->next are walked #define MAX_NEXT_COUNT 2048 @@ -164,7 +164,7 @@ } /*-------------------------------------------------------------------*/ #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH -_static void enable_desc_loop(uhci_t *s, urb_t *urb) +_static void enable_desc_loop(uhci_t *s, struct urb *urb) { int flags; @@ -179,7 +179,7 @@ spin_unlock_irqrestore (&s->qh_lock, flags); } /*-------------------------------------------------------------------*/ -_static void disable_desc_loop(uhci_t *s, urb_t *urb) +_static void disable_desc_loop(uhci_t *s, struct urb *urb) { int flags; @@ -200,7 +200,7 @@ } #endif /*-------------------------------------------------------------------*/ -_static void queue_urb_unlocked (uhci_t *s, urb_t *urb) +_static void queue_urb_unlocked (uhci_t *s, struct urb *urb) { struct list_head *p=&urb->urb_list; #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH @@ -220,7 +220,7 @@ uhci_switch_timer_int(s); } /*-------------------------------------------------------------------*/ -_static void queue_urb (uhci_t *s, urb_t *urb) +_static void queue_urb (uhci_t *s, struct urb *urb) { unsigned long flags=0; @@ -229,7 +229,7 @@ spin_unlock_irqrestore (&s->urb_list_lock, flags); } /*-------------------------------------------------------------------*/ -_static void dequeue_urb (uhci_t *s, urb_t *urb) +_static void dequeue_urb (uhci_t *s, struct urb *urb) { #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH int type; @@ -694,7 +694,7 @@ // LOW LEVEL STUFF // assembles QHs und TDs for control, bulk and iso /*-------------------------------------------------------------------*/ -_static int uhci_submit_control_urb (urb_t *urb) +_static int uhci_submit_control_urb (struct urb *urb) { uhci_desc_t *qh, *td; uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; @@ -811,7 +811,7 @@ // For queued bulk transfers, two additional QH helpers are allocated (nqh, bqh) // Due to the linking with other bulk urbs, it has to be locked with urb_list_lock! -_static int uhci_submit_bulk_urb (urb_t *urb, urb_t *bulk_urb) +_static int uhci_submit_bulk_urb (struct urb *urb, struct urb *bulk_urb) { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; urb_priv_t *urb_priv = urb->hcpriv, *upriv, *bpriv=NULL; @@ -973,7 +973,7 @@ looks a bit complicated because of all the bulk queueing goodies */ -_static void uhci_clean_transfer (uhci_t *s, urb_t *urb, uhci_desc_t *qh, int mode) +_static void uhci_clean_transfer (uhci_t *s, struct urb *urb, uhci_desc_t *qh, int mode) { uhci_desc_t *bqh, *nqh, *prevqh, *prevtd; int now; @@ -1027,7 +1027,7 @@ urb, priv->prev_queued_urb, priv->next_queued_urb, qh, bqh, priv->next_qh); if (mode != CLEAN_TRANSFER_DELETION_MARK) { // no work for cleanup at unlink-completion - urb_t *nurb; + struct urb *nurb; unsigned long flags; nurb = priv->next_queued_urb; @@ -1065,7 +1065,7 @@ } /*-------------------------------------------------------------------*/ // Release bandwidth for Interrupt or Isoc. transfers -_static void uhci_release_bandwidth(urb_t *urb) +_static void uhci_release_bandwidth(struct urb *urb) { if (urb->bandwidth) { switch (usb_pipetype(urb->pipe)) { @@ -1081,7 +1081,7 @@ } } -_static void uhci_urb_dma_sync(uhci_t *s, urb_t *urb, urb_priv_t *urb_priv) +_static void uhci_urb_dma_sync(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv) { if (urb_priv->setup_packet_dma) pci_dma_sync_single(s->uhci_pci, urb_priv->setup_packet_dma, @@ -1095,7 +1095,7 @@ PCI_DMA_TODEVICE); } -_static void uhci_urb_dma_unmap(uhci_t *s, urb_t *urb, urb_priv_t *urb_priv) +_static void uhci_urb_dma_unmap(uhci_t *s, struct urb *urb, urb_priv_t *urb_priv) { if (urb_priv->setup_packet_dma) { pci_unmap_single(s->uhci_pci, urb_priv->setup_packet_dma, @@ -1116,7 +1116,7 @@ mode: UNLINK_ASYNC_STORE_URB: unlink and move URB into unlinked list UNLINK_ASYNC_DONT_STORE: unlink, don't move URB into unlinked list */ -_static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb, int mode) +_static int uhci_unlink_urb_async (uhci_t *s, struct urb *urb, int mode) { uhci_desc_t *qh; urb_priv_t *urb_priv; @@ -1161,7 +1161,7 @@ } /*-------------------------------------------------------------------*/ // kills an urb by unlinking descriptors and waiting for at least one frame -_static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb) +_static int uhci_unlink_urb_sync (uhci_t *s, struct urb *urb) { uhci_desc_t *qh; urb_priv_t *urb_priv; @@ -1224,7 +1224,7 @@ _static void uhci_cleanup_unlink(uhci_t *s, int force) { struct list_head *q; - urb_t *urb; + struct urb *urb; struct usb_device *dev; int now, type; urb_priv_t *urb_priv; @@ -1234,7 +1234,7 @@ while (q != &s->urb_unlinked) { - urb = list_entry (q, urb_t, urb_list); + urb = list_entry (q, struct urb, urb_list); urb_priv = (urb_priv_t*)urb->hcpriv; q = urb->urb_list.next; @@ -1303,7 +1303,7 @@ } /*-------------------------------------------------------------------*/ -_static int uhci_unlink_urb (urb_t *urb) +_static int uhci_unlink_urb (struct urb *urb) { uhci_t *s; unsigned long flags=0; @@ -1336,9 +1336,9 @@ // In case of ASAP iso transfer, search the URB-list for already queued URBs // for this EP and calculate the earliest start frame for the new // URB (easy seamless URB continuation!) -_static int find_iso_limits (urb_t *urb, unsigned int *start, unsigned int *end) +_static int find_iso_limits (struct urb *urb, unsigned int *start, unsigned int *end) { - urb_t *u, *last_urb = NULL; + struct urb *u, *last_urb = NULL; uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; struct list_head *p; int ret=-1; @@ -1348,7 +1348,7 @@ p=s->urb_list.prev; for (; p != &s->urb_list; p = p->prev) { - u = list_entry (p, urb_t, urb_list); + u = list_entry (p, struct urb, urb_list); // look for pending URBs with identical pipe handle // works only because iso doesn't toggle the data bit! if ((urb->pipe == u->pipe) && (urb->dev == u->dev) && (u->status == -EINPROGRESS)) { @@ -1370,7 +1370,7 @@ /*-------------------------------------------------------------------*/ // adjust start_frame according to scheduling constraints (ASAP etc) -_static int iso_find_start (urb_t *urb) +_static int iso_find_start (struct urb *urb) { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; unsigned int now; @@ -1428,7 +1428,7 @@ // ASAP-flag set implicitely // if period==0, the transfer is only done once -_static int uhci_submit_int_urb (urb_t *urb) +_static int uhci_submit_int_urb (struct urb *urb) { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; urb_priv_t *urb_priv = urb->hcpriv; @@ -1488,7 +1488,7 @@ return 0; } /*-------------------------------------------------------------------*/ -_static int uhci_submit_iso_urb (urb_t *urb) +_static int uhci_submit_iso_urb (struct urb *urb) { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; urb_priv_t *urb_priv = urb->hcpriv; @@ -1581,10 +1581,10 @@ /*-------------------------------------------------------------------*/ // returns: 0 (no transfer queued), urb* (this urb already queued) -_static urb_t* search_dev_ep (uhci_t *s, urb_t *urb) +_static struct urb* search_dev_ep (uhci_t *s, struct urb *urb) { struct list_head *p; - urb_t *tmp; + struct urb *tmp; unsigned int mask = usb_pipecontrol(urb->pipe) ? (~USB_DIR_IN) : (~0); dbg("search_dev_ep:"); @@ -1592,7 +1592,7 @@ p=s->urb_list.next; for (; p != &s->urb_list; p = p->next) { - tmp = list_entry (p, urb_t, urb_list); + tmp = list_entry (p, struct urb, urb_list); dbg("urb: %p", tmp); // we can accept this urb if it is not queued at this time // or if non-iso transfer requests should be scheduled for the same device and pipe @@ -1605,13 +1605,13 @@ return 0; } /*-------------------------------------------------------------------*/ -_static int uhci_submit_urb (urb_t *urb) +_static int uhci_submit_urb (struct urb *urb) { uhci_t *s; urb_priv_t *urb_priv; int ret = 0, type; unsigned long flags; - urb_t *queued_urb=NULL; + struct urb *queued_urb=NULL; int bustime; if (!urb->dev || !urb->dev->bus) @@ -1765,7 +1765,7 @@ _static void uhci_check_timeouts(uhci_t *s) { struct list_head *p,*p2; - urb_t *urb; + struct urb *urb; int type; p = s->urb_list.prev; @@ -1775,7 +1775,7 @@ p2 = p; p = p->prev; - urb = list_entry (p2, urb_t, urb_list); + urb = list_entry (p2, struct urb, urb_list); type = usb_pipetype (urb->pipe); hcpriv = (urb_priv_t*)urb->hcpriv; @@ -1875,7 +1875,7 @@ /*-------------------------------------------------------------------------*/ /* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */ -_static int rh_send_irq (urb_t *urb) +_static int rh_send_irq (struct urb *urb) { int len = 1; int i; @@ -1902,12 +1902,12 @@ /*-------------------------------------------------------------------------*/ /* Virtual Root Hub INTs are polled by this timer every "intervall" ms */ -_static int rh_init_int_timer (urb_t *urb); +_static int rh_init_int_timer (struct urb *urb); _static void rh_int_timer_do (unsigned long ptr) { int len; - urb_t *urb = (urb_t*) ptr; + struct urb *urb = (struct urb *) ptr; uhci_t *uhci = urb->dev->bus->hcpriv; if (uhci->rh.send) { @@ -1924,7 +1924,7 @@ /*-------------------------------------------------------------------------*/ /* Root Hub INTs are polled by this timer, polling interval 20ms */ -_static int rh_init_int_timer (urb_t *urb) +_static int rh_init_int_timer (struct urb *urb) { uhci_t *uhci = urb->dev->bus->hcpriv; @@ -1958,7 +1958,7 @@ *************************/ -_static int rh_submit_urb (urb_t *urb) +_static int rh_submit_urb (struct urb *urb) { struct usb_device *usb_dev = urb->dev; uhci_t *uhci = usb_dev->bus->hcpriv; @@ -2159,7 +2159,7 @@ } /*-------------------------------------------------------------------------*/ -_static int rh_unlink_urb (urb_t *urb) +_static int rh_unlink_urb (struct urb *urb) { uhci_t *uhci = urb->dev->bus->hcpriv; @@ -2217,14 +2217,14 @@ unsigned long flags; struct list_head *p; struct list_head *p2; - urb_t *urb; + struct urb *urb; spin_lock_irqsave (&s->urb_list_lock, flags); p = s->urb_list.prev; while (p != &s->urb_list) { p2 = p; p = p->prev ; - urb = list_entry (p2, urb_t, urb_list); + urb = list_entry (p2, struct urb, urb_list); dbg("urb: %p, dev %p, %p", urb, usb_dev,urb->dev); //urb->transfer_flags |=USB_ASYNC_UNLINK; @@ -2274,7 +2274,7 @@ uhci_unlink_urb }; -_static void correct_data_toggles(urb_t *urb) +_static void correct_data_toggles(struct urb *urb) { usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe), !usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe))); @@ -2304,7 +2304,7 @@ * PROCESS_TRANSFER_DONT_UNLINK: QHs already unlinked (for async unlink_urb) */ -_static int process_transfer (uhci_t *s, urb_t *urb, int mode) +_static int process_transfer (uhci_t *s, struct urb *urb, int mode) { int ret = 0; urb_priv_t *urb_priv = urb->hcpriv; @@ -2392,7 +2392,7 @@ if (usb_pipetype (urb->pipe) == PIPE_BULK ) { /* toggle correction for short bulk transfers (nonqueued/queued) */ urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; - urb_t *next_queued_urb=priv->next_queued_urb; + struct urb *next_queued_urb=priv->next_queued_urb; if (next_queued_urb) { urb_priv_t *next_priv=(urb_priv_t*)next_queued_urb->hcpriv; @@ -2423,7 +2423,7 @@ return ret; } -_static int process_interrupt (uhci_t *s, urb_t *urb) +_static int process_interrupt (uhci_t *s, struct urb *urb) { int i, ret = -EINPROGRESS; urb_priv_t *urb_priv = urb->hcpriv; @@ -2520,7 +2520,7 @@ // mode: PROCESS_ISO_REGULAR: processing only for done TDs, unlink TDs // mode: PROCESS_ISO_FORCE: force processing, don't unlink TDs (already unlinked) -_static int process_iso (uhci_t *s, urb_t *urb, int mode) +_static int process_iso (uhci_t *s, struct urb *urb, int mode) { int i; int ret = 0; @@ -2589,9 +2589,9 @@ _static int process_urb (uhci_t *s, struct list_head *p) { int ret = 0; - urb_t *urb; + struct urb *urb; - urb=list_entry (p, urb_t, urb_list); + urb=list_entry (p, struct urb, urb_list); //dbg("process_urb: found queued urb: %p", urb); switch (usb_pipetype (urb->pipe)) { @@ -2640,7 +2640,7 @@ #endif if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) { // process_interrupt does completion on its own - urb_t *next_urb = urb->next; + struct urb *next_urb = urb->next; int is_ring = 0; int contains_killed = 0; int loop_count=0; diff -Nru a/drivers/usb/usb-uhci.h b/drivers/usb/usb-uhci.h --- a/drivers/usb/usb-uhci.h Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/usb-uhci.h Mon Jan 21 12:28:40 2002 @@ -158,8 +158,8 @@ dma_addr_t setup_packet_dma; dma_addr_t transfer_buffer_dma; unsigned long started; - urb_t *next_queued_urb; // next queued urb for this EP - urb_t *prev_queued_urb; + struct urb *next_queued_urb; // next queued urb for this EP + struct urb *prev_queued_urb; uhci_desc_t *bottom_qh; uhci_desc_t *next_qh; // next helper QH char use_loop; diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c --- a/drivers/usb/usb.c Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/usb.c Mon Jan 21 12:28:40 2002 @@ -1084,12 +1084,13 @@ * * The driver should call usb_free_urb() when it is finished with the urb. */ -urb_t *usb_alloc_urb(int iso_packets) +struct urb *usb_alloc_urb(int iso_packets) { - urb_t *urb; + struct urb *urb; - urb = (urb_t *)kmalloc(sizeof(urb_t) + iso_packets * sizeof(iso_packet_descriptor_t), - in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + urb = (struct urb *)kmalloc(sizeof(struct urb) + + iso_packets * sizeof(struct usb_iso_packet_descriptor), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); if (!urb) { err("alloc_urb: kmalloc failed"); return NULL; @@ -1110,7 +1111,7 @@ * cleaned up with a call to usb_free_urb() when the driver is finished * with it. */ -void usb_free_urb(urb_t* urb) +void usb_free_urb(struct urb *urb) { if (urb) kfree(urb); @@ -1171,7 +1172,7 @@ * the periodic request, and bandwidth reservation is being done for * this controller, submitting such a periodic request will fail. */ -int usb_submit_urb(urb_t *urb) +int usb_submit_urb(struct urb *urb) { if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) return urb->dev->bus->op->submit_urb(urb); @@ -1205,7 +1206,7 @@ * and the completion function will see status -ECONNRESET. Failure is * indicated by any other return value. */ -int usb_unlink_urb(urb_t *urb) +int usb_unlink_urb(struct urb *urb) { if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) return urb->dev->bus->op->unlink_urb(urb); @@ -1221,7 +1222,7 @@ int done; }; -static void usb_api_blocking_completion(urb_t *urb) +static void usb_api_blocking_completion(struct urb *urb) { struct usb_api_data *awd = (struct usb_api_data *)urb->context; @@ -1231,7 +1232,7 @@ } // Starts urb and waits for completion or timeout -static int usb_start_wait_urb(urb_t *urb, int timeout, int* actual_length) +static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) { DECLARE_WAITQUEUE(wait, current); struct usb_api_data awd; @@ -1289,7 +1290,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, struct usb_ctrlrequest *cmd, void *data, int len, int timeout) { - urb_t *urb; + struct urb *urb; int retv; int length; @@ -1376,7 +1377,7 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout) { - urb_t *urb; + struct urb *urb; if (len < 0) return -EINVAL; diff -Nru a/drivers/usb/usbvideo.c b/drivers/usb/usbvideo.c --- a/drivers/usb/usbvideo.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/usbvideo.c Mon Jan 21 12:28:39 2002 @@ -1776,7 +1776,7 @@ /* * Make all of the blocks of data contiguous */ -static int usbvideo_CompressIsochronous(uvd_t *uvd, urb_t *urb) +static int usbvideo_CompressIsochronous(uvd_t *uvd, struct urb *urb) { char *cdata; int i, totlen = 0; @@ -1891,7 +1891,7 @@ /* We double buffer the Iso lists */ for (i=0; i < USBVIDEO_NUMSBUF; i++) { int j, k; - urb_t *urb = uvd->sbuf[i].urb; + struct urb *urb = uvd->sbuf[i].urb; urb->dev = dev; urb->context = uvd; urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); diff -Nru a/drivers/usb/usbvideo.h b/drivers/usb/usbvideo.h --- a/drivers/usb/usbvideo.h Mon Jan 21 12:28:40 2002 +++ b/drivers/usb/usbvideo.h Mon Jan 21 12:28:40 2002 @@ -165,7 +165,7 @@ /* This structure represents one Isoc request - URB and buffer */ typedef struct { char *data; - urb_t *urb; + struct urb *urb; } usbvideo_sbuf_t; typedef struct { diff -Nru a/drivers/usb/vicam.c b/drivers/usb/vicam.c --- a/drivers/usb/vicam.c Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/vicam.c Mon Jan 21 12:28:39 2002 @@ -468,29 +468,23 @@ int err = 0; dbg("vicam_v4l_open"); - - MOD_INC_USE_COUNT; + down(&vicam->sem); - if (vicam->open_count) /* Maybe not needed? */ - err = -EBUSY; + vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES); + if (!vicam->fbuf) + err=-ENOMEM; else { - vicam->fbuf = rvmalloc(vicam->maxframesize * VICAM_NUMFRAMES); - if (!vicam->fbuf) - err=-ENOMEM; - else { - vicam->open_count = 1; - } + vicam->open_count = 1; + } #ifdef BLINKING - vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0); - info ("led on"); - vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0); + vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0); + info ("led on"); + vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0); #endif - } up(&vicam->sem); - if (err) - MOD_DEC_USE_COUNT; + return err; } @@ -515,7 +509,6 @@ up(&vicam->sem); /* Why does se401.c have a usbdevice check here? */ /* If device is unplugged while open, I guess we only may unregister now */ - MOD_DEC_USE_COUNT; } static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock) @@ -717,6 +710,7 @@ /* FIXME - vicam_template - important */ static struct video_device vicam_template = { + owner: THIS_MODULE, name: "vicam USB camera", type: VID_TYPE_CAPTURE, hardware: VID_HARDWARE_SE401, /* need to ask for own id */ @@ -938,6 +932,7 @@ /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver vicam_driver = { + owner: THIS_MODULE, name: "vicam", probe: vicam_probe, disconnect: vicam_disconnect, @@ -984,3 +979,4 @@ module_init(usb_vicam_init); module_exit(usb_vicam_exit); + diff -Nru a/drivers/usb/vicam.h b/drivers/usb/vicam.h --- a/drivers/usb/vicam.h Mon Jan 21 12:28:39 2002 +++ b/drivers/usb/vicam.h Mon Jan 21 12:28:39 2002 @@ -68,7 +68,7 @@ /* v4l stuff */ char *camera_name; char *fbuf; - urb_t *urb[VICAM_NUMSBUF]; + struct urb *urb[VICAM_NUMSBUF]; int sizes; int *width; int *height; diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c --- a/drivers/video/riva/fbdev.c Mon Jan 21 12:28:39 2002 +++ b/drivers/video/riva/fbdev.c Mon Jan 21 12:28:39 2002 @@ -1811,7 +1811,7 @@ info = &rinfo->info; strcpy(info->modename, rinfo->drvr_name); - info->node = -1; + info->node = NODEV; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &riva_fb_ops; diff -Nru a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c --- a/drivers/video/vga16fb.c Mon Jan 21 12:28:39 2002 +++ b/drivers/video/vga16fb.c Mon Jan 21 12:28:39 2002 @@ -926,7 +926,7 @@ /* name should not depend on EGA/VGA */ strcpy(vga16fb.fb_info.modename, "VGA16 VGA"); vga16fb.fb_info.changevar = NULL; - vga16fb.fb_info.node = -1; + vga16fb.fb_info.node = NODEV; vga16fb.fb_info.fbops = &vga16fb_ops; vga16fb.fb_info.disp=&disp; vga16fb.fb_info.switch_con=&vga16fb_switch; diff -Nru a/include/linux/acpi.h b/include/linux/acpi.h --- a/include/linux/acpi.h Mon Jan 21 12:28:40 2002 +++ b/include/linux/acpi.h Mon Jan 21 12:28:40 2002 @@ -28,6 +28,9 @@ #include #endif /* __KERNEL__ */ +#define _LINUX +#include "../../drivers/acpi/include/acpi.h" + /* * Device states */ diff -Nru a/include/linux/dnotify.h b/include/linux/dnotify.h --- a/include/linux/dnotify.h Mon Jan 21 12:28:40 2002 +++ b/include/linux/dnotify.h Mon Jan 21 12:28:40 2002 @@ -4,6 +4,8 @@ * Copyright 2000 (C) Stephen Rothwell */ +#include // greg k-h hack + struct dnotify_struct { struct dnotify_struct * dn_next; int dn_magic; diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Mon Jan 21 12:28:40 2002 +++ b/include/linux/usb.h Mon Jan 21 12:28:40 2002 @@ -576,13 +576,12 @@ /* ... less overhead for QUEUE_BULK */ #define USB_TIMEOUT_KILLED 0x1000 /* only set by HCD! */ -typedef struct -{ +struct usb_iso_packet_descriptor { unsigned int offset; unsigned int length; /* expected length */ unsigned int actual_length; unsigned int status; -} iso_packet_descriptor_t; +}; struct urb; @@ -741,10 +740,8 @@ int timeout; /* (in) timeout, in jiffies */ void *context; /* (in) context for completion */ usb_complete_t complete; /* (in) completion routine */ - iso_packet_descriptor_t iso_frame_desc[0]; /* (in) ISO ONLY */ + struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY */ }; - -typedef struct urb urb_t; /** * usb_fill_control_urb - initializes a control urb