📄 rio_linux.c
字号:
void *p; p = kmalloc(size, GFP_KERNEL); if (p) memset(p, 0, size); return p;}static int rio_init_datastructures (void){ int i; struct Port *port; func_enter(); /* Many drivers statically allocate the maximum number of ports There is no reason not to allocate them dynamically. Is there? -- REW */ /* However, the RIO driver allows users to configure their first RTA as the ports numbered 504-511. We therefore need to allocate the whole range. :-( -- REW */ #define RI_SZ sizeof(struct rio_info)#define HOST_SZ sizeof(struct Host)#define PORT_SZ sizeof(struct Port *)#define TMIO_SZ sizeof(struct termios *) rio_dprintk (RIO_DEBUG_INIT, "getting : %d %d %d %d %d bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ); if (!(p = ckmalloc ( RI_SZ))) goto free0; if (!(p->RIOHosts = ckmalloc (RIO_HOSTS * HOST_SZ))) goto free1; if (!(p->RIOPortp = ckmalloc (RIO_PORTS * PORT_SZ))) goto free2; p->RIOConf = RIOConf; rio_dprintk (RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);#if 1 for (i = 0; i < RIO_PORTS; i++) { port = p->RIOPortp[i] = ckmalloc (sizeof (struct Port)); if (!port) { goto free6; } rio_dprintk (RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped); port->PortNum = i; port->gs.magic = RIO_MAGIC; port->gs.close_delay = HZ/2; port->gs.closing_wait = 30 * HZ; port->gs.rd = &rio_real_driver; spin_lock_init(&port->portSem); /* * Initializing wait queue */ init_waitqueue_head(&port->gs.open_wait); init_waitqueue_head(&port->gs.close_wait); }#else /* We could postpone initializing them to when they are configured. */#endif if (rio_debug & RIO_DEBUG_INIT) { my_hd (&rio_real_driver, sizeof (rio_real_driver)); } func_exit(); return 0; free6:for (i--;i>=0;i--) kfree (p->RIOPortp[i]);/*free5: free4: free3:*/kfree (p->RIOPortp); free2:kfree (p->RIOHosts); free1: rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp); kfree(p); free0: return -ENOMEM;}static void __exit rio_release_drivers(void){ func_enter(); tty_unregister_driver(rio_driver2); tty_unregister_driver(rio_driver); put_tty_driver(rio_driver2); put_tty_driver(rio_driver); func_exit();}#ifdef CONFIG_PCI /* This was written for SX, but applies to RIO too... (including bugs....) There is another bit besides Bit 17. Turning that bit off (on boards shipped with the fix in the eeprom) results in a hang on the next access to the card. */ /******************************************************** * Setting bit 17 in the CNTRL register of the PLX 9050 * * chip forces a retry on writes while a read is pending.* * This is to prevent the card locking up on Intel Xeon * * multiprocessor systems with the NX chipset. -- NV * ********************************************************//* Newer cards are produced with this bit set from the configuration EEprom. As the bit is read/write for the CPU, we can fix it here, if we detect that it isn't set correctly. -- REW */static void fix_rio_pci (struct pci_dev *pdev){ unsigned int hwbase; unsigned long rebase; unsigned int t;#define CNTRL_REG_OFFSET 0x50#define CNTRL_REG_GOODVALUE 0x18260000 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); hwbase &= PCI_BASE_ADDRESS_MEM_MASK; rebase = (ulong) ioremap(hwbase, 0x80); t = readl (rebase + CNTRL_REG_OFFSET); if (t != CNTRL_REG_GOODVALUE) { printk (KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE); writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); } iounmap((char*) rebase);}#endifstatic int __init rio_init(void) { int found = 0; int i; struct Host *hp; int retval; struct vpd_prom *vpdp; int okboard;#ifdef CONFIG_PCI struct pci_dev *pdev = NULL; unsigned int tint; unsigned short tshort;#endif func_enter(); rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug); if (abs ((long) (&rio_debug) - rio_debug) < 0x10000) { printk (KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug); rio_debug=-1; } if (misc_register(&rio_fw_device) < 0) { printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n"); return -EIO; } retval = rio_init_datastructures (); if (retval < 0) { misc_deregister(&rio_fw_device); return retval; }#ifdef CONFIG_PCI /* First look for the JET devices: */ while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { if (pci_enable_device(pdev)) continue; /* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say its because the standard requires it. Stupid standard. */ /* It seems that reading a word doesn't work reliably on 2.0. Also, reading a non-aligned dword doesn't work. So we read the whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID) ourselves */ /* I don't know why the define doesn't work, constant 0x2c does --REW */ pci_read_config_dword (pdev, 0x2c, &tint); tshort = (tint >> 16) & 0xffff; rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); if (tshort != 0x0100) { rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort); continue; } rio_dprintk (RIO_DEBUG_PROBE, "cp1\n"); pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2, &tint); hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; hp->Mode = RIO_PCI_BOOT_FROM_RAM; spin_lock_init(&hp->HostLock); rio_reset_interrupt (hp); rio_start_card_running (hp); rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *)p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) { rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n"); WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); p->RIOHosts[p->RIONumHosts].UniqueNum = ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); fix_rio_pci (pdev); p->RIOLastPCISearch = RIO_SUCCESS; p->RIONumHosts++; found++; } else { iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); } } /* Then look for the older PCI card.... : */ /* These older PCI cards have problems (only byte-mode access is supported), which makes them a bit awkward to support. They also have problems sharing interrupts. Be careful. (The driver now refuses to share interrupts for these cards. This should be sufficient). */ /* Then look for the older RIO/PCI devices: */ while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) { if (pci_enable_device(pdev)) continue;#ifdef CONFIG_RIO_OLDPCI pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint); hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->Ivec |= 0x8000; /* Mark as non-sharable */ hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; hp->Mode = RIO_PCI_BOOT_FROM_RAM; spin_lock_init(&hp->HostLock); rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec); rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode); rio_reset_interrupt (hp); rio_start_card_running (hp); rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *)p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) { WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); p->RIOHosts[p->RIONumHosts].UniqueNum = ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); p->RIOLastPCISearch = RIO_SUCCESS; p->RIONumHosts++; found++; } else { iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); }#else printk (KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");#endif }#endif /* PCI */ /* Now probe for ISA cards... */ for (i=0;i<NR_RIO_ADDRS;i++) { hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = rio_probe_addrs[i]; /* There was something about the IRQs of these cards. 'Forget what.--REW */ hp->Ivec = 0; hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->CardP = (struct DpRam *) hp->Caddr; hp->Type = RIO_AT; hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL * -- YES! this is now a normal copy. Only the * old PCI card uses the special PCI copy. * Moreover, the ISA card will work with the * special PCI copy anyway. -- REW */ hp->Mode = 0; spin_lock_init(&hp->HostLock); vpdp = get_VPD_PROM (hp); rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n"); okboard = 0; if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp (vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) { /* Board is present... */ if (RIOBoardTest (hp->PaddrP, hp->Caddr, RIO_AT, 0) == RIO_SUCCESS) { /* ... and feeling fine!!!! */ rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) { rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts-1].UniqueNum); okboard++; found++; } } if (!okboard) iounmap ((char*) (hp->Caddr)); } } for (i=0;i<p->RIONumHosts;i++) { hp = &p->RIOHosts[i]; if (hp->Ivec) { int mode = SA_SHIRQ; if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;} rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode); retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp); rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval); if (retval) { printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); hp->Ivec = 0; } rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec); if (hp->Ivec != 0){ rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); hp->Mode |= RIO_PCI_INT_ENABLE; } else hp->Mode &= !RIO_PCI_INT_ENABLE; rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode); rio_start_card_running (hp); } /* Init the timer "always" to make sure that it can safely be deleted when we unload... */ init_timer (&hp->timer); if (!hp->Ivec) { rio_dprintk (RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll); hp->timer.data = i; hp->timer.function = rio_pollfunc; hp->timer.expires = jiffies + rio_poll; add_timer (&hp->timer); } } if (found) { rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found); rio_init_drivers (); } else { /* deregister the misc device we created earlier */ misc_deregister(&rio_fw_device); } func_exit(); return found?0:-EIO;}static void __exit rio_exit (void){ int i; struct Host *hp; func_enter(); for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) { RIOHostReset (hp->Type, hp->CardP, hp->Slot); if (hp->Ivec) { free_irq (hp->Ivec, hp); rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); } /* It is safe/allowed to del_timer a non-active timer */ del_timer (&hp->timer); } if (misc_deregister(&rio_fw_device) < 0) { printk (KERN_INFO "rio: couldn't deregister control-device\n"); } rio_dprintk (RIO_DEBUG_CLEANUP, "Cleaning up drivers\n"); rio_release_drivers (); /* Release dynamically allocated memory */ kfree (p->RIOPortp); kfree (p->RIOHosts); kfree (p); func_exit();}module_init(rio_init);module_exit(rio_exit);/* * Anybody who knows why this doesn't work for me, please tell me -- REW. * Snatched from scsi.c (fixed one spelling error): * Overrides for Emacs so that we follow Linus' tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local Variables: * c-indent-level: 4 * c-brace-imaginary-offset: 0 * c-brace-offset: -4 * c-argdecl-indent: 4 * c-label-offset: -4 * c-continued-statement-offset: 4 * c-continued-brace-offset: 0 * indent-tabs-mode: nil * tab-width: 8 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -