patch-2.4.0-test12 linux/drivers/usb/uhci.c

Next file: linux/drivers/usb/usb-uhci.c
Previous file: linux/drivers/usb/storage/usb.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/uhci.c linux/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_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 @@
 		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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 int __init uhci_init(void)
+static void uhci_pci_suspend(struct pci_dev *dev)
+{
+	reset_hc((struct uhci *) dev->driver_data);
+}
+
+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 @@
 	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 @@
 	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 @@
 		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");

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)