From 51d3b7814cdccef9188240fe0cbd8d97ff2c7470 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Jun 1999 23:05:57 +0000 Subject: Merge with Linux 2.3.7. WARNING: 2.3.7 is known to eat filesystems for breakfast and little children for lunch, so if you try this on your machine make backups first ... --- drivers/usb/acm.c | 2 +- drivers/usb/audio.c | 2 +- drivers/usb/cpia.c | 2 +- drivers/usb/hub.c | 2 +- drivers/usb/keyboard.c | 2 +- drivers/usb/mouse.c | 2 +- drivers/usb/ohci-hcd.c | 2 +- drivers/usb/ohci.c | 211 +++++++++++++++-------- drivers/usb/uhci-debug.c | 2 +- drivers/usb/uhci.c | 42 +++-- drivers/usb/usb-core.c | 2 +- drivers/usb/usb.h | 4 +- drivers/usb/usb_scsi.c | 402 ++++++++++++++++++++++++++++++++++++------- drivers/usb/usb_scsi_debug.c | 2 +- 14 files changed, 517 insertions(+), 162 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c index d4796e28c..10c837d5a 100644 --- a/drivers/usb/acm.c +++ b/drivers/usb/acm.c @@ -50,7 +50,7 @@ static struct acm_state static_acm_state; spinlock_t usb_acm_lock = SPIN_LOCK_UNLOCKED; -static int acm_irq(int state, void *__buffer, void *dev_id) +static int acm_irq(int state, void *__buffer, int len, void *dev_id) { // unsigned char *data = __buffer; struct acm_state *acm = &static_acm_state; diff --git a/drivers/usb/audio.c b/drivers/usb/audio.c index 45a276772..9743ec89e 100644 --- a/drivers/usb/audio.c +++ b/drivers/usb/audio.c @@ -27,7 +27,7 @@ static struct usb_driver usb_audio_driver = }; -static int usb_audio_irq(int state, void *buffer, void *dev_id) +static int usb_audio_irq(int state, void *buffer, int len, void *dev_id) { struct usb_audio *aud = (struct usb_audio*) dev_id; return 1; diff --git a/drivers/usb/cpia.c b/drivers/usb/cpia.c index 87e1e4254..2402d3425 100644 --- a/drivers/usb/cpia.c +++ b/drivers/usb/cpia.c @@ -451,7 +451,7 @@ printk("copying\n"); } } -static int cpia_isoc_irq(int status, void *__buffer, void *dev_id) +static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id) { struct usb_cpia *cpia = dev_id; struct usb_device *dev = cpia->dev; diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c index 1cd7d7ccb..0a1ec1f01 100644 --- a/drivers/usb/hub.c +++ b/drivers/usb/hub.c @@ -33,7 +33,7 @@ static int khubd_pid = 0; * the low-level driver that it wants to be re-activated, * or zero to say "I'm done". */ -static int hub_irq(int status, void *__buffer, void *dev_id) +static int hub_irq(int status, void *__buffer, int len, void *dev_id) { struct usb_hub *hub = dev_id; unsigned long flags; diff --git a/drivers/usb/keyboard.c b/drivers/usb/keyboard.c index 5d93a5a84..e87519d9f 100644 --- a/drivers/usb/keyboard.c +++ b/drivers/usb/keyboard.c @@ -92,7 +92,7 @@ usb_kbd_repeat(unsigned long dev_id) } static int -usb_kbd_irq(int state, void *buffer, void *dev_id) +usb_kbd_irq(int state, void *buffer, int len, void *dev_id) { struct usb_keyboard *kbd = (struct usb_keyboard*) dev_id; unsigned long *down = (unsigned long*) buffer; diff --git a/drivers/usb/mouse.c b/drivers/usb/mouse.c index f094c0b0d..a79c10a07 100644 --- a/drivers/usb/mouse.c +++ b/drivers/usb/mouse.c @@ -60,7 +60,7 @@ static struct mouse_state static_mouse_state; spinlock_t usb_mouse_lock = SPIN_LOCK_UNLOCKED; -static int mouse_irq(int state, void *__buffer, void *dev_id) +static int mouse_irq(int state, void *__buffer, int len, void *dev_id) { signed char *data = __buffer; /* finding the mouse is easy when there's only one */ diff --git a/drivers/usb/ohci-hcd.c b/drivers/usb/ohci-hcd.c index 820efc5dc..8db61e08e 100644 --- a/drivers/usb/ohci-hcd.c +++ b/drivers/usb/ohci-hcd.c @@ -102,7 +102,7 @@ static int sohci_int_handler(void * ohci_in, unsigned int ep_addr, int ctrl_len, OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);) OHCI_DEBUG( printk(" ret_status: %x\n", status); }) - ret = handler(cc_to_status[status & 0xf], data, dev_id); + ret = handler(cc_to_status[status & 0xf], data, data_len, dev_id); if(ret == 0) return 0; /* 0 .. do not requeue */ if(status > 0) return -1; /* error occured do not requeue ? */ ohci_trans_req(ohci, ep_addr, 0, NULL, data, 8, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id); /* requeue int request */ diff --git a/drivers/usb/ohci.c b/drivers/usb/ohci.c index 4ef570abd..48191e11b 100644 --- a/drivers/usb/ohci.c +++ b/drivers/usb/ohci.c @@ -121,7 +121,7 @@ static struct ohci_td *ohci_add_td_to_ed(struct ohci_td *td, u32 new_dummy; if (ed->tail_td == 0) { - printk("eek! an ED without a dummy_td\n"); + printk(KERN_ERR "eek! an ED without a dummy_td\n"); return td; } @@ -234,8 +234,8 @@ void ohci_add_periodic_ed(struct ohci *ohci, struct ohci_ed *ed, int period) */ int_ed = &root_hub->ed[ms_to_ed_int(period)]; #ifdef OHCI_DEBUG - printk("usb-ohci: Using INT ED queue %d for %dms period\n", - ms_to_ed_int(period), period); + printk(KERN_DEBUG "usb-ohci: Using INT ED queue %d for %dms period\n", + ms_to_ed_int(period), period); #endif spin_lock_irqsave(&ohci_edtd_lock, flags); @@ -264,6 +264,21 @@ inline void ohci_add_isoc_ed(struct ohci *ohci, struct ohci_ed *ed) */ DECLARE_WAIT_QUEUE_HEAD(start_of_frame_wakeup); +static void ohci_wait_sof(struct ohci_regs *regs) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&start_of_frame_wakeup, &wait); + + /* clear the SOF interrupt status and enable it */ + writel(OHCI_INTR_SF, ®s->intrstatus); + writel(OHCI_INTR_SF, ®s->intrenable); + + schedule_timeout(HZ/10); + + remove_wait_queue(&start_of_frame_wakeup, &wait); +} + /* * Guarantee that an ED is safe to be modified by the HCD (us). * @@ -296,21 +311,11 @@ void ohci_wait_for_ed_safe(struct ohci_regs *regs, struct ohci_ed *ed, int ed_ty * at least the next frame. */ if (virt_to_bus(ed) == readl(hw_listcurrent)) { - DECLARE_WAITQUEUE(wait, current); - #ifdef OHCI_DEBUG - printk("Waiting a frame for OHC to finish with ED %p [%x %x %x %x]\n", ed, FIELDS_OF_ED(ed)); + printk(KERN_INFO "Waiting a frame for OHC to finish with ED %p [%x %x %x %x]\n", ed, FIELDS_OF_ED(ed)); #endif + ohci_wait_sof(regs); - add_wait_queue(&start_of_frame_wakeup, &wait); - - /* clear the SOF interrupt status and enable it */ - writel(OHCI_INTR_SF, ®s->intrstatus); - writel(OHCI_INTR_SF, ®s->intrenable); - - schedule_timeout(HZ/10); - - remove_wait_queue(&start_of_frame_wakeup, &wait); } return; /* The ED is now safe */ @@ -334,6 +339,7 @@ void ohci_remove_norm_ed_from_hw(struct ohci *ohci, struct ohci_ed *ed, int ed_t if (ed == NULL || !bus_ed) return; + ed->status |= cpu_to_le32(OHCI_ED_SKIP); switch (ed_type) { case HCD_ED_CONTROL: @@ -343,16 +349,10 @@ void ohci_remove_norm_ed_from_hw(struct ohci *ohci, struct ohci_ed *ed, int ed_t hw_listhead_p = ®s->ed_bulkhead; break; default: - printk("Unknown HCD ED type %d.\n", ed_type); + printk(KERN_ERR "Unknown HCD ED type %d.\n", ed_type); return; } - /* - * Tell the controller to this skip ED and make sure it is not the - * being accessed by the HC as we speak. - */ - ohci_wait_for_ed_safe(regs, ed, ed_type); - bus_cur = readl(hw_listhead_p); if (bus_cur == 0) @@ -364,7 +364,7 @@ void ohci_remove_norm_ed_from_hw(struct ohci *ohci, struct ohci_ed *ed, int ed_t /* if its the head ED, move the head */ if (bus_cur == bus_ed) { - writel(cur->next_ed, hw_listhead_p); + writel(le32_to_cpup(&cur->next_ed), hw_listhead_p); } else if (cur->next_ed != 0) { struct ohci_ed *prev; @@ -373,7 +373,7 @@ void ohci_remove_norm_ed_from_hw(struct ohci *ohci, struct ohci_ed *ed, int ed_t prev = cur; cur = bus_to_virt(le32_to_cpup(&cur->next_ed)); - if (virt_to_bus(cur) == bus_ed) { + if (cur == ed) { /* unlink from the list */ prev->next_ed = cur->next_ed; break; @@ -381,6 +381,11 @@ void ohci_remove_norm_ed_from_hw(struct ohci *ohci, struct ohci_ed *ed, int ed_t } while (cur->next_ed != 0); } + /* + * Make sure this ED is not being accessed by the HC as we speak. + */ + ohci_wait_for_ed_safe(regs, ed, ed_type); + /* clear any links from the ED for safety */ ed->next_ed = 0; @@ -405,6 +410,68 @@ inline void ohci_remove_bulk_ed(struct ohci *ohci, struct ohci_ed *ed) ohci_remove_norm_ed_from_hw(ohci, ed, HCD_ED_BULK); } +/* + * Remove all the EDs which have a given device address from a list. + * Used when the device is unplugged. + * Returns 1 if anything was changed. + */ +static int ohci_remove_device_list(__u32 *headp, int devnum) +{ + struct ohci_ed *ed; + __u32 *prevp = headp; + int removed = 0; + + while (*prevp != 0) { + ed = bus_to_virt(le32_to_cpup(prevp)); + if ((le32_to_cpup(&ed->status) & OHCI_ED_FA) == devnum) { + /* set the controller to skip this one + and remove it from the list */ + ed->status |= cpu_to_le32(OHCI_ED_SKIP); + *prevp = ed->next_ed; + removed = 1; + } else { + prevp = &ed->next_ed; + } + } + wmb(); + + return removed; +} + +/* + * Remove all the EDs for a given device from all lists. + */ +void ohci_remove_device(struct ohci *ohci, int devnum) +{ + unsigned long flags; + __u32 head; + struct ohci_regs *regs = ohci->regs; + struct ohci_device *root_hub=usb_to_ohci(ohci->bus->root_hub); + + spin_lock_irqsave(&ohci_edtd_lock, flags); + + /* Control list */ + head = cpu_to_le32(readl(®s->ed_controlhead)); + if (ohci_remove_device_list(&head, devnum)) + writel(le32_to_cpup(&head), ®s->ed_controlhead); + + /* Bulk list */ + head = cpu_to_le32(readl(®s->ed_bulkhead)); + if (ohci_remove_device_list(&head, devnum)) + writel(le32_to_cpup(&head), ®s->ed_bulkhead); + + /* Interrupt/iso list */ + head = cpu_to_le32(virt_to_bus(&root_hub->ed[ED_INT_32])); + ohci_remove_device_list(&head, devnum); + + /* + * Wait until the start of the next frame to ensure + * that the HC has seen any changes. + */ + ohci_wait_sof(ohci->regs); + + spin_unlock_irqrestore(&ohci_edtd_lock, flags); +} /* * Remove a TD from the given EDs TD list. @@ -494,7 +561,7 @@ static struct ohci_td *ohci_get_free_td(struct ohci_device *dev) } } - printk("usb-ohci: unable to allocate a TD\n"); + printk(KERN_ERR "usb-ohci: unable to allocate a TD\n"); return NULL; } /* ohci_get_free_td() */ @@ -521,7 +588,7 @@ static struct ohci_ed *ohci_get_free_ed(struct ohci_device *dev) } } - printk("usb-ohci: unable to allocate an ED\n"); + printk(KERN_ERR "usb-ohci: unable to allocate an ED\n"); return NULL; } /* ohci_get_free_ed() */ @@ -594,12 +661,12 @@ struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed, struct ohci_td *dummy_td; if (ed_head_td(ed) != ed_tail_td(ed)) - printk("Reusing a non-empty ED %p!\n", ed); + printk(KERN_ERR "Reusing a non-empty ED %p!\n", ed); if (!ed->tail_td) { dummy_td = ohci_get_free_td(dev); if (dummy_td == NULL) { - printk("Error allocating dummy TD for ED %p\n", ed); + printk(KERN_ERR "Error allocating dummy TD for ED %p\n", ed); return NULL; /* no dummy available! */ } make_dumb_td(dummy_td); /* flag it as a dummy */ @@ -607,7 +674,7 @@ struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed, } else { dummy_td = bus_to_virt(ed_tail_td(ed)); if (!td_dummy(*dummy_td)) - printk("ED %p's dummy %p is screwy\n", ed, dummy_td); + printk(KERN_ERR "ED %p's dummy %p is screwy\n", ed, dummy_td); } /* set the head TD to the dummy and clear the Carry & Halted bits */ @@ -650,13 +717,13 @@ static int ohci_request_irq(struct usb_device *usb, unsigned int pipe, /* Get an ED and TD */ interrupt_ed = ohci_get_free_ed(dev); if (!interrupt_ed) { - printk("Out of EDs on device %p in ohci_request_irq\n", dev); + printk(KERN_ERR "Out of EDs on device %p in ohci_request_irq\n", dev); return -1; } td = ohci_get_free_td(dev); if (!td) { - printk("Out of TDs in ohci_request_irq\n"); + printk(KERN_ERR "Out of TDs in ohci_request_irq\n"); ohci_free_ed(interrupt_ed); return -1; } @@ -710,7 +777,7 @@ static DECLARE_WAIT_QUEUE_HEAD(control_wakeup); * * This function is called from the interrupt handler. */ -static int ohci_control_completed(int stats, void *buffer, void *dev_id) +static int ohci_control_completed(int stats, void *buffer, int len, void *dev_id) { /* pass the TDs completion status back to control_msg */ if (dev_id) { @@ -759,14 +826,14 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, printk(KERN_DEBUG "ohci_control_msg %p (ohci_dev: %p) pipe %x, cmd %p, data %p, len %d\n", usb, dev, pipe, cmd, data, len); #endif if (!control_ed) { - printk("usb-ohci: couldn't get ED for dev %p\n", dev); + printk(KERN_ERR "usb-ohci: couldn't get ED for dev %p\n", dev); return -1; } /* get a TD to send this control message with */ setup_td = ohci_get_free_td(dev); if (!setup_td) { - printk("usb-ohci: couldn't get TD for dev %p [cntl setup]\n", dev); + printk(KERN_ERR "usb-ohci: couldn't get TD for dev %p [cntl setup]\n", dev); ohci_free_ed(control_ed); return -1; } @@ -799,7 +866,7 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, /* allocate the next TD */ data_td = ohci_get_free_td(dev); if (!data_td) { - printk("usb-ohci: couldn't get TD for dev %p [cntl data]\n", dev); + printk(KERN_ERR "usb-ohci: couldn't get TD for dev %p [cntl data]\n", dev); ohci_free_td(setup_td); ohci_free_ed(control_ed); return -1; @@ -833,7 +900,7 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, status_td = ohci_get_free_td(dev); /* TODO check for NULL */ if (!status_td) { - printk("usb-ohci: couldn't get TD for dev %p [cntl status]\n", dev); + printk(KERN_ERR "usb-ohci: couldn't get TD for dev %p [cntl status]\n", dev); ohci_free_td(setup_td); ohci_free_td(data_td); ohci_free_ed(control_ed); @@ -918,15 +985,17 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, #ifdef OHCI_DEBUG if (completion_status != 0) { - printk(KERN_ERR "ohci_control_msg: %s on cmd %x %x %x %x %x\n", - cc_names[completion_status & 0xf], cmd->requesttype, - cmd->request, cmd->value, cmd->index, cmd->length); + char *what = (completion_status < 0)? "timed out": + cc_names[completion_status & 0xf]; + printk(KERN_ERR "ohci_control_msg: %s on pipe %x cmd %x %x %x %x %x\n", + what, pipe, cmd->requesttype, cmd->request, + cmd->value, cmd->index, cmd->length); } else if (!usb_pipeout(pipe)) { unsigned char *q = data; int i; - printk(KERN_DEBUG "ctrl msg %x %x %x %x %x returned:", + printk(KERN_DEBUG "ctrl msg %x %x %x %x %x on pipe %x returned:", cmd->requesttype, cmd->request, cmd->value, cmd->index, - cmd->length); + cmd->length, pipe); for (i = 0; i < len; ++i) { if (i % 16 == 0) printk("\n" KERN_DEBUG); @@ -1001,8 +1070,12 @@ static struct usb_device *ohci_usb_allocate(struct usb_device *parent) */ static int ohci_usb_deallocate(struct usb_device *usb_dev) { - kfree(usb_to_ohci(usb_dev)); - kfree(usb_dev); + struct ohci_device *dev = usb_to_ohci(usb_dev); + + ohci_remove_device(dev->ohci, usb_dev->devnum); + + /* kfree(usb_to_ohci(usb_dev)); */ + /* kfree(usb_dev); */ return 0; } @@ -1042,13 +1115,13 @@ static int reset_hc(struct ohci *ohci) while ((readl(&ohci->regs->cmdstatus) & OHCI_CMDSTAT_HCR) != 0) { if (!--timeout) { - printk("usb-ohci: USB HC reset timed out!\n"); + printk(KERN_ERR "usb-ohci: USB HC reset timed out!\n"); return -1; } udelay(1); } - printk(KERN_INFO "usb-ohci: HC %p reset.\n", ohci); + printk(KERN_DEBUG "usb-ohci: HC %p reset.\n", ohci); return 0; } /* reset_hc() */ @@ -1080,7 +1153,8 @@ static int start_hc(struct ohci *ohci) * XXX Should fminterval also be set here? * The spec suggests 0x2edf [11,999]. (FIXME: make this a constant) */ - fminterval |= (0x2edf << 16); + /* fminterval |= (0x2edf << 16); */ + fminterval = (10240 << 16) | 11999; writel(fminterval, &ohci->regs->fminterval); /* Start periodic transfers at 90% of fminterval (fmremaining * counts down; this will put them in the first 10% of the @@ -1122,7 +1196,7 @@ static int start_hc(struct ohci *ohci) /* Turn on power to the root hub ports (thanks Roman!) */ writel( OHCI_ROOT_LPSC, &ohci->regs->roothub.status ); - printk("usb-ohci: host controller operational\n"); + printk(KERN_INFO "usb-ohci: host controller operational\n"); return ret; } /* start_hc() */ @@ -1137,7 +1211,7 @@ static void ohci_reset_port(struct ohci *ohci, unsigned int port) /* Don't allow overflows. */ if (port >= MAX_ROOT_PORTS) { - printk("usb-ohci: bad port #%d in ohci_reset_port\n", port); + printk(KERN_ERR "usb-ohci: bad port #%d in ohci_reset_port\n", port); port = MAX_ROOT_PORTS-1; } @@ -1152,7 +1226,7 @@ static void ohci_reset_port(struct ohci *ohci, unsigned int port) status = readl(&ohci->regs->roothub.portstatus[port]); if (status & PORT_PRS) { /* reset failed, try harder? */ - printk("usb-ohci: port %d reset failed, retrying\n", port); + printk(KERN_ERR "usb-ohci: port %d reset failed, retrying\n", port); writel(PORT_PRS, &ohci->regs->roothub.portstatus[port]); wait_ms(50); } @@ -1340,7 +1414,7 @@ static void ohci_reap_donelist(struct ohci *ohci) int cc = OHCI_TD_CC_GET(le32_to_cpup(&td->info)); if (td_dummy(*td)) - printk("yikes! reaping a dummy TD\n"); + printk(KERN_ERR "yikes! reaping a dummy TD\n"); /* FIXME: munge td->info into a future standard status format */ @@ -1382,7 +1456,7 @@ static void ohci_reap_donelist(struct ohci *ohci) /* Check if TD should be re-queued */ if ((td->completed != NULL) && - (td->completed(cc, td->data, td->dev_id))) { + (td->completed(cc, td->data, -1 /* XXX */, td->dev_id))) { /* Mark the TD as active again: * Set the not accessed condition code * Reset the Error count @@ -1598,14 +1672,14 @@ static struct ohci *alloc_ohci(void* mem_base) /* Get the number of ports on the root hub */ usb->maxchild = readl(&ohci->regs->roothub.a) & 0xff; if (usb->maxchild > MAX_ROOT_PORTS) { - printk("usb-ohci: Limited to %d ports\n", MAX_ROOT_PORTS); + printk(KERN_INFO "usb-ohci: Limited to %d ports\n", MAX_ROOT_PORTS); usb->maxchild = MAX_ROOT_PORTS; } if (usb->maxchild < 1) { - printk("usb-ohci: Less than one root hub port? Impossible!\n"); + printk(KERN_ERR "usb-ohci: Less than one root hub port? Impossible!\n"); usb->maxchild = 1; } - printk("usb-ohci: %d root hub ports found\n", usb->maxchild); + printk(KERN_DEBUG "usb-ohci: %d root hub ports found\n", usb->maxchild); /* * Initialize the ED polling "tree" (for simplicity's sake in @@ -1650,14 +1724,13 @@ static struct ohci *alloc_ohci(void* mem_base) writel(0, &ohci->regs->ed_bulkhead); #ifdef OHCI_DEBUG - printk(KERN_INFO "alloc_ohci(): controller\n"); + printk(KERN_DEBUG "alloc_ohci(): controller\n"); show_ohci_status(ohci); #endif #if 0 printk(KERN_DEBUG "leaving alloc_ohci %p\n", ohci); #endif -printk("alloc_ohci done\n"); return ohci; } /* alloc_ohci() */ @@ -1722,7 +1795,7 @@ static int ohci_control_thread(void * __ohci) * This thread doesn't need any user-level access, * so get rid of all of our resources.. */ - printk(KERN_INFO "ohci-control thread code for 0x%p code at 0x%p\n", __ohci, &ohci_control_thread); + printk(KERN_DEBUG "ohci-control thread code for 0x%p code at 0x%p\n", __ohci, &ohci_control_thread); exit_mm(current); exit_files(current); exit_fs(current); @@ -1735,7 +1808,7 @@ static int ohci_control_thread(void * __ohci) * Damn the torpedoes, full speed ahead */ if (start_hc(ohci) < 0) { - printk("usb-ohci: failed to start the controller\n"); + printk(KERN_ERR "usb-ohci: failed to start the controller\n"); release_ohci(ohci); usb_deregister_bus(ohci->bus); printk(KERN_INFO "leaving ohci_control_thread %p\n", __ohci); @@ -1756,7 +1829,7 @@ static int ohci_control_thread(void * __ohci) writel(OHCI_INTR_RHSC, &ohci->regs->intrenable); #endif - printk(KERN_INFO "ohci-control thread sleeping\n"); + printk(KERN_DEBUG "ohci-control thread sleeping\n"); interruptible_sleep_on(&ohci_configure); #ifdef CONFIG_APM if (apm_resume) { @@ -1796,7 +1869,7 @@ static int ohci_control_thread(void * __ohci) reset_hc(ohci); release_ohci(ohci); usb_deregister_bus(ohci->bus); - printk(KERN_INFO "ohci-control thread for 0x%p exiting\n", __ohci); + printk(KERN_DEBUG "ohci-control thread for 0x%p exiting\n", __ohci); return 0; } /* ohci_control_thread() */ @@ -1891,7 +1964,7 @@ static int found_ohci(int irq, void* mem_base) ohci->irq = irq; #ifdef OHCI_DEBUG - printk(KERN_INFO "usb-ohci: forking ohci-control thread for 0x%p\n", ohci); + printk(KERN_DEBUG "usb-ohci: forking ohci-control thread for 0x%p\n", ohci); #endif /* fork off the handler */ @@ -1903,7 +1976,7 @@ static int found_ohci(int irq, void* mem_base) retval = pid; } else { - printk("usb-ohci: Couldn't allocate interrupt %d\n", irq); + printk(KERN_ERR "usb-ohci: Couldn't allocate interrupt %d\n", irq); } release_ohci(ohci); @@ -1931,7 +2004,7 @@ static int init_ohci(struct pci_dev *dev) /* no interrupt won't work... */ if (dev->irq == 0) { - printk("usb-ohci: no irq assigned? check your BIOS settings.\n"); + printk(KERN_ERR "usb-ohci: no irq assigned? check your BIOS settings.\n"); return -ENODEV; } @@ -1944,14 +2017,14 @@ static int init_ohci(struct pci_dev *dev) mem_base = (unsigned long) ioremap_nocache(mem_base, 4096); if (!mem_base) { - printk("Error mapping OHCI memory\n"); + printk(KERN_ERR "Error mapping OHCI memory\n"); return -EFAULT; } MOD_INC_USE_COUNT; #ifdef OHCI_DEBUG - printk("usb-ohci: Warning! Gobs of debugging output has been enabled.\n"); - printk(" Check your kern.debug logs for the bulk of it.\n"); + printk(KERN_INFO "usb-ohci: Warning! Gobs of debugging output has been enabled.\n"); + printk(KERN_INFO " Check your kern.debug logs for the bulk of it.\n"); #endif if (found_ohci(dev->irq, (void *) mem_base) < 0) { @@ -1978,11 +2051,11 @@ int ohci_init(void) /*u8 type;*/ if (sizeof(struct ohci_device) > 4096) { - printk("usb-ohci: struct ohci_device to large\n"); + printk(KERN_ERR "usb-ohci: struct ohci_device to large\n"); return -ENODEV; } - printk("OHCI USB Driver loading\n"); + printk(KERN_INFO "OHCI USB Driver loading\n"); retval = -ENODEV; for (;;) { @@ -2022,7 +2095,7 @@ void cleanup_module(void){ # ifdef CONFIG_APM apm_unregister_callback(&handle_apm_event); # endif - printk("usb-ohci: module unloaded\n"); + printk(KERN_ERR "usb-ohci: module unloaded\n"); } int init_module(void){ diff --git a/drivers/usb/uhci-debug.c b/drivers/usb/uhci-debug.c index 7c577a58f..32549763e 100644 --- a/drivers/usb/uhci-debug.c +++ b/drivers/usb/uhci-debug.c @@ -131,7 +131,7 @@ void show_queue(struct uhci_qh *qh) #if 0 printk(" link = %p, element = %p\n", qh->link, qh->element); #endif - if(!qh->element) { + if(!(qh->element & ~0xF)) { printk(" td 0 = NULL\n"); return; } diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c index 73aab5fa1..c03ce5adf 100644 --- a/drivers/usb/uhci.c +++ b/drivers/usb/uhci.c @@ -126,7 +126,7 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned tmp = td->first; printk("uhci_td_result() failed with status %x\n", status); - show_status(dev->uhci); + //show_status(dev->uhci); do { show_td(tmp); if ((tmp->link & 1) || (tmp->link & 2)) @@ -422,7 +422,7 @@ static int uhci_remove_irq(struct usb_device *usb_dev, unsigned int pipe, usb_de /* notify removal */ - td->completed(USB_ST_REMOVED, NULL, td->dev_id); + td->completed(USB_ST_REMOVED, NULL, 0, td->dev_id); /* this is DANGEROUS - not sure whether this is right */ @@ -645,7 +645,7 @@ void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc) */ static DECLARE_WAIT_QUEUE_HEAD(control_wakeup); -static int uhci_control_completed(int status, void *buffer, void *dev_id) +static int uhci_control_completed(int status, void *buffer, int len, void *dev_id) { wake_up(&control_wakeup); return 0; /* Don't re-instate */ @@ -692,7 +692,7 @@ static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, stru // show_status(dev->uhci); // show_queues(dev->uhci); - schedule_timeout(HZ/10); + schedule_timeout(HZ*5); // control should be empty here... // show_status(dev->uhci); @@ -736,8 +736,7 @@ static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, stru * information, that's just ridiculously high. Most * control messages have just a few bytes of data. */ -static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, - devrequest *cmd, void *data, int len) +static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, void *cmd, void *data, int len) { struct uhci_device *dev = usb_to_uhci(usb_dev); struct uhci_td *first, *td, *prevtd; @@ -805,17 +804,18 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, } /* - * Build the final TD for control status + * Build the final TD for control status */ destination ^= (0xE1 ^ 0x69); /* OUT -> IN */ destination |= 1 << 19; /* End in Data1 */ - td->link = 1; /* Terminate */ - td->status = status | (1 << 24); /* IOC */ + td->backptr = &prevtd->link; + td->status = (status /* & ~(3 << 27) */) | (1 << 24); /* no limit on final packet */ td->info = destination | (0x7ff << 21); /* 0 bytes of data */ td->buffer = 0; td->first = first; - td->backptr = &prevtd->link; + td->link = 1; /* Terminate */ + /* Start it up.. */ ret = uhci_run_control(dev, first, td); @@ -841,7 +841,7 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, } if (uhci_debug && ret) { - __u8 *p = (__u8 *) cmd; + __u8 *p = cmd; printk("Failed cmd - %02X %02X %02X %02X %02X %02X %02X %02X\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); @@ -860,7 +860,7 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, */ static DECLARE_WAIT_QUEUE_HEAD(bulk_wakeup); -static int uhci_bulk_completed(int status, void *buffer, void *dev_id) +static int uhci_bulk_completed(int status, void *buffer, int len, void *dev_id) { wake_up(&bulk_wakeup); return 0; /* Don't re-instate */ @@ -908,10 +908,11 @@ static int uhci_run_bulk(struct uhci_device *dev, struct uhci_td *first, struct // show_status(dev->uhci); // show_queues(dev->uhci); - schedule_timeout(HZ/10); + schedule_timeout(HZ*5); // show_status(dev->uhci); // show_queues(dev->uhci); + //show_queue(first->qh); remove_wait_queue(&bulk_wakeup, &wait); /* Clean up in case it failed.. */ @@ -1243,6 +1244,7 @@ static void uhci_interrupt_notify(struct uhci *uhci) { struct list_head *head = &uhci->interrupt_list; struct list_head *tmp; + int status; spin_lock(&irqlist_lock); tmp = head->next; @@ -1252,19 +1254,22 @@ static void uhci_interrupt_notify(struct uhci *uhci) next = tmp->next; - if (!(td->status & (1 << 23))) { /* No longer active? */ + if (!((status = td->status) & (1 << 23)) || /* No longer active? */ + ((td->qh->element & ~15) && + !((status = uhci_link_to_td(td->qh->element)->status) & (1 <<23)) && + (status & 0x760000) /* is in error state (Stall, db, babble, timeout, bitstuff) */)) { /* remove from IRQ list */ __list_del(tmp->prev, next); INIT_LIST_HEAD(tmp); - if (td->completed(uhci_map_status((td->status & 0xff)>> 16, 0), - bus_to_virt(td->buffer), td->dev_id)) { + if (td->completed(uhci_map_status(status, 0), bus_to_virt(td->buffer), -1, td->dev_id)) { list_add(&td->irq_list, &uhci->interrupt_list); if (!(td->status & (1 << 25))) { struct uhci_qh *interrupt_qh = td->qh; usb_dotoggle(td->dev, usb_pipeendpoint(td->info)); - td->info |= 1 << 19; /* toggle between data0 and data1 */ + td->info &= ~(1 << 19); /* clear data toggle */ + td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info)) << 19; /* toggle between data0 and data1 */ td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */ /* Remove then readd? Is that necessary */ @@ -1283,7 +1288,7 @@ static void uhci_interrupt_notify(struct uhci *uhci) /* If completed wants to not reactivate, then it's */ /* responsible for free'ing the TD's and QH's */ /* or another function (such as run_control) */ - } + } tmp = next; } spin_unlock(&irqlist_lock); @@ -1563,6 +1568,7 @@ static int uhci_control_thread(void * __uhci) { struct uhci *uhci = (struct uhci *)__uhci; struct uhci_device * root_hub =usb_to_uhci(uhci->bus->root_hub); + lock_kernel(); request_region(uhci->io_addr, 32, "usb-uhci"); diff --git a/drivers/usb/usb-core.c b/drivers/usb/usb-core.c index f9f73a051..082549b6e 100644 --- a/drivers/usb/usb-core.c +++ b/drivers/usb/usb-core.c @@ -53,7 +53,7 @@ int usb_init(void) usb_acm_init(); # endif # ifdef CONFIG_USB_PRINTER - usb_print_init(); + usb_printer_init(); # endif # ifdef CONFIG_USB_CPIA usb_cpia_init(); diff --git a/drivers/usb/usb.h b/drivers/usb/usb.h index 63ebeffb9..a6bf78e4a 100644 --- a/drivers/usb/usb.h +++ b/drivers/usb/usb.h @@ -242,10 +242,12 @@ struct usb_driver { * until we come up with a common meaning. * void *buffer - This is a pointer to the data used in this * USB transfer. + * int length - This is the number of bytes transferred in or out + * of the buffer by this transfer. (-1 = unknown/unsupported) * void *dev_id - This is a user defined pointer set when the IRQ * is requested that is passed back. */ -typedef int (*usb_device_irq)(int, void *, void *); +typedef int (*usb_device_irq)(int, void *, int, void *); struct usb_operations { struct usb_device *(*allocate)(struct usb_device *); diff --git a/drivers/usb/usb_scsi.c b/drivers/usb/usb_scsi.c index 655045bea..1a3e16b25 100644 --- a/drivers/usb/usb_scsi.c +++ b/drivers/usb/usb_scsi.c @@ -74,7 +74,9 @@ struct us_data { __u8 ep_int; /* interrupt . */ __u8 subclass; /* as in overview */ __u8 protocol; /* .............. */ + __u8 attention_done; /* force attention on first command */ int (*pop)(Scsi_Cmnd *); /* protocol specific do cmd */ + int (*pop_reset)(struct us_data *); /* ................. device reset */ GUID(guid); /* unique dev id */ struct Scsi_Host *host; /* our dummy host data */ Scsi_Host_Template *htmplt; /* own host template */ @@ -142,6 +144,9 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length) /* we want to retry if the device reported NAK */ if (result == USB_ST_TIMEOUT) { + if (partial != this_xfer) { + return 0; /* I do not like this */ + } if (!maxtry--) break; this_xfer -= partial; @@ -150,6 +155,11 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length) /* short data - assume end */ result = USB_ST_DATAUNDERRUN; break; + } else if (result == USB_ST_STALL && us->protocol == US_PR_CB) { + if (!maxtry--) + break; + this_xfer -= partial; + buf += partial; } else break; } while ( this_xfer ); @@ -216,27 +226,57 @@ static unsigned int us_transfer_length(Scsi_Cmnd *srb) } -static int pop_CBI_irq(int state, void *buffer, void *dev_id) +static int pop_CBI_irq(int state, void *buffer, int len, void *dev_id) { struct us_data *us = (struct us_data *)dev_id; if (state != USB_ST_REMOVED) { us->ip_data = *(__u16 *)buffer; - us->ip_wanted = 0; + US_DEBUGP("Interrupt Status %x\n", us->ip_data); } - wake_up(&us->ip_waitq); + if (us->ip_wanted) + wake_up(&us->ip_waitq); + us->ip_wanted = 0; /* we dont want another interrupt */ return 0; } + +static int pop_CB_reset(struct us_data *us) +{ + unsigned char cmd[12]; + devrequest dr; + int result; + + dr.requesttype = USB_TYPE_CLASS | USB_RT_INTERFACE; + dr.request = US_CBI_ADSC; + dr.value = 0; + dr.index = us->pusb_dev->ifnum; + dr.length = 12; + memset(cmd, -1, sizeof(cmd)); + cmd[0] = SEND_DIAGNOSTIC; + cmd[1] = 4; + us->pusb_dev->bus->op->control_msg(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev,0), + &dr, cmd, 12); + + usb_clear_halt(us->pusb_dev, us->ep_in | 0x80); + usb_clear_halt(us->pusb_dev, us->ep_out); + + /* long wait for reset */ + + schedule_timeout(HZ*5); + return 0; +} + static int pop_CB_command(Scsi_Cmnd *srb) { struct us_data *us = (struct us_data *)srb->host_scribble; devrequest dr; unsigned char cmd[16]; int result; - int retry = 1; + int retry = 5; int done_start = 0; while (retry--) { @@ -279,7 +319,8 @@ static int pop_CB_command(Scsi_Cmnd *srb) result = us->pusb_dev->bus->op->control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), &dr, cmd, us->fixedlength); - if (!done_start && us->subclass == US_SC_UFI && cmd[0] == TEST_UNIT_READY && result) { + if (!done_start && (us->subclass == US_SC_UFI /*|| us->subclass == US_SC_8070*/) + && cmd[0] == TEST_UNIT_READY && result) { /* as per spec try a start command, wait and retry */ done_start++; @@ -302,35 +343,47 @@ static int pop_CB_command(Scsi_Cmnd *srb) return result; } -/* Protocol command handlers */ +/* + * Control/Bulk status handler + */ -static int pop_CBI(Scsi_Cmnd *srb) +static int pop_CB_status(Scsi_Cmnd *srb) { struct us_data *us = (struct us_data *)srb->host_scribble; int result; + __u8 status[2]; + devrequest dr; + int retry = 5; - /* run the command */ - - if ((result = pop_CB_command(srb))) { - US_DEBUGP("CBI command %x\n", result); - if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) - return (DID_OK << 16) | 2; - return DID_ABORT << 16; - } - - /* transfer the data */ - - if (us_transfer_length(srb)) { - result = us_transfer(srb, US_DIRECTION(srb->cmnd[0])); - if (result && result != USB_ST_DATAUNDERRUN) { - US_DEBUGP("CBI transfer %x\n", result); + switch (us->protocol) { + case US_PR_CB: + /* get from control */ + + while (retry--) { + dr.requesttype = 0x80 | USB_TYPE_STANDARD | USB_RT_DEVICE; + dr.request = USB_REQ_GET_STATUS; + dr.index = 0; + dr.value = 0; + dr.length = 2; + result = us->pusb_dev->bus->op->control_msg(us->pusb_dev, + usb_rcvctrlpipe(us->pusb_dev,0), + &dr, status, sizeof(status)); + if (result != USB_ST_TIMEOUT) + break; + } + if (result) { + US_DEBUGP("Bad AP status request %d\n", result); return DID_ABORT << 16; } - } - - /* get status */ + US_DEBUGP("Got AP status %x %x\n", status[0], status[1]); + if (srb->cmnd[0] != REQUEST_SENSE && srb->cmnd[0] != INQUIRY && + ( (status[0] & ~3) || status[1])) + return (DID_OK << 16) | 2; + else + return DID_OK << 16; + break; - if (us->protocol == US_PR_CBI) { + case US_PR_CBI: /* get from interrupt pipe */ /* add interrupt transfer, marked for removal */ @@ -367,12 +420,48 @@ static int pop_CBI(Scsi_Cmnd *srb) return DID_ABORT << 16; } return (DID_OK << 16) + ((us->ip_data & 0x300) ? 2 : 0); - } else { - /* get from where? */ } return DID_ERROR << 16; } +/* Protocol command handlers */ + +static int pop_CBI(Scsi_Cmnd *srb) +{ + struct us_data *us = (struct us_data *)srb->host_scribble; + int result; + + /* run the command */ + + if ((result = pop_CB_command(srb))) { + US_DEBUGP("CBI command %x\n", result); + if (result == USB_ST_STALL || result == USB_ST_TIMEOUT) { + return (DID_OK << 16) | 2; + } + return DID_ABORT << 16; + } + + /* transfer the data */ + + if (us_transfer_length(srb)) { + result = us_transfer(srb, US_DIRECTION(srb->cmnd[0])); + if (result && result != USB_ST_DATAUNDERRUN) { + US_DEBUGP("CBI transfer %x\n", result); + return DID_ABORT << 16; + } else if (result == USB_ST_DATAUNDERRUN) { + return DID_OK << 16; + } + } else { + if (!result) { + return DID_OK << 16; + } + } + + /* get status */ + + return pop_CB_status(srb); +} + static int pop_Bulk_reset(struct us_data *us) { devrequest dr; @@ -380,21 +469,20 @@ static int pop_Bulk_reset(struct us_data *us) dr.requesttype = USB_TYPE_CLASS | USB_RT_INTERFACE; dr.request = US_BULK_RESET; - dr.value = US_BULK_RESET_SOFT; + dr.value = US_BULK_RESET_HARD; dr.index = 0; dr.length = 0; - US_DEBUGP("Bulk soft reset\n"); result = us->pusb_dev->bus->op->control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), &dr, NULL, 0); - if (result) { - US_DEBUGP("Bulk soft reset failed %d\n", result); - dr.value = US_BULK_RESET_HARD; - result = us->pusb_dev->bus->op->control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), &dr, NULL, 0); - if (result) - US_DEBUGP("Bulk hard reset failed %d\n", result); - } + if (result) + US_DEBUGP("Bulk hard reset failed %d\n", result); usb_clear_halt(us->pusb_dev, us->ep_in | 0x80); usb_clear_halt(us->pusb_dev, us->ep_out); + + /* long wait for reset */ + + schedule_timeout(HZ*5); + return result; } /* @@ -453,8 +541,6 @@ static int pop_Bulk(Scsi_Cmnd *srb) stall = 0; do { - //usb_settoggle(us->pusb_dev, us->ep_in, 0); /* AAARgh!! */ - US_DEBUGP("Toggle is %d\n", usb_gettoggle(us->pusb_dev, us->ep_in)); result = us->pusb_dev->bus->op->bulk_msg(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in), &bcs, US_BULK_CS_WRAP_LEN, &partial); @@ -564,6 +650,9 @@ static int us_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *)) struct us_data *us = (struct us_data *)srb->host->hostdata[0]; US_DEBUGP("Command wakeup\n"); + if (us->srb) { + /* busy */ + } srb->host_scribble = (unsigned char *)us; us->srb = srb; srb->scsi_done = done; @@ -581,9 +670,12 @@ static int us_abort( Scsi_Cmnd *srb ) return 0; } -static int us_device_reset( Scsi_Cmnd *srb ) +static int us_bus_reset( Scsi_Cmnd *srb ) { - return 0; + struct us_data *us = (struct us_data *)srb->host->hostdata[0]; + + us->pop_reset(us); + return SUCCESS; } static int us_host_reset( Scsi_Cmnd *srb ) @@ -591,10 +683,6 @@ static int us_host_reset( Scsi_Cmnd *srb ) return 0; } -static int us_bus_reset( Scsi_Cmnd *srb ) -{ - return 0; -} #undef SPRINTF #define SPRINTF(args...) { if (pos < (buffer + length)) pos += sprintf (pos, ## args); } @@ -623,9 +711,9 @@ int usb_scsi_proc_info (char *buffer, char **start, off_t offset, int length, in if (inout) return length; - if (!(vendor = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer))) + if (!us->pusb_dev || !(vendor = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer))) vendor = "?"; - if (!(product = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct))) + if (!us->pusb_dev || !(product = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct))) product = "?"; switch (us->protocol) { @@ -677,7 +765,7 @@ static Scsi_Host_Template my_host_template = { us_queuecommand, NULL, /* eh_strategy */ us_abort, - us_device_reset, + us_bus_reset, us_bus_reset, us_host_reset, NULL, /* abort */ @@ -695,6 +783,25 @@ static Scsi_Host_Template my_host_template = { TRUE /* emulated */ }; +static unsigned char sense_notready[] = { + 0x70, /* current error */ + 0x00, + 0x02, /* not ready */ + 0x00, + 0x00, + 10, /* additional length */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x04, /* not ready */ + 0x03, /* manual intervention */ + 0x00, + 0x00, + 0x00, + 0x00 +}; + static int usbscsi_control_thread(void * __us) { struct us_data *us = (struct us_data *)__us; @@ -710,7 +817,7 @@ static int usbscsi_control_thread(void * __us) exit_files(current); //exit_fs(current); - sprintf(current->comm, "usbscsi%d", us->host_no); + sprintf(current->comm, "usbscsi%d", us->host_number); unlock_kernel(); @@ -727,18 +834,160 @@ static int usbscsi_control_thread(void * __us) switch (action) { case US_ACT_COMMAND : - if (!us->pusb_dev || us->srb->target || us->srb->lun) { + if (us->srb->target || us->srb->lun) { /* bad device */ US_DEBUGP( "Bad device number (%d/%d) or dev %x\n", us->srb->target, us->srb->lun, (unsigned int)us->pusb_dev); us->srb->result = DID_BAD_TARGET << 16; + } else if (!us->pusb_dev) { + + /* our device has gone - pretend not ready */ + + if (us->srb->cmnd[0] == REQUEST_SENSE) { + memcpy(us->srb->request_buffer, sense_notready, sizeof(sense_notready)); + us->srb->result = DID_OK << 16; + } else { + us->srb->result = (DID_OK << 16) | 2; + } } else { US_DEBUG(us_show_command(us->srb)); + + /* check for variable length - do properly if so */ + if (us->filter && us->filter->command) us->srb->result = us->filter->command(us->fdata, us->srb); - else + else if (us->srb->cmnd[0] == START_STOP && + us->pusb_dev->descriptor.idProduct == 0x0001 && + us->pusb_dev->descriptor.idVendor == 0x04e6) + us->srb->result = DID_OK << 16; + else { + unsigned int savelen = us->srb->request_bufflen; + unsigned int saveallocation; + + switch (us->srb->cmnd[0]) { + case REQUEST_SENSE: + if (us->srb->request_bufflen > 18) + us->srb->request_bufflen = 18; + else + break; + saveallocation = us->srb->cmnd[4]; + us->srb->cmnd[4] = 18; + break; + + case INQUIRY: + if (us->srb->request_bufflen > 36) + us->srb->request_bufflen = 36; + else + break; + saveallocation = us->srb->cmnd[4]; + us->srb->cmnd[4] = 36; + break; + + case MODE_SENSE: + if (us->srb->request_bufflen > 4) + us->srb->request_bufflen = 4; + else + break; + saveallocation = us->srb->cmnd[4]; + us->srb->cmnd[4] = 4; + break; + + case LOG_SENSE: + case MODE_SENSE_10: + if (us->srb->request_bufflen > 8) + us->srb->request_bufflen = 8; + else + break; + saveallocation = (us->srb->cmnd[7] << 8) | us->srb->cmnd[8]; + us->srb->cmnd[7] = 0; + us->srb->cmnd[8] = 8; + break; + + default: + break; + } us->srb->result = us->pop(us->srb); + + if (savelen != us->srb->request_bufflen && + us->srb->result == (DID_OK << 16)) { + unsigned char *p = (unsigned char *)us->srb->request_buffer; + unsigned int length; + + /* set correct length and retry */ + switch (us->srb->cmnd[0]) { + case REQUEST_SENSE: + /* simply return 18 bytes */ + p[7] = 10; + length = us->srb->request_bufflen;; + break; + + case INQUIRY: + length = p[4] + 5 > savelen ? savelen : p[4] + 5; + us->srb->cmnd[4] = length; + break; + + case MODE_SENSE: + length = p[0] + 4 > savelen ? savelen : p[0] + 4; + us->srb->cmnd[4] = 4; + break; + + case LOG_SENSE: + length = ((p[2] << 8) + p[3]) + 4 > savelen ? savelen : ((p[2] << 8) + p[3]) + 4; + us->srb->cmnd[7] = length >> 8; + us->srb->cmnd[8] = length; + break; + + case MODE_SENSE_10: + length = ((p[0] << 8) + p[1]) + 8 > savelen ? savelen : ((p[0] << 8) + p[1]) + 8; + us->srb->cmnd[7] = length >> 8; + us->srb->cmnd[8] = length; + break; + } + + US_DEBUGP("Old/New length = %d/%d\n", savelen, length); + + if (us->srb->request_bufflen != length) { + us->srb->request_bufflen = length; + us->srb->result = us->pop(us->srb); + } + /* reset back to original values */ + + us->srb->request_bufflen = savelen; + switch (us->srb->cmnd[0]) { + case REQUEST_SENSE: + case INQUIRY: + case MODE_SENSE: + us->srb->cmnd[4] = saveallocation; + break; + + case LOG_SENSE: + case MODE_SENSE_10: + us->srb->cmnd[7] = saveallocation >> 8; + us->srb->cmnd[8] = saveallocation; + break; + } + } + /* force attention on first command */ + if (!us->attention_done) { + if (us->srb->cmnd[0] == REQUEST_SENSE) { + if (us->srb->result == (DID_OK << 16)) { + unsigned char *p = (unsigned char *)us->srb->request_buffer; + + us->attention_done = 1; + if ((p[2] & 0x0f) != UNIT_ATTENTION) { + p[2] = UNIT_ATTENTION; + p[12] = 0x29; /* power on, reset or bus-reset */ + p[13] = 0; + } + } + } else if (us->srb->cmnd[0] != INQUIRY && + us->srb->result == (DID_OK << 16)) { + us->srb->result |= 2; /* force check condition */ + } + } + } } us->srb->scsi_done(us->srb); + us->srb = NULL; break; case US_ACT_ABORT : @@ -820,7 +1069,7 @@ static int scsi_probe(struct usb_device *dev) if (dev->descriptor.idVendor == 0x04e6 && dev->descriptor.idProduct == 0x0001) { /* shuttle E-USB */ - protocol = US_PR_ZIP; + protocol = US_PR_CB; subclass = US_SC_8070; /* an assumption */ } else if (dev->descriptor.bDeviceClass != 0 || dev->config->altsetting->interface->bInterfaceClass != 8 || @@ -835,11 +1084,15 @@ static int scsi_probe(struct usb_device *dev) usb_string(dev, dev->descriptor.iSerialNumber) ) { make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct, usb_string(dev, dev->descriptor.iSerialNumber)); - for (ss = us_list; ss; ss = ss->next) { - if (GUID_EQUAL(guid, ss->guid)) { - US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); - break; - } + } else { + make_guid(guid, dev->descriptor.idVendor, dev->descriptor.idProduct, + "0"); + } + for (ss = us_list; ss; ss = ss->next) { + if (!ss->pusb_dev && GUID_EQUAL(guid, ss->guid)) { + US_DEBUGP("Found existing GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); + flags = ss->flags; + break; } } } @@ -865,6 +1118,7 @@ static int scsi_probe(struct usb_device *dev) ss->subclass = interface->bInterfaceSubClass; ss->protocol = interface->bInterfaceProtocol; } + ss->attention_done = 0; /* set the protocol op */ @@ -873,16 +1127,19 @@ static int scsi_probe(struct usb_device *dev) case US_PR_CB: US_DEBUGPX("Control/Bulk\n"); ss->pop = pop_CBI; + ss->pop_reset = pop_CB_reset; break; case US_PR_CBI: US_DEBUGPX("Control/Bulk/Interrupt\n"); ss->pop = pop_CBI; + ss->pop_reset = pop_CB_reset; break; default: US_DEBUGPX("Bulk\n"); ss->pop = pop_Bulk; + ss->pop_reset = pop_Bulk_reset; break; } @@ -907,6 +1164,7 @@ static int scsi_probe(struct usb_device *dev) /* exit if strange looking */ if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) || + usb_set_interface(dev, interface->bInterfaceNumber, 0) || !ss->ep_in || !ss->ep_out || (ss->protocol == US_PR_CBI && ss->ep_int == 0)) { US_DEBUGP("Problems with device\n"); if (ss->host) { @@ -933,13 +1191,8 @@ static int scsi_probe(struct usb_device *dev) /* make unique id if possible */ - if (dev->descriptor.iSerialNumber && - usb_string(dev, dev->descriptor.iSerialNumber) ) { - make_guid(ss->guid, dev->descriptor.idVendor, dev->descriptor.idProduct, - usb_string(dev, dev->descriptor.iSerialNumber)); - } - US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); + memcpy(ss->guid, guid, sizeof(guid)); /* set class specific stuff */ @@ -986,9 +1239,30 @@ static int scsi_probe(struct usb_device *dev) (struct us_data *)htmplt->proc_dir = ss; - if (ss->protocol == US_PR_CBI) + + if (dev->descriptor.idVendor == 0x04e6 && + dev->descriptor.idProduct == 0x0001) { + devrequest dr; + __u8 qstat[2]; + + /* shuttle E-USB */ + dr.requesttype = 0xC0; + dr.request = 1; + dr.index = 0; + dr.value = 0; + dr.length = 0; + ss->pusb_dev->bus->op->control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0), &dr, qstat, 2); + US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]); + init_waitqueue_head(&ss->ip_waitq); + ss->pusb_dev->bus->op->request_irq(ss->pusb_dev, + usb_rcvctrlpipe(ss->pusb_dev, ss->ep_int), + pop_CBI_irq, 0, (void *)ss); + interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*5); + + } else if (ss->protocol == US_PR_CBI) init_waitqueue_head(&ss->ip_waitq); + /* start up our thread */ { diff --git a/drivers/usb/usb_scsi_debug.c b/drivers/usb/usb_scsi_debug.c index 2ca847c08..634f4c0f6 100644 --- a/drivers/usb/usb_scsi_debug.c +++ b/drivers/usb/usb_scsi_debug.c @@ -95,7 +95,7 @@ void us_show_command(Scsi_Cmnd *srb) case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break; case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break; case WRITE_LONG_2: what = "WRITE_LONG_2"; break; - default: what = "??"; break; + default: break; } printk(KERN_DEBUG USB_SCSI "Command %s (%d bytes)\n", what, srb->cmd_len); printk(KERN_DEBUG USB_SCSI " %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -- cgit v1.2.3