📄 nicstar.c
字号:
error = ns_init_card(i, pcidev); if (error) cards[i--] = NULL; /* Try to find another card but don't increment index */ } if (i == 0 && error) return -EIO; TXPRINTK("nicstar: TX debug enabled.\n"); RXPRINTK("nicstar: RX debug enabled.\n"); PRINTK("nicstar: General debug enabled.\n");#ifdef PHY_LOOPBACK printk("nicstar: using PHY loopback.\n");#endif /* PHY_LOOPBACK */ XPRINTK("nicstar: init_module() returned.\n"); init_timer(&ns_timer); ns_timer.expires = jiffies + NS_POLL_PERIOD; ns_timer.data = 0UL; ns_timer.function = ns_poll; add_timer(&ns_timer); return i;}#endif /* MODULE */static u32 ns_read_sram(ns_dev *card, u32 sram_address){ unsigned long flags; u32 data; sram_address <<= 2; sram_address &= 0x0007FFFC; /* address must be dword aligned */ sram_address |= 0x50000000; /* SRAM read command */ ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); writel(sram_address, card->membase + CMD); while (CMD_BUSY(card)); data = readl(card->membase + DR0); spin_unlock_irqrestore(&card->res_lock, flags); return data;} static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count){ unsigned long flags; int i, c; count--; /* count range now is 0..3 instead of 1..4 */ c = count; c <<= 2; /* to use increments of 4 */ ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); for (i = 0; i <= c; i += 4) writel(*(value++), card->membase + i); /* Note: DR# registers are the first 4 dwords in nicstar's memspace, so card->membase + DR0 == card->membase */ sram_address <<= 2; sram_address &= 0x0007FFFC; sram_address |= (0x40000000 | count); writel(sram_address, card->membase + CMD); spin_unlock_irqrestore(&card->res_lock, flags);}static int __init ns_init_card(int i, struct pci_dev *pcidev){ int j; struct ns_dev *card = NULL; unsigned short pci_command; unsigned char pci_latency; unsigned error; u32 data; u32 u32d[4]; u32 ns_cfg_rctsize; int bcount; error = 0; if (pci_enable_device(pcidev)) { printk("nicstar%d: can't enable PCI device\n", i); error = 2; ns_init_card_error(card, error); return error; } if ((card = kmalloc(sizeof(ns_dev), GFP_KERNEL)) == NULL) { printk("nicstar%d: can't allocate memory for device structure.\n", i); error = 2; ns_init_card_error(card, error); return error; } cards[i] = card; spin_lock_init(&card->int_lock); spin_lock_init(&card->res_lock); card->index = i; card->atmdev = NULL; card->pcidev = pcidev; card->membase = pci_resource_start(pcidev, 1);#ifdef __powerpc__ /* Compensate for different memory map between host CPU and PCI bus. Shouldn't we use a macro for this? */ card->membase += KERNELBASE;#endif /* __powerpc__ */ card->membase = (unsigned long) ioremap(card->membase, NS_IOREMAP_SIZE); if (card->membase == 0) { printk("nicstar%d: can't ioremap() membase.\n",i); error = 3; ns_init_card_error(card, error); return error; } PRINTK("nicstar%d: membase at 0x%x.\n", i, card->membase); if (pci_read_config_word(pcidev, PCI_COMMAND, &pci_command) != 0) { printk("nicstar%d: can't read PCI_COMMAND.\n", i); error = 4; ns_init_card_error(card, error); return error; } pci_command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); if (pci_write_config_word(pcidev, PCI_COMMAND, pci_command) != 0) { printk("nicstar%d: can't write PCI_COMMAND.\n", i); error = 5; ns_init_card_error(card, error); return error; } if (pci_read_config_byte(pcidev, PCI_LATENCY_TIMER, &pci_latency) != 0) { printk("nicstar%d: can't read PCI latency timer.\n", i); error = 6; ns_init_card_error(card, error); return error; }#ifdef NS_PCI_LATENCY if (pci_latency < NS_PCI_LATENCY) { PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i, NS_PCI_LATENCY); for (j = 1; j < 4; j++) { if (pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0) break; } if (j == 4) { printk("nicstar%d: can't set PCI latency timer to %d.\n", i, NS_PCI_LATENCY); error = 7; ns_init_card_error(card, error); return error; } }#endif /* NS_PCI_LATENCY */ /* Clear timer overflow */ data = readl(card->membase + STAT); if (data & NS_STAT_TMROF) writel(NS_STAT_TMROF, card->membase + STAT); /* Software reset */ writel(NS_CFG_SWRST, card->membase + CFG); NS_DELAY; writel(0x00000000, card->membase + CFG); /* PHY reset */ writel(0x00000008, card->membase + GP); NS_DELAY; writel(0x00000001, card->membase + GP); NS_DELAY; while (CMD_BUSY(card)); writel(NS_CMD_WRITE_UTILITY | 0x00000100, card->membase + CMD); /* Sync UTOPIA with SAR clock */ NS_DELAY; /* Detect PHY type */ while (CMD_BUSY(card)); writel(NS_CMD_READ_UTILITY | 0x00000200, card->membase + CMD); while (CMD_BUSY(card)); data = readl(card->membase + DR0); switch(data) { case 0x00000009: printk("nicstar%d: PHY seems to be 25 Mbps.\n", i); card->max_pcr = ATM_25_PCR; while(CMD_BUSY(card)); writel(0x00000008, card->membase + DR0); writel(NS_CMD_WRITE_UTILITY | 0x00000200, card->membase + CMD); /* Clear an eventual pending interrupt */ writel(NS_STAT_SFBQF, card->membase + STAT);#ifdef PHY_LOOPBACK while(CMD_BUSY(card)); writel(0x00000022, card->membase + DR0); writel(NS_CMD_WRITE_UTILITY | 0x00000202, card->membase + CMD);#endif /* PHY_LOOPBACK */ break; case 0x00000030: case 0x00000031: printk("nicstar%d: PHY seems to be 155 Mbps.\n", i); card->max_pcr = ATM_OC3_PCR;#ifdef PHY_LOOPBACK while(CMD_BUSY(card)); writel(0x00000002, card->membase + DR0); writel(NS_CMD_WRITE_UTILITY | 0x00000205, card->membase + CMD);#endif /* PHY_LOOPBACK */ break; default: printk("nicstar%d: unknown PHY type (0x%08X).\n", i, data); error = 8; ns_init_card_error(card, error); return error; } writel(0x00000000, card->membase + GP); /* Determine SRAM size */ data = 0x76543210; ns_write_sram(card, 0x1C003, &data, 1); data = 0x89ABCDEF; ns_write_sram(card, 0x14003, &data, 1); if (ns_read_sram(card, 0x14003) == 0x89ABCDEF && ns_read_sram(card, 0x1C003) == 0x76543210) card->sram_size = 128; else card->sram_size = 32; PRINTK("nicstar%d: %dK x 32bit SRAM size.\n", i, card->sram_size); card->rct_size = NS_MAX_RCTSIZE;#if (NS_MAX_RCTSIZE == 4096) if (card->sram_size == 128) printk("nicstar%d: limiting maximum VCI. See NS_MAX_RCTSIZE in nicstar.h\n", i);#elif (NS_MAX_RCTSIZE == 16384) if (card->sram_size == 32) { printk("nicstar%d: wasting memory. See NS_MAX_RCTSIZE in nicstar.h\n", i); card->rct_size = 4096; }#else#error NS_MAX_RCTSIZE must be either 4096 or 16384 in nicstar.c#endif card->vpibits = NS_VPIBITS; if (card->rct_size == 4096) card->vcibits = 12 - NS_VPIBITS; else /* card->rct_size == 16384 */ card->vcibits = 14 - NS_VPIBITS; /* Initialize the nicstar eeprom/eprom stuff, for the MAC addr */ if (mac[i] == NULL) nicstar_init_eprom(card->membase); if (request_irq(pcidev->irq, &ns_irq_handler, SA_INTERRUPT | SA_SHIRQ, "nicstar", card) != 0) { printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); error = 9; ns_init_card_error(card, error); return error; } /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ writel(0x00000000, card->membase + VPM); /* Initialize TSQ */ card->tsq.org = kmalloc(NS_TSQSIZE + NS_TSQ_ALIGNMENT, GFP_KERNEL); if (card->tsq.org == NULL) { printk("nicstar%d: can't allocate TSQ.\n", i); error = 10; ns_init_card_error(card, error); return error; } card->tsq.base = (ns_tsi *) ALIGN_ADDRESS(card->tsq.org, NS_TSQ_ALIGNMENT); card->tsq.next = card->tsq.base; card->tsq.last = card->tsq.base + (NS_TSQ_NUM_ENTRIES - 1); for (j = 0; j < NS_TSQ_NUM_ENTRIES; j++) ns_tsi_init(card->tsq.base + j); writel(0x00000000, card->membase + TSQH); writel((u32) virt_to_bus(card->tsq.base), card->membase + TSQB); PRINTK("nicstar%d: TSQ base at 0x%x 0x%x 0x%x.\n", i, (u32) card->tsq.base, (u32) virt_to_bus(card->tsq.base), readl(card->membase + TSQB)); /* Initialize RSQ */ card->rsq.org = kmalloc(NS_RSQSIZE + NS_RSQ_ALIGNMENT, GFP_KERNEL); if (card->rsq.org == NULL) { printk("nicstar%d: can't allocate RSQ.\n", i); error = 11; ns_init_card_error(card, error); return error; } card->rsq.base = (ns_rsqe *) ALIGN_ADDRESS(card->rsq.org, NS_RSQ_ALIGNMENT); card->rsq.next = card->rsq.base; card->rsq.last = card->rsq.base + (NS_RSQ_NUM_ENTRIES - 1); for (j = 0; j < NS_RSQ_NUM_ENTRIES; j++) ns_rsqe_init(card->rsq.base + j); writel(0x00000000, card->membase + RSQH); writel((u32) virt_to_bus(card->rsq.base), card->membase + RSQB); PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base); /* Initialize SCQ0, the only VBR SCQ used */ card->scq1 = (scq_info *) NULL; card->scq2 = (scq_info *) NULL; card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0); if (card->scq0 == (scq_info *) NULL) { printk("nicstar%d: can't get SCQ0.\n", i); error = 12; ns_init_card_error(card, error); return error; } u32d[0] = (u32) virt_to_bus(card->scq0->base); u32d[1] = (u32) 0x00000000; u32d[2] = (u32) 0xffffffff; u32d[3] = (u32) 0x00000000; ns_write_sram(card, NS_VRSCD0, u32d, 4); ns_write_sram(card, NS_VRSCD1, u32d, 4); /* These last two won't be used */ ns_write_sram(card, NS_VRSCD2, u32d, 4); /* but are initialized, just in case... */ card->scq0->scd = NS_VRSCD0; PRINTK("nicstar%d: VBR-SCQ0 base at 0x%x.\n", i, (u32) card->scq0->base); /* Initialize TSTs */ card->tst_addr = NS_TST0; card->tst_free_entries = NS_TST_NUM_ENTRIES; data = NS_TST_OPCODE_VARIABLE; for (j = 0; j < NS_TST_NUM_ENTRIES; j++) ns_write_sram(card, NS_TST0 + j, &data, 1); data = ns_tste_make(NS_TST_OPCODE_END, NS_TST0); ns_write_sram(card, NS_TST0 + NS_TST_NUM_ENTRIES, &data, 1); for (j = 0; j < NS_TST_NUM_ENTRIES; j++) ns_write_sram(card, NS_TST1 + j, &data, 1); data = ns_tste_make(NS_TST_OPCODE_END, NS_TST1); ns_write_sram(card, NS_TST1 + NS_TST_NUM_ENTRIES, &data, 1); for (j = 0; j < NS_TST_NUM_ENTRIES; j++) card->tste2vc[j] = NULL; writel(NS_TST0 << 2, card->membase + TSTB); /* Initialize RCT. AAL type is set on opening the VC. */#ifdef RCQ_SUPPORT u32d[0] = NS_RCTE_RAWCELLINTEN;#else u32d[0] = 0x00000000;#endif /* RCQ_SUPPORT */ u32d[1] = 0x00000000; u32d[2] = 0x00000000; u32d[3] = 0xFFFFFFFF; for (j = 0; j < card->rct_size; j++) ns_write_sram(card, j * 4, u32d, 4); memset(card->vcmap, 0, NS_MAX_RCTSIZE * sizeof(vc_map)); for (j = 0; j < NS_FRSCD_NUM; j++) card->scd2vc[j] = NULL; /* Initialize buffer levels */ card->sbnr.min = MIN_SB; card->sbnr.init = NUM_SB; card->sbnr.max = MAX_SB; card->lbnr.min = MIN_LB; card->lbnr.init = NUM_LB; card->lbnr.max = MAX_LB; card->iovnr.min = MIN_IOVB; card->iovnr.init = NUM_IOVB; card->iovnr.max = MAX_IOVB; card->hbnr.min = MIN_HB; card->hbnr.init = NUM_HB; card->hbnr.max = MAX_HB; card->sm_handle = 0x00000000; card->sm_addr = 0x00000000; card->lg_handle = 0x00000000; card->lg_addr = 0x00000000; card->efbie = 1; /* To prevent push_rxbufs from enabling the interrupt */ /* Pre-allocate some huge buffers */ skb_queue_head_init(&card->hbpool.queue); card->hbpool.count = 0; for (j = 0; j < NUM_HB; j++) { struct sk_buff *hb; hb = alloc_skb(NS_HBUFSIZE, GFP_KERNEL); if (hb == NULL) { printk("nicstar%d: can't allocate %dth of %d huge buffers.\n", i, j, NUM_HB); error = 13; ns_init_card_error(card, error); return error; } skb_queue_tail(&card->hbpool.queue, hb); card->hbpool.count++; } /* Allocate large buffers */ skb_queue_head_init(&card->lbpool.queue); card->lbpool.count = 0; /* Not used */ for (j = 0; j < NUM_LB; j++) { struct sk_buff *lb; lb = alloc_skb(NS_LGSKBSIZE, GFP_KERNEL); if (lb == NULL) { printk("nicstar%d: can't allocate %dth of %d large buffers.\n", i, j, NUM_LB); error = 14; ns_init_card_error(card, error); return error; } skb_queue_tail(&card->lbpool.queue, lb); skb_reserve(lb, NS_SMBUFSIZE); push_rxbufs(card, BUF_LG, (u32) lb, (u32) virt_to_bus(lb->data), 0, 0); /* Due to the implementation of push_rxbufs() this is 1, not 0 */ if (j == 1) { card->rcbuf = lb; card->rawch = (u32) virt_to_bus(lb->data); } } /* Test for strange behaviour which leads to crashes */ if ((bcount = ns_stat_lfbqc_get(readl(card->membase + STAT))) < card->lbnr.min) { printk("nicstar%d: Strange... Just allocated %d large buffers and lfbqc = %d.\n", i, j, bcount); error = 14; ns_init_card_error(card, error); return error; } /* Allocate small buffers */ skb_queue_head_init(&card->sbpool.queue); card->sbpool.count = 0; /* Not used */ for (j = 0; j < NUM_SB; j++) { struct sk_buff *sb; sb = alloc_skb(NS_SMSKBSIZE, GFP_KERNEL); if (sb == NULL) { printk("nicstar%d: can't allocate %dth of %d small buffers.\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -