1,396 → 1,396 |
/* |
* OHCI HCD (Host Controller Driver) for USB. |
* |
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
* |
* [ Initialisation is based on Linus' ] |
* [ uhci code and gregs ohci fragments ] |
* [ (C) Copyright 1999 Linus Torvalds ] |
* [ (C) Copyright 1999 Gregory P. Smith] |
* |
* PCI Bus Glue |
* |
* This file is licenced under the GPL. |
*/ |
|
#ifdef CONFIG_PMAC_PBOOK |
#include <asm/machdep.h> |
#include <asm/pmac_feature.h> |
#include <asm/pci-bridge.h> |
#include <asm/prom.h> |
#ifndef CONFIG_PM |
# define CONFIG_PM |
#endif |
#endif |
|
#ifndef CONFIG_PCI |
#error "This file is PCI bus glue. CONFIG_PCI must be defined." |
#endif |
|
/*-------------------------------------------------------------------------*/ |
|
static int |
ohci_pci_reset (struct usb_hcd *hcd) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
|
ohci->regs = hcd->regs; |
return hc_reset (ohci); |
} |
|
static int __devinit |
ohci_pci_start (struct usb_hcd *hcd) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
int ret; |
|
if (hcd->pdev) { |
ohci->hcca = pci_alloc_consistent (hcd->pdev, |
sizeof *ohci->hcca, &ohci->hcca_dma); |
|
if (!ohci->hcca) |
return -ENOMEM; |
|
/* AMD 756, for most chips (early revs), corrupts register |
* values on read ... so enable the vendor workaround. |
*/ |
if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD |
&& hcd->pdev->device == 0x740c) { |
ohci->flags = OHCI_QUIRK_AMD756; |
ohci_info (ohci, "AMD756 erratum 4 workaround\n"); |
} |
|
/* FIXME for some of the early AMD 760 southbridges, OHCI |
* won't work at all. blacklist them. |
*/ |
|
/* Apple's OHCI driver has a lot of bizarre workarounds |
* for this chip. Evidently control and bulk lists |
* can get confused. (B&W G3 models, and ...) |
*/ |
else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI |
&& hcd->pdev->device == 0xc861) { |
ohci_info (ohci, |
"WARNING: OPTi workarounds unavailable\n"); |
} |
|
/* Check for NSC87560. We have to look at the bridge (fn1) to |
* identify the USB (fn2). This quirk might apply to more or |
* even all NSC stuff. |
*/ |
else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) { |
struct pci_dev *b, *hc; |
|
hc = hcd->pdev; |
b = pci_find_slot (hc->bus->number, |
PCI_DEVFN (PCI_SLOT (hc->devfn), 1)); |
if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO |
&& b->vendor == PCI_VENDOR_ID_NS) { |
ohci->flags |= OHCI_QUIRK_SUPERIO; |
ohci_info (ohci, "Using NSC SuperIO setup\n"); |
} |
} |
|
} |
|
memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); |
if ((ret = ohci_mem_init (ohci)) < 0) { |
ohci_stop (hcd); |
return ret; |
} |
|
if (hc_start (ohci) < 0) { |
ohci_err (ohci, "can't start\n"); |
ohci_stop (hcd); |
return -EBUSY; |
} |
create_debug_files (ohci); |
|
#ifdef DEBUG |
ohci_dump (ohci, 1); |
#endif |
return 0; |
} |
|
#ifdef CONFIG_PM |
|
static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
u16 cmd; |
u32 tmp; |
|
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { |
ohci_dbg (ohci, "can't suspend (state is %s)\n", |
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); |
return -EIO; |
} |
|
/* act as if usb suspend can always be used */ |
ohci_dbg (ohci, "suspend to %d\n", state); |
|
/* First stop processing */ |
spin_lock_irq (&ohci->lock); |
ohci->hc_control &= |
~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); |
writel (ohci->hc_control, &ohci->regs->control); |
writel (OHCI_INTR_SF, &ohci->regs->intrstatus); |
(void) readl (&ohci->regs->intrstatus); |
spin_unlock_irq (&ohci->lock); |
|
/* Wait a frame or two */ |
mdelay (1); |
if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) |
mdelay (1); |
|
#ifdef CONFIG_PMAC_PBOOK |
if (_machine == _MACH_Pmac) |
disable_irq (hcd->pdev->irq); |
/* else, 2.4 assumes shared irqs -- don't disable */ |
#endif |
|
/* Enable remote wakeup */ |
writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, |
&ohci->regs->intrenable); |
|
/* Suspend chip and let things settle down a bit */ |
spin_lock_irq (&ohci->lock); |
ohci->hc_control = OHCI_USB_SUSPEND; |
writel (ohci->hc_control, &ohci->regs->control); |
(void) readl (&ohci->regs->control); |
spin_unlock_irq (&ohci->lock); |
|
set_current_state (TASK_UNINTERRUPTIBLE); |
schedule_timeout (HZ/2); |
|
tmp = readl (&ohci->regs->control) | OHCI_CTRL_HCFS; |
switch (tmp) { |
case OHCI_USB_RESET: |
case OHCI_USB_RESUME: |
case OHCI_USB_OPER: |
ohci_err (ohci, "can't suspend; hcfs %d\n", tmp); |
break; |
case OHCI_USB_SUSPEND: |
ohci_dbg (ohci, "suspended\n"); |
break; |
} |
|
/* In some rare situations, Apple's OHCI have happily trashed |
* memory during sleep. We disable its bus master bit during |
* suspend |
*/ |
pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); |
cmd &= ~PCI_COMMAND_MASTER; |
pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); |
#ifdef CONFIG_PMAC_PBOOK |
{ |
struct device_node *of_node; |
|
/* Disable USB PAD & cell clock */ |
of_node = pci_device_to_OF_node (hcd->pdev); |
if (of_node) |
pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); |
} |
#endif |
return 0; |
} |
|
|
static int ohci_pci_resume (struct usb_hcd *hcd) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
int temp; |
int retval = 0; |
|
#ifdef CONFIG_PMAC_PBOOK |
{ |
struct device_node *of_node; |
|
/* Re-enable USB PAD & cell clock */ |
of_node = pci_device_to_OF_node (hcd->pdev); |
if (of_node) |
pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); |
} |
#endif |
/* did we suspend, or were we powered off? */ |
ohci->hc_control = readl (&ohci->regs->control); |
temp = ohci->hc_control & OHCI_CTRL_HCFS; |
|
#ifdef DEBUG |
/* the registers may look crazy here */ |
ohci_dump_status (ohci, 0, 0); |
#endif |
|
/* Re-enable bus mastering */ |
pci_set_master (ohci->hcd.pdev); |
|
switch (temp) { |
|
case OHCI_USB_RESET: // lost power |
restart: |
ohci_info (ohci, "USB restart\n"); |
retval = hc_restart (ohci); |
break; |
|
case OHCI_USB_SUSPEND: // host wakeup |
case OHCI_USB_RESUME: // remote wakeup |
ohci_info (ohci, "USB continue from %s wakeup\n", |
(temp == OHCI_USB_SUSPEND) |
? "host" : "remote"); |
|
/* we "should" only need RESUME if we're SUSPENDed ... */ |
ohci->hc_control = OHCI_USB_RESUME; |
writel (ohci->hc_control, &ohci->regs->control); |
(void) readl (&ohci->regs->control); |
/* Some controllers (lucent) need extra-long delays */ |
mdelay (35); /* no schedule here ! */ |
|
temp = readl (&ohci->regs->control); |
temp = ohci->hc_control & OHCI_CTRL_HCFS; |
if (temp != OHCI_USB_RESUME) { |
ohci_err (ohci, "controller won't resume\n"); |
/* maybe we can reset */ |
goto restart; |
} |
|
/* Then re-enable operations */ |
writel (OHCI_USB_OPER, &ohci->regs->control); |
(void) readl (&ohci->regs->control); |
mdelay (3); |
|
spin_lock_irq (&ohci->lock); |
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; |
if (!ohci->ed_rm_list) { |
if (ohci->ed_controltail) |
ohci->hc_control |= OHCI_CTRL_CLE; |
if (ohci->ed_bulktail) |
ohci->hc_control |= OHCI_CTRL_BLE; |
} |
hcd->state = USB_STATE_RUNNING; |
writel (ohci->hc_control, &ohci->regs->control); |
|
/* trigger a start-frame interrupt (why?) */ |
writel (OHCI_INTR_SF, &ohci->regs->intrstatus); |
writel (OHCI_INTR_SF, &ohci->regs->intrenable); |
|
writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); |
(void) readl (&ohci->regs->intrdisable); |
spin_unlock_irq (&ohci->lock); |
|
#ifdef CONFIG_PMAC_PBOOK |
if (_machine == _MACH_Pmac) |
enable_irq (hcd->pdev->irq); |
#endif |
|
/* Check for a pending done list */ |
if (ohci->hcca->done_head) |
dl_done_list (ohci, dl_reverse_done_list (ohci), NULL); |
writel (OHCI_INTR_WDH, &ohci->regs->intrenable); |
|
/* assume there are TDs on the bulk and control lists */ |
writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); |
break; |
|
default: |
ohci_warn (ohci, "odd PCI resume\n"); |
} |
return retval; |
} |
|
#endif /* CONFIG_PM */ |
|
|
/*-------------------------------------------------------------------------*/ |
|
static const struct hc_driver ohci_pci_hc_driver = { |
.description = hcd_name, |
|
/* |
* generic hardware linkage |
*/ |
.irq = ohci_irq, |
.flags = HCD_MEMORY | HCD_USB11, |
|
/* |
* basic lifecycle operations |
*/ |
.reset = ohci_pci_reset, |
.start = ohci_pci_start, |
#ifdef CONFIG_PM |
.suspend = ohci_pci_suspend, |
.resume = ohci_pci_resume, |
#endif |
.stop = ohci_stop, |
|
/* |
* memory lifecycle (except per-request) |
*/ |
.hcd_alloc = ohci_hcd_alloc, |
.hcd_free = ohci_hcd_free, |
|
/* |
* managing i/o requests and associated device resources |
*/ |
.urb_enqueue = ohci_urb_enqueue, |
.urb_dequeue = ohci_urb_dequeue, |
.endpoint_disable = ohci_endpoint_disable, |
|
/* |
* scheduling support |
*/ |
.get_frame_number = ohci_get_frame, |
|
/* |
* root hub support |
*/ |
.hub_status_data = ohci_hub_status_data, |
.hub_control = ohci_hub_control, |
}; |
|
/*-------------------------------------------------------------------------*/ |
|
|
static const struct pci_device_id pci_ids [] = { { |
/* handle any USB OHCI controller */ |
PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0), |
.driver_data = (unsigned long) &ohci_pci_hc_driver, |
}, { /* end: all zeroes */ } |
}; |
MODULE_DEVICE_TABLE (pci, pci_ids); |
|
/* pci driver glue; this is a "new style" PCI driver module */ |
static struct pci_driver ohci_pci_driver = { |
.name = (char *) hcd_name, |
.id_table = pci_ids, |
|
.probe = usb_hcd_pci_probe, |
.remove = usb_hcd_pci_remove, |
|
#ifdef CONFIG_PM |
.suspend = usb_hcd_pci_suspend, |
.resume = usb_hcd_pci_resume, |
#endif |
}; |
|
|
/*static*/ int __init ohci_hcd_pci_init (void) |
{ |
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name); |
if (usb_disabled()) |
return -ENODEV; |
|
printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, |
sizeof (struct ed), sizeof (struct td)); |
//*** printk (KERN_DEBUG "File: %s @Line:%d\n", __FILE__, __LINE__); |
return pci_module_init (&ohci_pci_driver); |
} |
module_init (ohci_hcd_pci_init); |
|
/*-------------------------------------------------------------------------*/ |
|
/*static*/ void /*__exit*/ ohci_hcd_pci_cleanup (void) |
{ |
pci_unregister_driver (&ohci_pci_driver); |
} |
module_exit (ohci_hcd_pci_cleanup); |
/* |
* OHCI HCD (Host Controller Driver) for USB. |
* |
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
* |
* [ Initialisation is based on Linus' ] |
* [ uhci code and gregs ohci fragments ] |
* [ (C) Copyright 1999 Linus Torvalds ] |
* [ (C) Copyright 1999 Gregory P. Smith] |
* |
* PCI Bus Glue |
* |
* This file is licenced under the GPL. |
*/ |
|
#ifdef CONFIG_PMAC_PBOOK |
#include <asm/machdep.h> |
#include <asm/pmac_feature.h> |
#include <asm/pci-bridge.h> |
#include <asm/prom.h> |
#ifndef CONFIG_PM |
# define CONFIG_PM |
#endif |
#endif |
|
#ifndef CONFIG_PCI |
#error "This file is PCI bus glue. CONFIG_PCI must be defined." |
#endif |
|
/*-------------------------------------------------------------------------*/ |
|
static int |
ohci_pci_reset (struct usb_hcd *hcd) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
|
ohci->regs = hcd->regs; |
return hc_reset (ohci); |
} |
|
static int __devinit |
ohci_pci_start (struct usb_hcd *hcd) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
int ret; |
|
if (hcd->pdev) { |
ohci->hcca = pci_alloc_consistent_usb (hcd->pdev, |
sizeof *ohci->hcca, &ohci->hcca_dma); |
|
if (!ohci->hcca) |
return -ENOMEM; |
|
/* AMD 756, for most chips (early revs), corrupts register |
* values on read ... so enable the vendor workaround. |
*/ |
if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD |
&& hcd->pdev->device == 0x740c) { |
ohci->flags = OHCI_QUIRK_AMD756; |
ohci_info (ohci, "AMD756 erratum 4 workaround\n"); |
} |
|
/* FIXME for some of the early AMD 760 southbridges, OHCI |
* won't work at all. blacklist them. |
*/ |
|
/* Apple's OHCI driver has a lot of bizarre workarounds |
* for this chip. Evidently control and bulk lists |
* can get confused. (B&W G3 models, and ...) |
*/ |
else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI |
&& hcd->pdev->device == 0xc861) { |
ohci_info (ohci, |
"WARNING: OPTi workarounds unavailable\n"); |
} |
|
/* Check for NSC87560. We have to look at the bridge (fn1) to |
* identify the USB (fn2). This quirk might apply to more or |
* even all NSC stuff. |
*/ |
else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) { |
struct pci_dev *b, *hc; |
|
hc = hcd->pdev; |
b = pci_find_slot (hc->bus->number, |
PCI_DEVFN (PCI_SLOT (hc->devfn), 1)); |
if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO |
&& b->vendor == PCI_VENDOR_ID_NS) { |
ohci->flags |= OHCI_QUIRK_SUPERIO; |
ohci_info (ohci, "Using NSC SuperIO setup\n"); |
} |
} |
|
} |
|
memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); |
if ((ret = ohci_mem_init (ohci)) < 0) { |
ohci_stop (hcd); |
return ret; |
} |
|
if (hc_start (ohci) < 0) { |
ohci_err (ohci, "can't start\n"); |
ohci_stop (hcd); |
return -EBUSY; |
} |
create_debug_files (ohci); |
|
#ifdef DEBUG |
ohci_dump (ohci, 1); |
#endif |
return 0; |
} |
|
#ifdef CONFIG_PM |
|
static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
u16 cmd; |
u32 tmp; |
|
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { |
ohci_dbg (ohci, "can't suspend (state is %s)\n", |
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); |
return -EIO; |
} |
|
/* act as if usb suspend can always be used */ |
ohci_dbg (ohci, "suspend to %d\n", state); |
|
/* First stop processing */ |
spin_lock_irq (&ohci->lock); |
ohci->hc_control &= |
~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); |
writel (ohci->hc_control, &ohci->regs->control); |
writel (OHCI_INTR_SF, &ohci->regs->intrstatus); |
(void) readl (&ohci->regs->intrstatus); |
spin_unlock_irq (&ohci->lock); |
|
/* Wait a frame or two */ |
mdelay (1); |
if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) |
mdelay (1); |
|
#ifdef CONFIG_PMAC_PBOOK |
if (_machine == _MACH_Pmac) |
disable_irq (hcd->pdev->irq); |
/* else, 2.4 assumes shared irqs -- don't disable */ |
#endif |
|
/* Enable remote wakeup */ |
writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, |
&ohci->regs->intrenable); |
|
/* Suspend chip and let things settle down a bit */ |
spin_lock_irq (&ohci->lock); |
ohci->hc_control = OHCI_USB_SUSPEND; |
writel (ohci->hc_control, &ohci->regs->control); |
(void) readl (&ohci->regs->control); |
spin_unlock_irq (&ohci->lock); |
|
set_current_state (TASK_UNINTERRUPTIBLE); |
schedule_timeout (HZ/2); |
|
tmp = readl (&ohci->regs->control) | OHCI_CTRL_HCFS; |
switch (tmp) { |
case OHCI_USB_RESET: |
case OHCI_USB_RESUME: |
case OHCI_USB_OPER: |
ohci_err (ohci, "can't suspend; hcfs %d\n", tmp); |
break; |
case OHCI_USB_SUSPEND: |
ohci_dbg (ohci, "suspended\n"); |
break; |
} |
|
/* In some rare situations, Apple's OHCI have happily trashed |
* memory during sleep. We disable its bus master bit during |
* suspend |
*/ |
pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); |
cmd &= ~PCI_COMMAND_MASTER; |
pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); |
#ifdef CONFIG_PMAC_PBOOK |
{ |
struct device_node *of_node; |
|
/* Disable USB PAD & cell clock */ |
of_node = pci_device_to_OF_node (hcd->pdev); |
if (of_node) |
pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); |
} |
#endif |
return 0; |
} |
|
|
static int ohci_pci_resume (struct usb_hcd *hcd) |
{ |
struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
int temp; |
int retval = 0; |
|
#ifdef CONFIG_PMAC_PBOOK |
{ |
struct device_node *of_node; |
|
/* Re-enable USB PAD & cell clock */ |
of_node = pci_device_to_OF_node (hcd->pdev); |
if (of_node) |
pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); |
} |
#endif |
/* did we suspend, or were we powered off? */ |
ohci->hc_control = readl (&ohci->regs->control); |
temp = ohci->hc_control & OHCI_CTRL_HCFS; |
|
#ifdef DEBUG |
/* the registers may look crazy here */ |
ohci_dump_status (ohci, 0, 0); |
#endif |
|
/* Re-enable bus mastering */ |
pci_set_master (ohci->hcd.pdev); |
|
switch (temp) { |
|
case OHCI_USB_RESET: // lost power |
restart: |
ohci_info (ohci, "USB restart\n"); |
retval = hc_restart (ohci); |
break; |
|
case OHCI_USB_SUSPEND: // host wakeup |
case OHCI_USB_RESUME: // remote wakeup |
ohci_info (ohci, "USB continue from %s wakeup\n", |
(temp == OHCI_USB_SUSPEND) |
? "host" : "remote"); |
|
/* we "should" only need RESUME if we're SUSPENDed ... */ |
ohci->hc_control = OHCI_USB_RESUME; |
writel (ohci->hc_control, &ohci->regs->control); |
(void) readl (&ohci->regs->control); |
/* Some controllers (lucent) need extra-long delays */ |
mdelay (35); /* no schedule here ! */ |
|
temp = readl (&ohci->regs->control); |
temp = ohci->hc_control & OHCI_CTRL_HCFS; |
if (temp != OHCI_USB_RESUME) { |
ohci_err (ohci, "controller won't resume\n"); |
/* maybe we can reset */ |
goto restart; |
} |
|
/* Then re-enable operations */ |
writel (OHCI_USB_OPER, &ohci->regs->control); |
(void) readl (&ohci->regs->control); |
mdelay (3); |
|
spin_lock_irq (&ohci->lock); |
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; |
if (!ohci->ed_rm_list) { |
if (ohci->ed_controltail) |
ohci->hc_control |= OHCI_CTRL_CLE; |
if (ohci->ed_bulktail) |
ohci->hc_control |= OHCI_CTRL_BLE; |
} |
hcd->state = USB_STATE_RUNNING; |
writel (ohci->hc_control, &ohci->regs->control); |
|
/* trigger a start-frame interrupt (why?) */ |
writel (OHCI_INTR_SF, &ohci->regs->intrstatus); |
writel (OHCI_INTR_SF, &ohci->regs->intrenable); |
|
writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); |
(void) readl (&ohci->regs->intrdisable); |
spin_unlock_irq (&ohci->lock); |
|
#ifdef CONFIG_PMAC_PBOOK |
if (_machine == _MACH_Pmac) |
enable_irq (hcd->pdev->irq); |
#endif |
|
/* Check for a pending done list */ |
if (ohci->hcca->done_head) |
dl_done_list (ohci, dl_reverse_done_list (ohci), NULL); |
writel (OHCI_INTR_WDH, &ohci->regs->intrenable); |
|
/* assume there are TDs on the bulk and control lists */ |
writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); |
break; |
|
default: |
ohci_warn (ohci, "odd PCI resume\n"); |
} |
return retval; |
} |
|
#endif /* CONFIG_PM */ |
|
|
/*-------------------------------------------------------------------------*/ |
|
static const struct hc_driver ohci_pci_hc_driver = { |
.description = hcd_name, |
|
/* |
* generic hardware linkage |
*/ |
.irq = ohci_irq, |
.flags = HCD_MEMORY | HCD_USB11, |
|
/* |
* basic lifecycle operations |
*/ |
.reset = ohci_pci_reset, |
.start = ohci_pci_start, |
#ifdef CONFIG_PM |
.suspend = ohci_pci_suspend, |
.resume = ohci_pci_resume, |
#endif |
.stop = ohci_stop, |
|
/* |
* memory lifecycle (except per-request) |
*/ |
.hcd_alloc = ohci_hcd_alloc, |
.hcd_free = ohci_hcd_free, |
|
/* |
* managing i/o requests and associated device resources |
*/ |
.urb_enqueue = ohci_urb_enqueue, |
.urb_dequeue = ohci_urb_dequeue, |
.endpoint_disable = ohci_endpoint_disable, |
|
/* |
* scheduling support |
*/ |
.get_frame_number = ohci_get_frame, |
|
/* |
* root hub support |
*/ |
.hub_status_data = ohci_hub_status_data, |
.hub_control = ohci_hub_control, |
}; |
|
/*-------------------------------------------------------------------------*/ |
|
|
static const struct pci_device_id pci_ids [] = { { |
/* handle any USB OHCI controller */ |
PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0), |
.driver_data = (unsigned long) &ohci_pci_hc_driver, |
}, { /* end: all zeroes */ } |
}; |
MODULE_DEVICE_TABLE (pci, pci_ids); |
|
/* pci driver glue; this is a "new style" PCI driver module */ |
static struct pci_driver ohci_pci_driver = { |
.name = (char *) hcd_name, |
.id_table = pci_ids, |
|
.probe = usb_hcd_pci_probe, |
.remove = usb_hcd_pci_remove, |
|
#ifdef CONFIG_PM |
.suspend = usb_hcd_pci_suspend, |
.resume = usb_hcd_pci_resume, |
#endif |
}; |
|
|
/*static*/ int __init ohci_hcd_pci_init (void) |
{ |
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name); |
if (usb_disabled()) |
return -ENODEV; |
|
printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, |
sizeof (struct ed), sizeof (struct td)); |
//*** printk (KERN_DEBUG "File: %s @Line:%d\n", __FILE__, __LINE__); |
return pci_module_init (&ohci_pci_driver); |
} |
module_init (ohci_hcd_pci_init); |
|
/*-------------------------------------------------------------------------*/ |
|
/*static*/ void /*__exit*/ ohci_hcd_pci_cleanup (void) |
{ |
pci_unregister_driver (&ohci_pci_driver); |
} |
module_exit (ohci_hcd_pci_cleanup); |