superio.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 597 行 · 第 1/2 页

C
597
字号
superio_enable_irq(void *dev, int local_irq){	u8 r8;	if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) {	    printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", local_irq);	    BUG();	    return;	}	/* Unmask interrupt */	r8 = inb(IC_PIC1+1);	r8 &= ~(1 << local_irq);	outb (r8,IC_PIC1+1);}static voidsuperio_mask_irq(void *dev, int local_irq){	BUG();}static voidsuperio_unmask_irq(void *dev, int local_irq){	BUG();}static struct irq_region_ops superio_irq_ops = {	.disable_irq =	superio_disable_irq,	.enable_irq =	superio_enable_irq,	.mask_irq =	superio_mask_irq,	.unmask_irq =	superio_unmask_irq};#ifdef DEBUG_SUPERIO_INITstatic unsigned short expected_device[3] = {	PCI_DEVICE_ID_NS_87415,	PCI_DEVICE_ID_NS_87560_LIO,	PCI_DEVICE_ID_NS_87560_USB};#endifint superio_fixup_irq(struct pci_dev *pcidev){	int local_irq;#ifdef DEBUG_SUPERIO_INIT	int fn;	fn = PCI_FUNC(pcidev->devfn);	/* Verify the function number matches the expected device id. */	if (expected_device[fn] != pcidev->device) {		BUG();		return -1;	}	printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %p\n",		pci_name(pcidev),		pcidev->vendor, pcidev->device,		__builtin_return_address(0));#endif	if (!sio_dev.irq_region) {		/* Allocate an irq region for SuperIO devices */		sio_dev.irq_region = alloc_irq_region(SUPERIO_NIRQS,						&superio_irq_ops,						"SuperIO", (void *) &sio_dev);		if (!sio_dev.irq_region) {			printk(KERN_WARNING "SuperIO: alloc_irq_region failed\n");			return -1;		}	}	/*	 * We don't allocate a SuperIO irq for the legacy IO function,	 * since it is a "bridge". Instead, we will allocate irq's for	 * each legacy device as they are initialized.	 */	switch(pcidev->device) {	case PCI_DEVICE_ID_NS_87415:		/* Function 0 */		local_irq = IDE_IRQ;		break;	case PCI_DEVICE_ID_NS_87560_LIO:	/* Function 1 */		sio_dev.lio_pdev = pcidev;	/* save for superio_init() */		return -1;	case PCI_DEVICE_ID_NS_87560_USB:	/* Function 2 */		sio_dev.usb_pdev = pcidev;	/* save for superio_init() */		local_irq = USB_IRQ;		break;	default:		local_irq = -1;		BUG();		break;	}	return(sio_dev.irq_region->data.irqbase + local_irq);}static struct uart_port serial[] = {	{		.iotype		= UPIO_PORT,		.line		= 0,		.type		= PORT_16550A,		.uartclk	= 115200*16,		.fifosize	= 16,	},	{		.iotype		= UPIO_PORT,		.line		= 1,		.type		= PORT_16550A,		.uartclk	= 115200*16,		.fifosize	= 16,	}};void __devinitsuperio_serial_init(void){#ifdef CONFIG_SERIAL_8250	int retval;#ifdef CONFIG_SERIAL_8250_CONSOLE	extern void serial8250_console_init(void); /* drivers/serial/8250.c */#endif                	if (!sio_dev.irq_region)		return; /* superio not present */	if (!serial) {		printk(KERN_WARNING "SuperIO: Could not get memory for serial struct.\n");		return;	}	serial[0].iobase = sio_dev.sp1_base;	serial[0].irq = sio_dev.irq_region->data.irqbase + SP1_IRQ;	retval = early_serial_setup(&serial[0]);	if (retval < 0) {		printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n");		return;	}#ifdef CONFIG_SERIAL_8250_CONSOLE	serial8250_console_init();#endif        	serial[1].iobase = sio_dev.sp2_base;	serial[1].irq = sio_dev.irq_region->data.irqbase + SP2_IRQ;	retval = early_serial_setup(&serial[1]);	if (retval < 0)		printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n");#endif /* CONFIG_SERIAL_8250 */}static void __devinitsuperio_parport_init(void){#ifdef CONFIG_PARPORT_PC	if (!parport_pc_probe_port(sio_dev.pp_base,			0 /*base_hi*/,			sio_dev.irq_region->data.irqbase + PAR_IRQ, 			PARPORT_DMA_NONE /* dma */,			NULL /*struct pci_dev* */) )		printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n");#endif	/* CONFIG_PARPORT_PC */}static u8 superio_ide_inb (unsigned long port);static unsigned long superio_ide_status[2];static unsigned long superio_ide_select[2];static unsigned long superio_ide_dma_status[2];void superio_fixup_pci(struct pci_dev *pdev){	u8 prog;	pdev->class |= 0x5;	pci_write_config_byte(pdev, PCI_CLASS_PROG, pdev->class);	pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);	printk("PCI: Enabled native mode for NS87415 (pif=0x%x)\n", prog);}DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);/* Because of a defect in Super I/O, all reads of the PCI DMA status  * registers, IDE status register and the IDE select register need to be  * retried */static u8 superio_ide_inb (unsigned long port){	if (port == superio_ide_status[0] ||	    port == superio_ide_status[1] ||	    port == superio_ide_select[0] ||	    port == superio_ide_select[1] ||	    port == superio_ide_dma_status[0] ||	    port == superio_ide_dma_status[1]) {		u8 tmp;		int retries = SUPERIO_IDE_MAX_RETRIES;		/* printk(" [ reading port 0x%x with retry ] ", port); */		do {			tmp = inb(port);			if (tmp == 0)				udelay(50);		} while (tmp == 0 && retries-- > 0);		return tmp;	}	return inb(port);}void __init superio_ide_init_iops (struct hwif_s *hwif){	u32 base, dmabase;	u8 tmp;	struct pci_dev *pdev = hwif->pci_dev;	u8 port = hwif->channel;	base = pci_resource_start(pdev, port * 2) & ~3;	dmabase = pci_resource_start(pdev, 4) & ~3;	superio_ide_status[port] = base + IDE_STATUS_OFFSET;	superio_ide_select[port] = base + IDE_SELECT_OFFSET;	superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);		/* Clear error/interrupt, enable dma */	tmp = superio_ide_inb(superio_ide_dma_status[port]);	outb(tmp | 0x66, superio_ide_dma_status[port]);	/* We need to override inb to workaround a SuperIO errata */	hwif->INB = superio_ide_inb;}static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id){	/*	** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a	** superio_probe(00:0e.1) ven 0x100b dev 0xe sv 0x0 sd 0x0 class 0x68000	** superio_probe(00:0e.2) ven 0x100b dev 0x12 sv 0x0 sd 0x0 class 0xc0310	*/	DBG_INIT("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n",		pci_name(dev),		dev->vendor, dev->device,		dev->subsystem_vendor, dev->subsystem_device,		dev->class);	superio_init(&sio_dev);	if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) {	/* Function 1 */		superio_parport_init();		superio_serial_init();		/* REVISIT XXX : superio_fdc_init() ? */		return 0;	} else if (dev->device == PCI_DEVICE_ID_NS_87415) {	/* Function 0 */		DBG_INIT("superio_probe: ignoring IDE 87415\n");	} else if (dev->device == PCI_DEVICE_ID_NS_87560_USB) {	/* Function 2 */		DBG_INIT("superio_probe: ignoring USB OHCI controller\n");	} else {		DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n");	}	/* Let appropriate other driver claim this device. */ 	return -ENODEV;}static struct pci_device_id superio_tbl[] = {	{ PCI_VENDOR_ID_NS, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ 0, }};static struct pci_driver superio_driver = {	.name =		"SuperIO",	.id_table =	superio_tbl,	.probe =	superio_probe,};static int __init superio_modinit(void){	return pci_module_init(&superio_driver);}static void __exit superio_exit(void){	pci_unregister_driver(&superio_driver);}module_init(superio_modinit);module_exit(superio_exit);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?