📄 dgrs.c
字号:
/* * NVRAM configurables from Space.c */ priv0->bcomm->bc_spantree = dgrs_spantree; priv0->bcomm->bc_hashexpire = dgrs_hashexpire; memcpy(priv0->bcomm->bc_ipaddr, dgrs_ipaddr, 4); memcpy(priv0->bcomm->bc_iptrap, dgrs_iptrap, 4); memcpy(priv0->bcomm->bc_ipxnet, &dgrs_ipxnet, 4); /* * Release processor, wait 8 seconds for board to initialize */ proc_reset(dev0, 0); for (i = jiffies + 8 * HZ; time_after(i, jiffies); ) { if (priv0->bcomm->bc_status >= BC_RUN) break; } if (priv0->bcomm->bc_status < BC_RUN) { printk("%s: board not operating\n", dev0->name); return -ENXIO; } priv0->port = (PORT *) S2H(priv0->bcomm->bc_port); priv0->scbp = (I596_SCB *) S2H(priv0->port->scbp); priv0->rfdp = (I596_RFD *) S2H(priv0->scbp->rfdp); priv0->rbdp = (I596_RBD *) S2H(priv0->rfdp->rbdp); priv0->scbp->status = I596_SCB_CNA; /* CU is idle */ /* * Get switch physical and host virtual pointers to DMA * chaining area. NOTE: the MSB of the switch physical * address *must* be turned off. Otherwise, the HW kludge * that allows host access of the PLX DMA registers will * erroneously select the PLX registers. */ priv0->dmadesc_s = (DMACHAIN *) S2DMA(priv0->bcomm->bc_hostarea); if (priv0->dmadesc_s) priv0->dmadesc_h = (DMACHAIN *) S2H(priv0->dmadesc_s); else priv0->dmadesc_h = NULL; /* * Enable board interrupts */ if (priv0->plxreg) { /* PCI bus */ OUTL(dev0->base_addr + PLX_INT_CSR, inl(dev0->base_addr + PLX_INT_CSR) | PLX_PCI_DOORBELL_IE); /* Enable intr to host */ OUTL(dev0->base_addr + PLX_LCL2PCI_DOORBELL, 1); } else { /* EISA bus */ } return (0);}/* * Probe (init) a board */__initfunc(intdgrs_probe1(struct device *dev)){ DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv; int i; int rc; printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n", dev->name, dev->base_addr, dev->mem_start, dev->irq, priv->plxreg, priv->plxdma); /* * Download the firmware and light the processor */ rc = dgrs_download(dev); if (rc) { return rc; } /* * Get ether address of board */ printk("%s: Ethernet address", dev->name); memcpy(dev->dev_addr, priv->port->ethaddr, 6); for (i = 0; i < 6; ++i) printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); printk("\n"); if (dev->dev_addr[0] & 1) { printk("%s: Illegal Ethernet Address\n", dev->name); return (-ENXIO); } /* * ACK outstanding interrupts, hook the interrupt, * and verify that we are getting interrupts from the board. */ if (priv->plxreg) OUTL(dev->base_addr + PLX_LCL2PCI_DOORBELL, 1); rc = request_irq(dev->irq, &dgrs_intr, 0, "RightSwitch", dev); if (rc) return (rc); priv->intrcnt = 0; for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); ) if (priv->intrcnt >= 2) break; if (priv->intrcnt < 2) { printk("%s: Not interrupting on IRQ %d (%d)\n", dev->name, dev->irq, priv->intrcnt); return (-ENXIO); } /* * Register the /proc/ioports information... */ request_region(dev->base_addr, 256, "RightSwitch"); /* * Entry points... */ dev->open = &dgrs_open; dev->stop = &dgrs_close; dev->get_stats = &dgrs_get_stats; dev->hard_start_xmit = &dgrs_start_xmit; dev->set_multicast_list = &dgrs_set_multicast_list; dev->do_ioctl = &dgrs_ioctl; return (0);}__initfunc(intdgrs_initclone(struct device *dev)){ DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv; int i; printk("%s: Digi RightSwitch port %d ", dev->name, priv->chan); for (i = 0; i < 6; ++i) printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); printk("\n"); return (0);}__initfunc(static intdgrs_found_device( struct device *dev, int io, ulong mem, int irq, ulong plxreg, ulong plxdma)){ DGRS_PRIV *priv; #ifdef MODULE { /* Allocate and fill new device structure. */ int dev_size = sizeof(struct device) + sizeof(DGRS_PRIV); int i; dev = (struct device *) kmalloc(dev_size, GFP_KERNEL); memset(dev, 0, dev_size); dev->priv = ((void *)dev) + sizeof(struct device); priv = (DGRS_PRIV *)dev->priv; dev->name = priv->devname; /* An empty string. */ dev->base_addr = io; dev->mem_start = mem; dev->mem_end = mem + 2048 * 1024 - 1; dev->irq = irq; priv->plxreg = plxreg; priv->plxdma = plxdma; priv->vplxdma = NULL; priv->chan = 1; priv->devtbl[0] = dev; dev->init = dgrs_probe1; ether_setup(dev); priv->next_dev = dgrs_root_dev; dgrs_root_dev = dev; if (register_netdev(dev) != 0) return -EIO; if ( !dgrs_nicmode ) return (0); /* Switch mode, we are done */ /* * Operating card as N separate NICs */ priv->nports = priv->bcomm->bc_nports; for (i = 1; i < priv->nports; ++i) { struct device *devN; DGRS_PRIV *privN; /* Allocate new dev and priv structures */ devN = (struct device *) kmalloc(dev_size, GFP_KERNEL); /* Make it an exact copy of dev[0]... */ memcpy(devN, dev, dev_size); devN->priv = ((void *)devN) + sizeof(struct device); privN = (DGRS_PRIV *)devN->priv; /* ... but seset devname to a NULL string */ privN->devname[0] = 0; devN->name = privN->devname; /* ... and zero out VM areas */ privN->vmem = 0; privN->vplxdma = 0; /* ... and zero out IRQ */ devN->irq = 0; /* ... and base MAC address off address of 1st port */ devN->dev_addr[5] += i; privN->chan = i+1; priv->devtbl[i] = devN; devN->init = dgrs_initclone; ether_setup(devN); privN->next_dev = dgrs_root_dev; dgrs_root_dev = devN; if (register_netdev(devN) != 0) return -EIO; } } #else { if (dev) { dev->priv = kmalloc(sizeof (DGRS_PRIV), GFP_KERNEL); memset(dev->priv, 0, sizeof (DGRS_PRIV)); } dev = init_etherdev(dev, sizeof(DGRS_PRIV)); priv = (DGRS_PRIV *)dev->priv; dev->base_addr = io; dev->mem_start = mem; dev->mem_end = mem + 2048 * 1024; dev->irq = irq; priv->plxreg = plxreg; priv->plxdma = plxdma; priv->vplxdma = NULL; priv->chan = 1; priv->devtbl[0] = dev; dgrs_probe1(dev); } #endif return (0);}/* * Scan for all boards */static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };__initfunc(static intdgrs_scan(struct device *dev)){ int cards_found = 0; uint io; uint mem; uint irq; uint plxreg; uint plxdma; /* * First, check for PCI boards */ if (pci_present()) { int pci_index = 0; for (; pci_index < 8; pci_index++) { uchar pci_bus, pci_device_fn;#if LINUX_VERSION_CODE < 0x20100 uchar pci_irq;#else uint pci_irq; struct pci_dev *pdev;#endif uchar pci_latency; ushort pci_command; if (pcibios_find_device(SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, pci_index, &pci_bus, &pci_device_fn)) break;#if LINUX_VERSION_CODE < 0x20100 pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &plxreg); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &io); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &mem);#else pdev = pci_find_slot(pci_bus, pci_device_fn); pci_irq = pdev->irq; plxreg = pdev->base_address[0]; io = pdev->base_address[1]; mem = pdev->base_address[2];#endif pcibios_read_config_dword(pci_bus, pci_device_fn, 0x30, &plxdma); irq = pci_irq; plxreg &= ~15; io &= ~3; mem &= ~15; plxdma &= ~15; /* * On some BIOSES, the PLX "expansion rom" (used for DMA) * address comes up as "0". This is probably because * the BIOS doesn't see a valid 55 AA ROM signature at * the "ROM" start and zeroes the address. To get * around this problem the SE-6 is configured to ask * for 4 MB of space for the dual port memory. We then * must set its range back to 2 MB, and use the upper * half for DMA register access */ OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L); if (plxdma == 0) plxdma = mem + (2048L * 1024L); pcibios_write_config_dword(pci_bus, pci_device_fn, 0x30, plxdma + 1); pcibios_read_config_dword(pci_bus, pci_device_fn, 0x30, &plxdma); plxdma &= ~15; /* * Get and check the bus-master and latency values. * Some PCI BIOSes fail to set the master-enable bit, * and the latency timer must be set to the maximum * value to avoid data corruption that occurs when the * timer expires during a transfer. Yes, it's a bug. */ pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_command); if ( ! (pci_command & PCI_COMMAND_MASTER)) { printk(" Setting the PCI Master Bit!\n"); pci_command |= PCI_COMMAND_MASTER; pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, pci_command); } pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency != 255) { printk(" Overriding PCI latency timer: " "was %d, now is 255.\n", pci_latency); pcibios_write_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, 255); } dgrs_found_device(dev, io, mem, irq, plxreg, plxdma); dev = 0; cards_found++; } } /* * Second, check for EISA boards */ if (EISA_bus) { for (io = 0x1000; io < 0x9000; io += 0x1000) { if (inb(io+ES4H_MANUFmsb) != 0x10 || inb(io+ES4H_MANUFlsb) != 0x49 || inb(io+ES4H_PRODUCT) != ES4H_PRODUCT_CODE) continue; if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) ) continue; /* Not EISA configured */ mem = (inb(io+ES4H_AS_31_24) << 24) + (inb(io+ES4H_AS_23_16) << 16); irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ]; dgrs_found_device(dev, io, mem, irq, 0L, 0L); dev = 0; ++cards_found; } } return cards_found;}/* * Module/driver initialization points. Two ways, depending on * whether we are a module or statically linked, ala Don Becker's * 3c59x driver. */#ifdef MODULE/* * Variables that can be overriden from command line */static int debug = -1;static int dma = -1;static int hashexpire = -1;static int spantree = -1;static int ipaddr[4] = { -1 };static int iptrap[4] = { -1 };static __u32 ipxnet = -1;static int nicmode = -1;MODULE_PARM(debug, "i");MODULE_PARM(dma, "i");MODULE_PARM(hashexpire, "i");MODULE_PARM(spantree, "i");MODULE_PARM(ipaddr, "1-4i");MODULE_PARM(iptrap, "1-4i");MODULE_PARM(ipxnet, "i");MODULE_PARM(nicmode, "i");intinit_module(void){ int cards_found; int i; /* * Command line variable overrides * debug=NNN * dma=0/1 * spantree=0/1 * hashexpire=NNN * ipaddr=A,B,C,D * iptrap=A,B,C,D * ipxnet=NNN * nicmode=NNN */ if (debug >= 0) dgrs_debug = debug; if (dma >= 0) dgrs_dma = dma; if (nicmode >= 0) dgrs_nicmode = nicmode; if (hashexpire >= 0) dgrs_hashexpire = hashexpire; if (spantree >= 0) dgrs_spantree = spantree; if (ipaddr[0] != -1) for (i = 0; i < 4; ++i) dgrs_ipaddr[i] = ipaddr[i]; if (iptrap[0] != -1) for (i = 0; i < 4; ++i) dgrs_iptrap[i] = iptrap[i]; if (ipxnet != -1) dgrs_ipxnet = htonl( ipxnet ); if (dgrs_debug) { printk("dgrs: SW=%s FW=Build %d %s\n", version, dgrs_firmnum, dgrs_firmdate); } /* * Find and configure all the cards */ dgrs_root_dev = NULL; cards_found = dgrs_scan(0); return cards_found ? 0 : -ENODEV;}voidcleanup_module(void){ while (dgrs_root_dev) { struct device *next_dev; DGRS_PRIV *priv; priv = (DGRS_PRIV *) dgrs_root_dev->priv; next_dev = priv->next_dev; unregister_netdev(dgrs_root_dev); proc_reset(priv->devtbl[0], 1); if (priv->vmem) IOUNMAP(priv->vmem); if (priv->vplxdma) IOUNMAP((uchar *) priv->vplxdma); release_region(dgrs_root_dev->base_addr, 256); if (dgrs_root_dev->irq) free_irq(dgrs_root_dev->irq, dgrs_root_dev); kfree(dgrs_root_dev); dgrs_root_dev = next_dev; }}#else__initfunc(intdgrs_probe(struct device *dev)){ int cards_found; cards_found = dgrs_scan(dev); if (dgrs_debug && cards_found) printk("dgrs: SW=%s FW=Build %d %s\n", version, dgrs_firmnum, dgrs_firmdate); return cards_found ? 0 : -ENODEV;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -