patch-2.3.11 linux/drivers/usb/uhci.c

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

diff -u --recursive --new-file v2.3.10/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
@@ -344,10 +344,14 @@
 	spin_unlock_irqrestore(&irqlist_lock, flags);
 }
 
+
 /*
  * Request a interrupt handler..
+ *
+ * Returns: a "handle pointer" that release_irq can use to stop this
+ * interrupt.  (It's really a pointer to the TD).
  */
-static int uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
+static void* uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
 {
 	struct uhci_device *dev = usb_to_uhci(usb_dev);
 	struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub);
@@ -357,7 +361,7 @@
 	unsigned int destination, status;
 
 	/* Destination: pipe destination with INPUT */
-	destination = (pipe & 0x0007ff00) | 0x69;
+	destination = (pipe & PIPE_DEVEP_MASK) | 0x69;
 
 	/* Status:    slow/fast,      Interrupt,   Active,    Short Packet Detect     Infinite Errors */
 	status = (pipe & (1 << 26)) | (1 << 24) | (1 << 23)   |   (1 << 29)       |    (0 << 27);
@@ -368,7 +372,8 @@
 
 	td->link = 1;
 	td->status = status;			/* In */
-	td->info = destination | (7 << 21) | (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19);	/* 8 bytes of data */
+	td->info = destination | ((usb_maxpacket(usb_dev, pipe) - 1) << 21) |
+		(usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19);
 	td->buffer = virt_to_bus(dev->data);
 	td->first = td;
 	td->qh = interrupt_qh;
@@ -388,13 +393,16 @@
 
 	/* Add it into the skeleton */
 	uhci_insert_qh(interrupt_qh->skel, interrupt_qh);
-	return 0;
+
+	return (void*)td;
 }
 
 /*
  * Remove running irq td from queues
+ *
+ * This function is not used anymore.
  */
-
+#if 0
 static int uhci_remove_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
 {
     struct uhci_device *dev = usb_to_uhci(usb_dev);
@@ -435,11 +443,56 @@
     spin_unlock_irqrestore(&irqlist_lock, flags);
     return USB_ST_INTERNALERROR;
 }
+#endif
+
+/*
+ * Release an interrupt handler previously allocated using
+ * uhci_request_irq.  This function does no validity checking, so make
+ * sure you're not releasing an already released handle as it may be
+ * in use by something else..
+ *
+ * This function can NOT be called from an interrupt.
+ */
+int uhci_release_irq(void* handle)
+{
+	struct uhci_td *td;
+	struct uhci_qh *interrupt_qh;
+	unsigned long flags;
+
+#ifdef UHCI_DEBUG
+	printk("usb-uhci: Releasing irq handle %p\n", handle);
+#endif
+
+	td = (struct uhci_td*)handle;
+	if (td == NULL)
+		return USB_ST_INTERNALERROR;
+
+	/* Remove it from the internal irq_list */
+	spin_lock_irqsave(&irqlist_lock, flags);
+	list_del(&td->irq_list);
+	spin_unlock_irqrestore(&irqlist_lock, flags);
+
+	/* Remove the interrupt TD and QH */
+	uhci_remove_td(td);
+	interrupt_qh = td->qh;
+	uhci_remove_qh(interrupt_qh->skel, interrupt_qh);
+
+	if (td->completed != NULL)
+		td->completed(USB_ST_REMOVED, NULL, 0, td->dev_id);
+
+	/* Free the TD and QH */
+	uhci_td_deallocate(td);
+	uhci_qh_deallocate(interrupt_qh);
+
+	return USB_ST_NOERROR;
+} /* uhci_release_irq() */
+
+
 /*
  * Isochronous thread operations
  */
 
-int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc)
+static int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc)
 {
 	struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
 	char *data = isodesc->data;
@@ -466,7 +519,7 @@
 	return totlen;
 }
 
-int uhci_unsched_isochronous(struct usb_device *usb_dev, void *_isodesc)
+static int uhci_unschedule_isochronous(struct usb_device *usb_dev, void *_isodesc)
 {
 	struct uhci_device *dev = usb_to_uhci(usb_dev);
 	struct uhci *uhci = dev->uhci;
@@ -489,7 +542,7 @@
 }
 	
 /* td points to the one td we allocated for isochronous transfers */
-int uhci_sched_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc)
+static int uhci_schedule_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc)
 {
 	struct uhci_device *dev = usb_to_uhci(usb_dev);
 	struct uhci *uhci = dev->uhci;
@@ -499,7 +552,7 @@
 
 	if (isodesc->frame != -1) {
 		printk("isoc queue not removed\n");
-		uhci_unsched_isochronous(usb_dev, isodesc);
+		uhci_unschedule_isochronous(usb_dev, isodesc);
 	}
 
 	/* Insert TD into list */
@@ -541,7 +594,7 @@
 /*
  * Initialize isochronous queue
  */
-void *uhci_alloc_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
+static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
 {
 	struct uhci_device *dev = usb_to_uhci(usb_dev);
 	unsigned long destination, status;
@@ -580,7 +633,7 @@
 		td = &isodesc->td[i];
 
 		/* The "pipe" thing contains the destination in bits 8--18 */
-		destination = (pipe & 0x0007ff00);
+		destination = (pipe & PIPE_DEVEP_MASK);
 
 		if (usb_pipeout(pipe))
 			destination |= 0xE1;	/* OUT */
@@ -616,13 +669,13 @@
 	return isodesc;
 }
 
-void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc)
+static void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc)
 {
 	struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
 
 	/* If it's still scheduled, unschedule them */
 	if (isodesc->frame)
-		uhci_unsched_isochronous(usb_dev, isodesc);
+		uhci_unschedule_isochronous(usb_dev, isodesc);
 
 	/* Remove it from the IRQ list */
 	uhci_remove_irq_list(&isodesc->td[isodesc->num - 1]);
@@ -732,7 +785,7 @@
  * 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, void *cmd, void *data, int len)
+static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len)
 {
 	struct uhci_device *dev = usb_to_uhci(usb_dev);
 	struct uhci_td *first, *td, *prevtd;
@@ -746,7 +799,7 @@
 	first = td = uhci_td_allocate(dev);
 
 	/* The "pipe" thing contains the destination in bits 8--18, 0x2D is SETUP */
-	destination = (pipe & 0x0007ff00) | 0x2D;
+	destination = (pipe & PIPE_DEVEP_MASK) | 0x2D;
 
 	/* Status:    slow/fast,       Active,    Short Packet Detect     Three Errors */
 	status = (pipe & (1 << 26)) | (1 << 23)   |   (1 << 29)       |    (3 << 27);
@@ -807,7 +860,7 @@
 
 	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->info = destination | (UHCI_NULL_DATA_SIZE << 21);	/* 0 bytes of data */
 	td->buffer = 0;
 	td->first = first;
 	td->link = 1;					/* Terminate */
@@ -837,7 +890,7 @@
 	}
 
 	if (uhci_debug && ret) {
-		__u8 *p = cmd;
+		__u8 *p = (__u8 *)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]);
@@ -964,10 +1017,10 @@
 	  I FORGOT WHAT IT EXACTLY DOES
 	*/
 	if (usb_pipeout(pipe)) {
-		destination = (pipe & 0x0007ff00) | 0xE1;
+		destination = (pipe & PIPE_DEVEP_MASK) | 0xE1;
 	}
 	else {
-		destination = (pipe & 0x0007ff00) | 0x69;
+		destination = (pipe & PIPE_DEVEP_MASK) | 0x69;
 	}
 
 	/* Status:    slow/fast,       Active,    Short Packet Detect     Three Errors */
@@ -1124,7 +1177,12 @@
 	uhci_control_msg,
 	uhci_bulk_msg,
 	uhci_request_irq,
-	uhci_remove_irq,
+	uhci_release_irq,
+	uhci_allocate_isochronous,
+	uhci_delete_isochronous,
+	uhci_schedule_isochronous,
+	uhci_unschedule_isochronous,
+	uhci_compress_isochronous
 };
 
 /*
@@ -1192,6 +1250,9 @@
 	 * and find out what it wants to do..
 	 */
 	usb_dev = uhci_usb_allocate(root_hub->usb);
+	if (!usb_dev)
+		return;
+	
 	dev = usb_dev->hcpriv;
 
 	dev->uhci = uhci;
@@ -1622,8 +1683,8 @@
 				printk("UHCI queue dump:\n");
 				show_queues(uhci);
 			} else if (signr == SIGUSR2) {
-				printk("UHCI debug toggle\n");
 				uhci_debug = !uhci_debug;
+				printk("UHCI debug toggle = %x\n", uhci_debug);
 			} else {
 				break;
 			}

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