patch-2.3.10 linux/drivers/usb/ohci.c
Next file: linux/drivers/usb/ohci.h
Previous file: linux/drivers/usb/ohci-debug.c
Back to the patch index
Back to the overall index
- Lines: 209
- Date:
Sat Jul 3 18:07:29 1999
- Orig file:
v2.3.9/linux/drivers/usb/ohci.c
- Orig date:
Wed Jun 30 13:38:20 1999
diff -u --recursive --new-file v2.3.9/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c
@@ -179,27 +179,27 @@
/* .......... */
-inline void ohci_start_control(struct ohci *ohci)
+void ohci_start_control(struct ohci *ohci)
{
/* tell the HC to start processing the control list */
writel_set(OHCI_USB_CLE, &ohci->regs->control);
writel_set(OHCI_CMDSTAT_CLF, &ohci->regs->cmdstatus);
}
-inline void ohci_start_bulk(struct ohci *ohci)
+void ohci_start_bulk(struct ohci *ohci)
{
/* tell the HC to start processing the bulk list */
writel_set(OHCI_USB_BLE, &ohci->regs->control);
writel_set(OHCI_CMDSTAT_BLF, &ohci->regs->cmdstatus);
}
-inline void ohci_start_periodic(struct ohci *ohci)
+void ohci_start_periodic(struct ohci *ohci)
{
/* enable processing periodic (intr) transfers starting next frame */
writel_set(OHCI_USB_PLE, &ohci->regs->control);
}
-inline void ohci_start_isoc(struct ohci *ohci)
+void ohci_start_isoc(struct ohci *ohci)
{
/* enable processing isoc. transfers starting next frame */
writel_set(OHCI_USB_IE, &ohci->regs->control);
@@ -658,7 +658,7 @@
* dir = OHCI_TD_D_IN, OHCI_TD_D_OUT, or OHCI_TD_D_SETUP
* toggle = TOGGLE_AUTO, TOGGLE_DATA0, TOGGLE_DATA1
*/
-inline struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32 flags, void *data, __u32 len, void *dev_id, usb_device_irq completed)
+struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32 flags, void *data, __u32 len, void *dev_id, usb_device_irq completed)
{
/* hardware fields */
td->info = cpu_to_le32(OHCI_TD_CC_NEW |
@@ -846,16 +846,20 @@
return 0;
/* if cur_buf is 0, all data has been transferred */
- bus_data_end = td->cur_buf ? td->cur_buf : td->buf_end;
+ if (!td->cur_buf) {
+ return td->buf_end - bus_data_start + 1;
+ }
+
+ bus_data_end = td->cur_buf;
/* is it on the same page? */
if ((bus_data_start & ~0xfff) == (bus_data_end & ~0xfff)) {
- result = bus_data_end - bus_data_start + 1;
+ result = bus_data_end - bus_data_start;
} else {
/* compute the amount transferred on the first page */
result = 0x1000 - (bus_data_start & 0xfff);
/* add the amount done in the second page */
- result += (bus_data_end & 0xfff) + 1;
+ result += (bus_data_end & 0xfff);
}
return result;
@@ -1190,16 +1194,12 @@
if (stats == USB_ST_NOERROR)
req->_bytes_done += len;
-#ifdef OHCI_DEBUG
- printk(KERN_DEBUG "ohci_bulk_td_handler %d bytes done\n", req->_bytes_done);
-#endif
-
/* call the real completion handler when done or on an error */
if ((stats != USB_ST_NOERROR) ||
(req->_bytes_done >= req->length && req->completion != NULL)) {
*req->bytes_transferred_p += req->_bytes_done;
#ifdef OHCI_DEBUG
- printk(KERN_DEBUG "usb-ohci: bulk request %p ending after %d bytes\n", req, req->_bytes_done);
+ printk(KERN_DEBUG "usb-ohci: bulk request %p ending\n", req);
#endif
req->completion(stats, buffer, req->_bytes_done, req->dev_id);
}
@@ -1282,13 +1282,13 @@
#ifdef OHCI_DEBUG
-/* if (MegaDebug) { */
- /* complete transaction debugging output (before) */
+ if (MegaDebug) {
+ /* complete request debugging output (before) */
printk(KERN_DEBUG " Bulk ED %lx:\n", virt_to_bus(bulk_ed));
show_ohci_ed(bulk_ed);
printk(KERN_DEBUG " Bulk TDs %lx:\n", virt_to_bus(head_td));
show_ohci_td_chain(head_td);
-/* } */
+ }
#endif
/* Give the ED to the HC */
@@ -1303,6 +1303,9 @@
static int ohci_bulk_msg_completed(int stats, void *buffer, int len, void *dev_id)
{
+#ifdef OHCI_DEBUG
+ printk("ohci_bulk_msg_completed %x, %p, %d, %p\n", stats, buffer, len, dev_id);
+#endif
if (dev_id != NULL) {
int *completion_status = (int *)dev_id;
*completion_status = stats;
@@ -1320,12 +1323,15 @@
struct ohci_bulk_request_state req;
struct ohci_ed *req_ed;
- /* ....... */
-
#ifdef OHCI_DEBUG
printk(KERN_DEBUG "ohci_bulk_msg %p pipe %x, data %p, len %d, bytes_transferred %p\n", usb_dev, pipe, data, len, bytes_transferred_p);
#endif
+ /* initialize bytes transferred to nothing */
+ *bytes_transferred_p = 0;
+
+ /* Hopefully this is similar to the "URP" (USB Request Packet) code
+ * that michael gee is working on... */
req.usb_dev = usb_dev;
req.pipe = pipe;
req.data = data;
@@ -1345,9 +1351,44 @@
/* FIXME this should to wait for a caller specified time... */
schedule_timeout(HZ*5);
+ /* it'll only stay in this state of the request never finished */
+ if (completion_status == USB_ST_INTERNALERROR) {
+ struct ohci_device *dev = usb_to_ohci(usb_dev);
+ struct ohci_regs *regs = dev->ohci->regs;
+
#ifdef OHCI_DEBUG
- printk(KERN_DEBUG "ohci_bulk_msg request completed or timed out w/ status %x\n", completion_status);
+ printk(KERN_DEBUG "ohci_bulk_msg timing out\n");
#endif
+ /* XXX This code should go into a function used to stop
+ * a previously requested bulk transfer. -greg */
+
+ /* stop the transfer & collect the number of bytes */
+ ohci_wait_for_ed_safe(regs, req_ed, HCD_ED_BULK);
+
+ /* Get the number of bytes transferred out of the head TD
+ * on the ED if it didn't finish while we were waiting. */
+ if ( ed_head_td(req_ed) &&
+ (ed_head_td(req_ed) != ed_tail_td(req_ed)) ) {
+ struct ohci_td *partial_td;
+ partial_td = bus_to_virt(ed_head_td(req_ed));
+
+#ifdef OHCI_DEBUG
+ if (MegaDebug) {
+ show_ohci_td(partial_td);
+ }
+#endif
+ /* Record the bytes as transferred */
+ *bytes_transferred_p += ohci_td_bytes_done(partial_td);
+
+ /* If there was an unreported error, return it.
+ * Otherwise return a timeout */
+ completion_status = OHCI_TD_CC_GET(partial_td->info);
+ if (completion_status == USB_ST_NOERROR) {
+ completion_status = USB_ST_TIMEOUT;
+ }
+ }
+
+ }
remove_wait_queue(&bulk_wakeup, &wait);
@@ -1356,7 +1397,7 @@
ohci_free_ed(req_ed); /* return it to the pool */
#ifdef OHCI_DEBUG
- printk(KERN_DEBUG "ohci_bulk_msg done.\n");
+ printk(KERN_DEBUG "ohci_bulk_msg done, status %x (bytes_transferred = %ld).\n", completion_status, *bytes_transferred_p);
#endif
return completion_status;
@@ -1761,7 +1802,7 @@
struct ohci_td *td; /* used for walking the list */
/* um... isn't this dangerous to do in an interrupt handler? -greg */
- spin_lock(&ohci_edtd_lock);
+// spin_lock(&ohci_edtd_lock);
/* create the FIFO ordered donelist */
td = ohci_reverse_donelist(ohci);
@@ -1832,6 +1873,7 @@
/* insert it back on its ED */
ohci_add_td_to_ed(td, td, td->ed);
+ ohci_unhalt_ed(td->ed);
} else {
/* return it to the pool of free TDs */
if (can_auto_free(*td))
@@ -1841,7 +1883,7 @@
td = next_td;
}
- spin_unlock(&ohci_edtd_lock);
+// spin_unlock(&ohci_edtd_lock);
} /* ohci_reap_donelist() */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)