diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 05:27:25 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 05:27:25 +0000 |
commit | c9c06167e7933d93a6e396174c68abf242294abb (patch) | |
tree | d9a8bb30663e9a3405a1ef37ffb62bc14b9f019f /drivers/usb/uhci.c | |
parent | f79e8cc3c34e4192a3e5ef4cc9c6542fdef703c0 (diff) |
Merge with Linux 2.4.0-test12.
Diffstat (limited to 'drivers/usb/uhci.c')
-rw-r--r-- | drivers/usb/uhci.c | 174 |
1 files changed, 83 insertions, 91 deletions
diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c index 0a0d32f69..40cf2f746 100644 --- a/drivers/usb/uhci.c +++ b/drivers/usb/uhci.c @@ -2,12 +2,16 @@ * Universal Host Controller Interface driver for USB. * * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@sventech.com + * (C) Copyright 1999-2000 Johannes Erdfelt, johannes@erdfelt.com * (C) Copyright 1999 Randy Dunlap * (C) Copyright 1999 Georg Acher, acher@in.tum.de * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at + * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface + * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). + * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) + * * * Intel documents this fairly well, and as far as I know there * are no royalties or anything like that, but even so there are @@ -21,6 +25,7 @@ * - working around the horridness of the rest */ +#include <linux/config.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/kernel.h> @@ -46,7 +51,6 @@ #include "uhci-debug.h" #include <linux/pm.h> -static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data); static int debug = 1; MODULE_PARM(debug, "i"); @@ -56,8 +60,6 @@ static kmem_cache_t *uhci_td_cachep; static kmem_cache_t *uhci_qh_cachep; static kmem_cache_t *uhci_up_cachep; /* urb_priv */ -static LIST_HEAD(uhci_list); - static int rh_submit_urb(struct urb *urb); static int rh_unlink_urb(struct urb *urb); static int uhci_get_current_frame_number(struct usb_device *dev); @@ -1753,11 +1755,11 @@ static void rh_int_timer_do(unsigned long ptr) urbp = (struct urb_priv *)u->hcpriv; if (urbp) { /* Check if the FSBR timed out */ - if (urbp->fsbr && time_after(urbp->inserttime + IDLE_TIMEOUT, jiffies)) + if (urbp->fsbr && time_after_eq(jiffies, urbp->inserttime + IDLE_TIMEOUT)) uhci_fsbr_timeout(uhci, u); /* Check if the URB timed out */ - if (u->timeout && time_after(u->timeout, jiffies)) { + if (u->timeout && time_after_eq(jiffies, u->timeout)) { u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED; uhci_unlink_urb(u); } @@ -2343,9 +2345,7 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign uhci = alloc_uhci(io_addr, io_size); if (!uhci) return -ENOMEM; - - INIT_LIST_HEAD(&uhci->uhci_list); - list_add(&uhci->uhci_list, &uhci_list); + dev->driver_data = uhci; request_region(uhci->io_addr, io_size, "usb-uhci"); @@ -2358,21 +2358,13 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci) == 0) { uhci->irq = irq; - if (!uhci_start_root_hub(uhci)) { - struct pm_dev *pmdev; + pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); - pmdev = pm_register(PM_PCI_DEV, - PM_PCI_ID(dev), - handle_pm_event); - if (pmdev) - pmdev->data = uhci; + if (!uhci_start_root_hub(uhci)) return 0; - } } /* Couldn't allocate IRQ if we got here */ - list_del(&uhci->uhci_list); - INIT_LIST_HEAD(&uhci->uhci_list); reset_hc(uhci); release_region(uhci->io_addr, uhci->io_size); @@ -2381,19 +2373,19 @@ static int setup_uhci(struct pci_dev *dev, int irq, unsigned int io_addr, unsign return retval; } -static int found_uhci(struct pci_dev *dev) +static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { int i; /* disable legacy emulation */ - pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); + pci_write_config_word(dev, USBLEGSUP, 0); if (pci_enable_device(dev) < 0) - return -1; + return -ENODEV; if (!dev->irq) { err("found UHCI device with no IRQ assigned. check BIOS settings!"); - return -1; + return -ENODEV; } /* Search for the IO base address.. */ @@ -2409,32 +2401,77 @@ static int found_uhci(struct pci_dev *dev) if (check_region(io_addr, io_size)) break; + pci_set_master(dev); return setup_uhci(dev, dev->irq, io_addr, io_size); } - return -1; + return -ENODEV; } -static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data) +static void __devexit uhci_pci_remove(struct pci_dev *dev) { - struct uhci *uhci = dev->data; - switch (rqst) { - case PM_SUSPEND: - reset_hc(uhci); - break; - case PM_RESUME: - reset_hc(uhci); - start_hc(uhci); - break; - } - return 0; + struct uhci *uhci = dev->driver_data; + + if (uhci->bus->root_hub) + usb_disconnect(&uhci->bus->root_hub); + + usb_deregister_bus(uhci->bus); + + reset_hc(uhci); + release_region(uhci->io_addr, uhci->io_size); + + uhci_free_pending_qhs(uhci); + + release_uhci(uhci); +} + +static void uhci_pci_suspend(struct pci_dev *dev) +{ + reset_hc((struct uhci *) dev->driver_data); } -static int __init uhci_init(void) +static void uhci_pci_resume(struct pci_dev *dev) +{ + reset_hc((struct uhci *) dev->driver_data); + start_hc((struct uhci *) dev->driver_data); +} + +/*-------------------------------------------------------------------------*/ + +static const struct pci_device_id __devinitdata uhci_pci_ids [] = { { + + /* handle any USB UHCI controller */ + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00), + class_mask: ~0, + + /* 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, uhci_pci_ids); + +static struct pci_driver uhci_pci_driver = { + name: "usb-uhci", + id_table: &uhci_pci_ids [0], + + probe: uhci_pci_probe, + remove: uhci_pci_remove, + +#ifdef CONFIG_PM + suspend: uhci_pci_suspend, + resume: uhci_pci_resume, +#endif /* PM */ +}; + + +static int __init uhci_hcd_init(void) { int retval; - struct pci_dev *dev; - u8 type; retval = -ENOMEM; @@ -2461,25 +2498,8 @@ static int __init uhci_init(void) if (!uhci_up_cachep) goto up_failed; - retval = -ENODEV; - dev = NULL; - for (;;) { - dev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, dev); - if (!dev) - break; - - /* Is it the UHCI programming interface? */ - pci_read_config_byte(dev, PCI_CLASS_PROG, &type); - if (type != 0) - continue; - - /* Ok set it up */ - retval = found_uhci(dev); - } - - /* We only want to return an error code if ther was an error */ - /* and we didn't find a UHCI controller */ - if (retval && list_empty(&uhci_list)) + retval = pci_module_init (&uhci_pci_driver); + if (retval) goto init_failed; return 0; @@ -2500,32 +2520,10 @@ td_failed: return retval; } -void uhci_cleanup(void) +static void __exit uhci_hcd_cleanup (void) { - struct list_head *tmp, *head = &uhci_list; - - tmp = head->next; - while (tmp != head) { - struct uhci *uhci = list_entry(tmp, struct uhci, uhci_list); - - tmp = tmp->next; - - list_del(&uhci->uhci_list); - INIT_LIST_HEAD(&uhci->uhci_list); - - if (uhci->bus->root_hub) - usb_disconnect(&uhci->bus->root_hub); - - usb_deregister_bus(uhci->bus); - - reset_hc(uhci); - release_region(uhci->io_addr, uhci->io_size); - - uhci_free_pending_qhs(uhci); - - release_uhci(uhci); - } - + pci_unregister_driver (&uhci_pci_driver); + if (kmem_cache_destroy(uhci_up_cachep)) printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); @@ -2536,14 +2534,8 @@ void uhci_cleanup(void) printk(KERN_INFO "uhci: not all TD's were freed\n"); } -static void __exit uhci_exit(void) -{ - pm_unregister_all(handle_pm_event); - uhci_cleanup(); -} - -module_init(uhci_init); -module_exit(uhci_exit); +module_init(uhci_hcd_init); +module_exit(uhci_hcd_cleanup); MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"); MODULE_DESCRIPTION("USB Universal Host Controller Interface driver"); |