patch-2.3.4 linux/drivers/usb/ohci-hcd.c
Next file: linux/drivers/usb/ohci-hcd.h
Previous file: linux/drivers/usb/mouse.c
Back to the patch index
Back to the overall index
- Lines: 326
- Date:
Mon May 31 09:01:50 1999
- Orig file:
v2.3.3/linux/drivers/usb/ohci-hcd.c
- Orig date:
Sat May 15 23:46:03 1999
diff -u --recursive --new-file v2.3.3/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
@@ -3,12 +3,14 @@
*
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
*
- * The OHCI HCD layer is a simple but nearly complete implementation of what the
- * USB people would call a HCD for the OHCI.
+ * The OHCI HCD layer is a simple but nearly complete implementation of what
+ * the USB people would call a HCD for the OHCI.
* (ISO comming soon, Bulk disabled, INT u. CTRL transfers enabled)
- * The layer on top of it, is for interfacing to the alternate-usb device-drivers.
+ * The layer on top of it, is for interfacing to the alternate-usb
+ * device-drivers.
*
- * [ This is based on Linus' UHCI code and gregs OHCI fragments (0.03c source tree). ]
+ * [ This is based on Linus' UHCI code and gregs OHCI fragments
+ * (0.03c source tree). ]
* [ Open Host Controller Interface driver for USB. ]
* [ (C) Copyright 1999 Linus Torvalds (uhci.c) ]
* [ (C) Copyright 1999 Gregory P. Smith <greg@electricrain.com> ]
@@ -51,9 +53,6 @@
#include "usb.h"
#include "ohci-hcd.h"
-#include "inits.h"
-
-
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
@@ -62,7 +61,7 @@
#endif
-
+static DECLARE_WAIT_QUEUE_HEAD(bulk_wakeup);
static DECLARE_WAIT_QUEUE_HEAD(control_wakeup);
static DECLARE_WAIT_QUEUE_HEAD(root_hub);
@@ -122,7 +121,19 @@
OHCI_DEBUG( printk(" ret_status: %x\n", status); })
return 0;
}
-
+
+static int sohci_bulk_handler(void * ohci_in, unsigned int ep_addr, int ctrl_len, void * ctrl, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw)
+{
+ *(int * )lw0 = status;
+ wake_up(&bulk_wakeup);
+
+ OHCI_DEBUG( { int i; printk("USB HC BULK<<<: %x:", ep_addr, ctrl_len);)
+ OHCI_DEBUG( printk(" data(%d):", data_len);)
+ OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+ OHCI_DEBUG( printk(" ret_status: %x\n", status); })
+ return 0;
+}
+
static int sohci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
{
struct ohci * ohci = usb_dev->bus->hcpriv;
@@ -179,6 +190,40 @@
return cc_to_status[status & 0x0f];
}
+static int sohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct ohci * ohci = usb_dev->bus->hcpriv;
+ int status;
+ union ep_addr_ ep_addr;
+
+ ep_addr.iep = 0;
+ ep_addr.bep.ep = ((pipe >> 15) & 0x0f) /* endpoint address */
+ | (pipe & 0x80) /* direction */
+ | (11 << 5); /* type = bulk*/
+ ep_addr.bep.fa = ((pipe >> 8) & 0x7f); /* device address */
+
+ status = 0xf; /* CC not Accessed */
+ OHCI_DEBUG( { int i; printk("USB HC BULK>>>: %x:", ep_addr.iep);)
+ OHCI_DEBUG( printk(" data(%d):", len);)
+ OHCI_DEBUG( for(i=0; i < len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+ OHCI_DEBUG( printk("\n"); })
+
+ usb_ohci_add_ep(ohci, ep_addr.iep, 0, 1, sohci_bulk_handler, 1 << ((pipe & 0x03) + 3) , (pipe >> 26) & 0x01);
+
+ current->state = TASK_UNINTERRUPTIBLE;
+ add_wait_queue(&bulk_wakeup, &wait);
+
+ ohci_trans_req(ohci, ep_addr.iep, 0, NULL, data, len, (__OHCI_BAG) &status, 0);
+
+ schedule_timeout(HZ/10);
+
+ remove_wait_queue(&bulk_wakeup, &wait);
+
+ OHCI_DEBUG(printk("USB HC status::: %x\n", cc_to_status[status & 0x0f]);)
+
+ return cc_to_status[status & 0x0f];
+}
static int sohci_usb_deallocate(struct usb_device *usb_dev) {
struct ohci_device *dev = usb_to_ohci(usb_dev);
@@ -234,8 +279,6 @@
return usb_dev;
}
-/* FIXME! */
-#define sohci_bulk_msg NULL
struct usb_operations sohci_device_operations = {
sohci_usb_allocate,
@@ -567,7 +610,7 @@
}
writel(0, &ohci->regs->ed_controlcurrent); /* reset CTRL list */
writel(0, &ohci->regs->ed_bulkcurrent); /* reset BULK list */
- writel_set((0x01<<4), &ohci->regs->control); /* start CTRL u. (BULK list) */
+ writel_set((0x03<<4), &ohci->regs->control); /* start CTRL u. (BULK list) */
spin_unlock_irqrestore(&usb_ed_lock, flags);
@@ -915,6 +958,7 @@
{
/* int fminterval; */
unsigned int mask;
+ int port_nr;
/* fminterval = readl(&ohci->regs->fminterval) & 0x3fff;
reset_hc(ohci); */
@@ -926,16 +970,19 @@
/* | OHCI_INTR_SO | OHCI_INTR_UE |OHCI_INTR_RHSC |OHCI_INTR_SF|
OHCI_INTR_FNO */
-
+ if(readl(&ohci->regs->roothub.a) & 0x100) /* global power on */
+ writel( 0x10000, &ohci->regs->roothub.status); /* root hub power on */
+ else { /* port power on */
+ for(port_nr=0; port_nr < (ohci->regs->roothub.a & 0xff); port_nr++)
+ writel(0x100, &ohci->regs->roothub.portstatus[port_nr]);
+ }
+ wait_ms(50);
writel((0x00), &ohci->regs->control); /* USB Reset BUS */
wait_ms(10);
- writel((0x97), &ohci->regs->control); /* USB Operational */
-
- writel( 0x10000, &ohci->regs->roothub.status); /* root hub power on */
- wait_ms(50);
-
+ writel((0xB7), &ohci->regs->control); /* USB Operational */
+
OHCI_DEBUG(printk("USB HC rstart_hc_operational: %x\n", readl(&ohci->regs->control)); )
OHCI_DEBUG(printk("USB HC roothubstata: %x \n", readl( &(ohci->regs->roothub.a) )); )
OHCI_DEBUG(printk("USB HC roothubstatb: %x \n", readl( &(ohci->regs->roothub.b) )); )
@@ -952,15 +999,15 @@
struct usb_device * usb_dev;
struct ohci_device *dev;
-
- usb_dev = sohci_usb_allocate(ohci->root_hub->usb);
+ struct ohci_device *tmp_root_hub= usb_to_ohci(ohci->bus->root_hub);
+ usb_dev = sohci_usb_allocate(tmp_root_hub->usb);
dev = usb_dev->hcpriv;
dev->ohci = ohci;
usb_connect(usb_dev);
- ohci->root_hub->usb->children[0] = usb_dev;
+ tmp_root_hub->usb->children[0] = usb_dev;
usb_new_device(usb_dev);
}
@@ -1037,6 +1084,7 @@
{
struct usb_device *usb_dev;
struct ohci_device *dev;
+ struct ohci_device *tmp_root_hub=usb_to_ohci(ohci->bus->root_hub);
OHCI_DEBUG(printk("uhci_connect_change: called for %d stat %x\n", port_nr,readl(&ohci->regs->roothub.portstatus[port_nr]) );)
/*
@@ -1046,7 +1094,7 @@
*
* So start off by getting rid of any old devices..
*/
- usb_disconnect(&ohci->root_hub->usb->children[port_nr]);
+ usb_disconnect(&tmp_root_hub->usb->children[port_nr]);
if(!(readl(&ohci->regs->roothub.portstatus[port_nr]) & RH_PS_CCS)) {
writel(RH_PS_CCS, &ohci->regs->roothub.portstatus[port_nr]);
@@ -1056,11 +1104,11 @@
* Ok, we got a new connection. Allocate a device to it,
* and find out what it wants to do..
*/
- usb_dev = sohci_usb_allocate(ohci->root_hub->usb);
+ usb_dev = sohci_usb_allocate(tmp_root_hub->usb);
dev = usb_dev->hcpriv;
dev->ohci = ohci;
usb_connect(dev->usb);
- ohci->root_hub->usb->children[port_nr] = usb_dev;
+ tmp_root_hub->usb->children[port_nr] = usb_dev;
wait_ms(200); /* wait for powerup */
/* reset port/device */
writel(RH_PS_PRS, &ohci->regs->roothub.portstatus[port_nr]); /* reset port */
@@ -1205,10 +1253,9 @@
if (!usb)
return NULL;
- dev = ohci->root_hub = usb_to_ohci(usb);
-
+ dev = usb_to_ohci(usb);
usb->bus = bus;
- /* bus->root_hub = ohci_to_usb(ohci->root_hub); */
+ bus->root_hub = usb;
dev->ohci = ohci;
/* Initialize the root hub */
@@ -1227,10 +1274,11 @@
static void release_ohci(struct ohci *ohci)
{
int i;
+ struct ohci_device *tmp_root_hub=usb_to_ohci(ohci->bus->root_hub);
union ep_addr_ ep_addr;
ep_addr.iep = 0;
- OHCI_DEBUG(printk("USB HC release ohci \n");)
+ OHCI_DEBUG(printk("USB HC release ohci \n"););
if (ohci->irq >= 0) {
free_irq(ohci->irq, ohci);
@@ -1248,25 +1296,22 @@
ohci_rm_eds(ohci); /* remove eds */
/* disconnect all devices */
- if(ohci->root_hub)
- for(i = 0; i < ohci->root_hub->usb->maxchild; i++)
- usb_disconnect(ohci->root_hub->usb->children + i);
+ if(ohci->bus->root_hub)
+ for(i = 0; i < tmp_root_hub->usb->maxchild; i++)
+ usb_disconnect(tmp_root_hub->usb->children + i);
- USB_FREE(ohci->root_hub->usb);
- USB_FREE(ohci->root_hub);
+ usb_deregister_bus(ohci->bus);
+ USB_FREE(tmp_root_hub->usb);
+ USB_FREE(tmp_root_hub);
USB_FREE(ohci->bus);
/* unmap the IO address space */
iounmap(ohci->regs);
-
free_pages((unsigned int) ohci->hc_area, 1);
}
-
-void cleanup_drivers(void);
-
static int ohci_roothub_thread(void * __ohci)
{
struct ohci *ohci = (struct ohci *)__ohci;
@@ -1288,6 +1333,7 @@
start_hc(ohci);
writel( 0x10000, &ohci->regs->roothub.status);
wait_ms(50); /* root hub power on */
+ usb_register_bus(ohci->bus);
do {
#ifdef CONFIG_APM
if (apm_resume) {
@@ -1297,7 +1343,7 @@
}
#endif
- OHCI_DEBUG(printk("USB RH tasks: int: %x\n", ohci->intrstatus); )
+ OHCI_DEBUG(printk("USB RH tasks: int: %x\n",ohci->intrstatus););
#ifndef VROOTHUB
/* if (ohci->intrstatus & OHCI_INTR_RHSC) */
{
@@ -1332,9 +1378,6 @@
return 0;
}
-
-
-
/*
* Increment the module usage count, start the control thread and
* return success.
@@ -1432,20 +1475,6 @@
}
#endif
-
-#ifdef MODULE
-
-void cleanup_module(void)
-{
-#ifdef CONFIG_APM
- apm_unregister_callback(&handle_apm_event);
-#endif
-}
-
-#define ohci_hcd_init init_module
-
-#endif
-
#define PCI_CLASS_SERIAL_USB_OHCI 0x0C0310
#define PCI_CLASS_SERIAL_USB_OHCI_PG 0x10
@@ -1471,3 +1500,17 @@
}
return retval;
}
+
+#ifdef MODULE
+int init_module(void){
+ return ohci_hcd_init();
+}
+
+void cleanup_module(void)
+{
+# ifdef CONFIG_APM
+ apm_unregister_callback(&handle_apm_event);
+# endif
+}
+#endif //MODULE
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)