📄 init.c
字号:
#include "usblink.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v5.3"
#define DRIVER_AUTHOR "Roman Weissgaerber <weissg@vienna.at>, David Brownell"
#define DRIVER_DESC "USB OHCI Host Controller Driver"
typedef struct _UsblinkOtg
{
U32 driverObject;
U32 ohciIntr;
SctBool ohciDriverInitialized;
SctBool ohciInterruptPending;
void *ohci;
U32 intr;
char *name;
} UsblinkOtg;
static UsblinkOtg otg = {0, 0, SCC_FALSE, SCC_FALSE, 0};
static struct pci_driver ohci_pci_driver;
extern int __devinit hc_found_ohci (struct pci_dev *dev, int irq,
void *mem_base, const struct pci_device_id *id);
extern void __devexit ohci_pci_remove (struct pci_dev *dev);
extern void hc_interrupt (int irq, void * __ohci, struct pt_regs * r);
extern int ohci_pci_suspend (struct pci_dev *dev, u32 state);
extern int ohci_pci_resume (struct pci_dev *dev);
#ifdef OTG_16_BIT_DATA_BUS
//some tricks here, addr + offset is working because addr
//is declared as U8, sigh...
U32 HW_ReadOtg242Register(volatile U8* addr, U32 offset)
{
volatile U16 *Address;
U32 value;
Address = (U16 *)(addr + offset);
value = (U32)(*Address++) & 0xFFFF;
value |= (*Address & 0xFFFF) << 16;
return value;
}
void HW_WriteOtg242Register(volatile U8* addr, U32 offset, U32 val)
{
volatile U16 *Address;
//write the lower 16bits of val
Address = (U16 *)(addr + offset);
*Address = val &0xFFFF;
//write the higher 16bits of val
Address++;
*Address = (val>>16) & 0xFFFF;
}
U16 HW_ReadOtg242Register16(volatile U16* addr, U32 offset)
{
volatile U16 *Address;
U16 value;
Address = (U16 *)((U32)addr + offset);
value = (U16)((*Address) & 0xFFFF);
return value;
}
void HW_WriteOtg242Register16(volatile U16* addr, U32 offset, U16 val)
{
volatile U16 *Address;
Address = (U16 *)((U32)addr + offset);
*Address = val;
}
#endif
static int __devinit
otg242_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
{
unsigned long mem_resource, mem_len;
void *mem_base;
int status;
SctBool rc;
info("probe: dev=%p\n", dev);
if (pci_enable_device(dev) < 0)
return -ENODEV;
if (!dev->irq) {
err("found OHCI device with no IRQ assigned. check BIOS settings!");
pci_disable_device (dev);
return -ENODEV;
}
/* we read its hardware registers as memory */
mem_resource = pci_resource_start(dev, 3);
mem_len = pci_resource_len(dev, 3);
info("mem=%lx len=%lx", mem_resource, mem_len);
if (!request_mem_region (mem_resource, mem_len, ohci_pci_driver.name)) {
dbg ("controller already in use");
pci_disable_device (dev);
return -EBUSY;
}
if (otg.driverObject != 0)
{
dbg ("controller already in use");
pci_disable_device (dev);
return -EBUSY;
}
mem_base = ioremap_nocache (mem_resource, mem_len);
if (!mem_base) {
err("Error mapping OHCI memory");
release_mem_region (mem_resource, mem_len);
pci_disable_device (dev);
return -EFAULT;
}
otg.intr = dev->irq;
otg.driverObject = OTG242_Create(mem_base, otg.intr, (U32)(&otg));
if (otg.driverObject == 0)
{
err("Failed to create otg242");
release_mem_region (mem_resource, mem_len);
pci_disable_device (dev);
return -EFAULT;
}
rc = OTG242_Initialize(otg.driverObject);
if (rc != SCS_SUCCESS)
{
err("Failed to initialize otg242");
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
release_mem_region (mem_resource, mem_len);
pci_disable_device (dev);
return -EFAULT;
}
rc = OTG242_Start(otg.driverObject);
if (rc != SCS_SUCCESS)
{
err("Failed to start otg242");
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
release_mem_region (mem_resource, mem_len);
pci_disable_device (dev);
return -EFAULT;
}
otg.ohciIntr = 0xff;
/* controller writes into our memory */
pci_set_master (dev);
status = hc_found_ohci (dev, otg.ohciIntr, OTG242_GetOHCIRegisterBase(otg.driverObject), id);
if (status < 0)
{
err("Failed to start ohci driver");
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
iounmap (mem_base);
release_mem_region (mem_resource, mem_len);
pci_disable_device (dev);
return -EFAULT;
}
info(" **OTG242** Start successful, baseAddress %p!", mem_base);
otg.ohci = pci_get_drvdata(dev);
otg.ohciDriverInitialized = SCC_TRUE;
if (otg.ohciInterruptPending == SCC_TRUE)
{
otg.ohciInterruptPending = SCC_FALSE;
TriggerOhciInterrupt((U32)(&otg));
}
return status;
}
/*-------------------------------------------------------------------------*/
/* may be called from interrupt context [interface spec] */
/* may be called without controller present */
/* may be called with controller, bus, and devices active */
static void __devexit
otg242_pci_remove (struct pci_dev *dev)
{
ohci_pci_remove(dev);
info("Removing otg242 driver");
OTG242_Delete(otg.driverObject);
otg.driverObject = 0;
release_mem_region (pci_resource_start (dev, 0), pci_resource_len (dev, 0));
pci_disable_device (dev);
}
void TriggerOhciInterrupt(U32 context)
{
if (otg.ohciDriverInitialized == SCC_FALSE)
{
otg.ohciInterruptPending = SCC_TRUE;
return;
}
hc_interrupt(otg.ohciIntr, otg.ohci, NULL);
}
#ifdef CONFIG_PM
static int
otg242_pci_suspend(struct pci_dev *dev, u32 state)
{
ohci_pci_suspend(dev, state);
}
static int
otg242_pci_resume(struct pci_dev *dev)
{
ohci_pci_resume(dev);
}
#endif /* PM */
/*-------------------------------------------------------------------------*/
static const struct pci_device_id __devinitdata ohci_pci_ids [] = {
{
/* handle any USB OHCI controller */
class: ((PCI_CLASS_BRIDGE_OTHER << 8) | 0x10),
class_mask: ~0xFF,
/* no matter who makes it */
vendor: 0x10B5,
device: 0x9030,
subvendor: PCI_ANY_ID,
subdevice: PCI_ANY_ID,
}, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, ohci_pci_ids);
static struct pci_driver ohci_pci_driver = {
name: "otg242",
id_table: &ohci_pci_ids [0],
probe: otg242_pci_probe,
remove: __devexit_p(otg242_pci_remove),
#ifdef CONFIG_PM
suspend: otg242_pci_suspend,
resume: otg242_pci_resume,
#endif /* PM */
};
/*-------------------------------------------------------------------------*/
static int __init otg242_hcd_init (void)
{
int rc;
otg.driverObject = 0;
otg.ohciIntr = 0;
otg.ohciDriverInitialized = SCC_FALSE;
otg.ohciInterruptPending = SCC_FALSE;
otg.ohci = 0;
rc = pci_module_init (&ohci_pci_driver);
return rc;
}
/*-------------------------------------------------------------------------*/
static void __exit otg242_hcd_cleanup (void)
{
pci_unregister_driver (&ohci_pci_driver);
}
module_init (otg242_hcd_init);
module_exit (otg242_hcd_cleanup);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -