patch-2.3.22 linux/drivers/usb/uhci.c
Next file: linux/drivers/usb/uhci.h
Previous file: linux/drivers/usb/serial.c
Back to the patch index
Back to the overall index
- Lines: 190
- Date:
Thu Oct 14 14:59:46 1999
- Orig file:
v2.3.21/linux/drivers/usb/uhci.c
- Orig date:
Sat Oct 9 11:47:50 1999
diff -u --recursive --new-file v2.3.21/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
@@ -119,6 +119,7 @@
return USB_ST_INTERNALERROR;
}
+
/*
* Return the result of a TD..
*/
@@ -189,12 +190,12 @@
if (!status)
return USB_ST_NOERROR;
- /* APC BackUPS Pro kludge */
+ /* XXX FIXME APC BackUPS Pro kludge */
/* It tries to send all of the descriptor instead of */
/* the amount we requested */
if (tmp->status & TD_CTRL_IOC &&
tmp->status & TD_CTRL_ACTIVE &&
- tmp->status & TD_CTRL_NAK)
+ tmp->status & TD_CTRL_NAK /* && its a control TD */)
return USB_ST_NOERROR;
#if 0
@@ -627,9 +628,11 @@
*
* Returns 0 (success) or negative (failure).
* Also returns/sets a "handle pointer" that release_irq can use to stop this
- * interrupt. (It's really a pointer to the TD).
+ * 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, void **handle)
+static int uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe,
+ usb_device_irq handler, int period,
+ void *dev_id, void **handle, long bustime)
{
struct uhci_device *dev = usb_to_uhci(usb_dev);
struct uhci_td *td = uhci_td_alloc(dev);
@@ -658,13 +661,15 @@
td->buffer = virt_to_bus(dev->data);
td->qh = qh;
td->dev = dev;
+ td->pipetype = PIPE_INTERRUPT;
+ td->bandwidth_alloc = bustime;
- /* if period 0, insert into fast q */
+ /* if period 0, set _REMOVE flag */
if (period == 0) {
td->flags |= UHCI_TD_REMOVE;
- qh->skel = &dev->uhci->skel_int2_qh;
- } else
- qh->skel = &dev->uhci->skel_int8_qh;
+ }
+
+ qh->skel = &dev->uhci->skelqh[__interval_to_skel(period)];
uhci_add_irq_list(dev->uhci, td, handler, dev_id);
@@ -964,6 +969,7 @@
td->info = destination | ((frlen - 1) << 21);
td->buffer = virt_to_bus (bufptr);
td->dev = dev;
+ td->pipetype = PIPE_ISOCHRONOUS;
td->isoc_td_number = ix; /* 0-based; does not wrap/overflow back to 0 */
if (isocdesc->callback_frames &&
@@ -971,7 +977,7 @@
td->status |= TD_CTRL_IOC;
td->completed = isocdesc->callback_fn;
cb_frames = 0;
- uhci_add_irq_list (dev->uhci, td, isocdesc->callback_fn, isocdesc->context);
+ uhci_add_irq_list (dev->uhci, td, isocdesc->callback_fn, isocdesc);
}
bufptr += fd->frame_length; /* or isocdesc->frame_size; */
@@ -991,7 +997,7 @@
if (!(td->status & TD_CTRL_IOC)) {
td->status |= TD_CTRL_IOC;
td->completed = isocdesc->callback_fn;
- uhci_add_irq_list(dev->uhci, td, isocdesc->callback_fn, isocdesc->context); /* TBD: D.K. ??? */
+ uhci_add_irq_list(dev->uhci, td, isocdesc->callback_fn, isocdesc); /* TBD: D.K. ??? */
}
return 0;
} /* end uhci_run_isoc */
@@ -1158,6 +1164,7 @@
td->status = status; /* Try forever */
td->info = destination | (7 << 21); /* 8 bytes of data */
td->buffer = virt_to_bus(cmd);
+ td->pipetype = PIPE_CONTROL;
/*
* If direction is "send", change the frame from SETUP (0x2D)
@@ -1191,6 +1198,7 @@
td->info = destination | ((pktsze - 1) << 21); /* pktsze bytes of data */
td->buffer = virt_to_bus(data);
td->backptr = &prevtd->link;
+ td->pipetype = PIPE_CONTROL;
data += pktsze;
len -= pktsze;
@@ -1219,6 +1227,7 @@
td->buffer = 0;
td->backptr = &prevtd->link;
td->link = UHCI_PTR_TERM; /* Terminate */
+ td->pipetype = PIPE_CONTROL;
/* Start it up.. */
ret = uhci_run_control(dev, first, td, timeout);
@@ -1349,6 +1358,7 @@
usb_pipeout(pipe)) << TD_TOKEN_TOGGLE); /* pktsze bytes of data */
td->buffer = virt_to_bus(data);
td->backptr = &prevtd->link;
+ td->pipetype = PIPE_BULK;
data += maxsze;
len -= maxsze;
@@ -1429,6 +1439,7 @@
td->backptr = &prevtd->link;
td->qh = bulk_qh;
td->dev = dev;
+ td->pipetype = PIPE_BULK;
data += pktsze;
len -= pktsze;
@@ -1467,11 +1478,11 @@
{
/* none found? there is nothing to remove! */
if (!first)
- return 0;
+ return USB_ST_REMOVED;
uhci_remove_transfer(first, 1);
- return 1;
+ return USB_ST_NOERROR;
}
struct usb_operations uhci_device_operations = {
@@ -1698,7 +1709,7 @@
uhci_packetout(td->info)) << 19; /* toggle between data0 and data1 */
td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
/* The HC only removes it when it completed */
- /* successfully, so force remove and readd it */
+ /* successfully, so force remove and re-add it */
uhci_remove_td(td);
uhci_insert_td_in_qh(td->qh, td);
} else if (td->flags & UHCI_TD_REMOVE) {
@@ -1710,6 +1721,8 @@
uhci_remove_qh(td->qh->skel, td->qh);
uhci_qh_free(td->qh);
uhci_td_free(td);
+ if (td->pipetype == PIPE_INTERRUPT)
+ usb_release_bandwidth(usb_dev, td->bandwidth_alloc);
}
/* If completed does not wants to reactivate, then */
@@ -1790,6 +1803,7 @@
td->info = (15 << 21) | (0x7f << 8) | USB_PID_IN; /* (ignored) input packet, 16 bytes, device 127 */
td->buffer = 0;
td->qh = NULL;
+ td->pipetype = -1;
uhci->fl->frame[0] = virt_to_bus(td);
@@ -1931,16 +1945,21 @@
usb->maxchild = port;
usb_init_root_hub(usb);
- /* 8 Interrupt queues */
- for (i = 0; i < 8; i++) {
+ /*
+ * 9 Interrupt queues; link int2 thru int256 to int1 first,
+ * then link int1 to control and control to bulk
+ */
+ for (i = 1; i < 9; i++) {
struct uhci_qh *qh = &uhci->skelqh[i];
- qh->link = virt_to_bus(&uhci->skel_control_qh) | UHCI_PTR_QH;
+ qh->link = virt_to_bus(&uhci->skel_int1_qh) | UHCI_PTR_QH;
qh->element = UHCI_PTR_TERM;
}
- uhci->skel_control_qh.link = virt_to_bus(&uhci->skel_bulk_qh) |
- UHCI_PTR_QH;
+ uhci->skel_int1_qh.link = virt_to_bus(&uhci->skel_control_qh) | UHCI_PTR_QH;
+ uhci->skel_int1_qh.element = UHCI_PTR_TERM;
+
+ uhci->skel_control_qh.link = virt_to_bus(&uhci->skel_bulk_qh) | UHCI_PTR_QH;
uhci->skel_control_qh.element = UHCI_PTR_TERM;
uhci->skel_bulk_qh.link = UHCI_PTR_TERM;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)