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
- Lines: 256
- Date:
Mon Jul 19 11:18:42 1999
- Orig file:
v2.3.10/linux/drivers/usb/uhci.c
- Orig date:
Thu Jul 8 15:42:21 1999
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)