📄 dgrs.c
字号:
(uchar) (dev0->mem_start >> 16) ); priv0->is_reg = ES4H_IS_LINEAR | is | ((uchar) (dev0->mem_start >> 8) & ES4H_IS_AS15); OUTB(dev0->base_addr + ES4H_IS, priv0->is_reg); OUTB(dev0->base_addr + ES4H_EC, ES4H_EC_ENABLE); OUTB(dev0->base_addr + ES4H_PC, ES4H_PC_RESET); OUTB(dev0->base_addr + ES4H_MW, ES4H_MW_ENABLE | 0x00); } /* * See if we can do DMA on the SE-6 */ priv0->use_dma = check_board_dma(dev0); if (priv0->use_dma) printk("%s: Bus Master DMA is enabled.\n", dev0->name); /* * Load and verify the code at the desired address */ memcpy(priv0->vmem, dgrs_code, dgrs_ncode); /* Load code */ if (memcmp(priv0->vmem, dgrs_code, dgrs_ncode)) { iounmap(priv0->vmem); priv0->vmem = NULL; printk("%s: download compare failed\n", dev0->name); return -ENXIO; } /* * Configurables */ priv0->bcomm = (struct bios_comm *) (priv0->vmem + 0x0100); priv0->bcomm->bc_nowait = 1; /* Tell board to make printf not wait */ priv0->bcomm->bc_squelch = 0; /* Flag from Space.c */ priv0->bcomm->bc_150ohm = 0; /* Flag from Space.c */ priv0->bcomm->bc_spew = 0; /* Debug flag from Space.c */ priv0->bcomm->bc_maxrfd = 0; /* Debug flag from Space.c */ priv0->bcomm->bc_maxrbd = 0; /* Debug flag from Space.c */ /* * Tell board we are operating in switch mode (1) or in * multi-NIC mode (2). */ priv0->bcomm->bc_host = dgrs_nicmode ? BC_MULTINIC : BC_SWITCH; /* * Request memory space on board for DMA chains */ if (priv0->use_dma) priv0->bcomm->bc_hostarea_len = (2048/64) * 16; /* * 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); ) { barrier(); /* Gcc 2.95 needs this */ 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 */int __init dgrs_probe1(struct net_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, SA_SHIRQ, "RightSwitch", dev); if (rc) return (rc); priv->intrcnt = 0; for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); ) { barrier(); /* gcc 2.95 needs this */ 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);}int __init dgrs_initclone(struct net_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);}static int __init dgrs_found_device( int io, ulong mem, int irq, ulong plxreg, ulong plxdma){ DGRS_PRIV *priv; struct net_device *dev, *aux; /* Allocate and fill new device structure. */ int dev_size = sizeof(struct net_device) + sizeof(DGRS_PRIV); int i, ret; dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL); if (!dev) return -ENOMEM; memset(dev, 0, dev_size); dev->priv = ((void *)dev) + sizeof(struct net_device); priv = (DGRS_PRIV *)dev->priv; 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; SET_MODULE_OWNER(dev); ether_setup(dev); if (register_netdev(dev) != 0) return -EIO; priv->next_dev = dgrs_root_dev; dgrs_root_dev = dev; 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 net_device *devN; DGRS_PRIV *privN; /* Allocate new dev and priv structures */ devN = (struct net_device *) kmalloc(dev_size, GFP_KERNEL); /* Make it an exact copy of dev[0]... */ ret = -ENOMEM; if (!devN) goto fail; memcpy(devN, dev, dev_size); memset(devN->name, 0, sizeof(devN->name)); devN->priv = ((void *)devN) + sizeof(struct net_device); privN = (DGRS_PRIV *)devN->priv; /* ... 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; devN->init = dgrs_initclone; SET_MODULE_OWNER(devN); ether_setup(devN); ret = -EIO; if (register_netdev(devN)) { kfree(devN); goto fail; } privN->chan = i+1; priv->devtbl[i] = devN; privN->next_dev = dgrs_root_dev; dgrs_root_dev = devN; } return 0;fail: aux = priv->next_dev; while (dgrs_root_dev != aux) { struct net_device *d = dgrs_root_dev; dgrs_root_dev = ((DGRS_PRIV *)d->priv)->next_dev; unregister_netdev(d); kfree(d); } return ret;}/* * Scan for all boards */static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };static int __init dgrs_scan(void){ int cards_found = 0; uint io; uint mem; uint irq; uint plxreg; uint plxdma; /* * First, check for PCI boards */ if (pci_present()) { struct pci_dev *pdev = NULL; while ((pdev = pci_find_device(SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, pdev)) != NULL) { /* * 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. */ if (pci_enable_device(pdev)) continue; pci_set_master(pdev); plxreg = pci_resource_start (pdev, 0); io = pci_resource_start (pdev, 1); mem = pci_resource_start (pdev, 2); pci_read_config_dword(pdev, 0x30, &plxdma); irq = pdev->irq; 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); pci_write_config_dword(pdev, 0x30, plxdma + 1); pci_read_config_dword(pdev, 0x30, &plxdma); plxdma &= ~15; dgrs_found_device(io, mem, irq, plxreg, plxdma); 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(io, mem, irq, 0L, 0L); ++cards_found; } } return cards_found;}/* * Variables that can be overriden from module 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");MODULE_PARM_DESC(debug, "Digi RightSwitch enable debugging (0-1)");MODULE_PARM_DESC(dma, "Digi RightSwitch enable BM DMA (0-1)");MODULE_PARM_DESC(nicmode, "Digi RightSwitch operating mode (1: switch, 2: multi-NIC)");static int __init dgrs_init_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(KERN_INFO "dgrs: SW=%s FW=Build %d %s\nFW Version=%s\n", version, dgrs_firmnum, dgrs_firmdate, dgrs_firmver); } /* * Find and configure all the cards */ dgrs_root_dev = NULL; cards_found = dgrs_scan(); return cards_found ? 0 : -ENODEV;}static void __exit dgrs_cleanup_module (void){ while (dgrs_root_dev) { struct net_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; }}module_init(dgrs_init_module);module_exit(dgrs_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -