nicstar.c

来自「linux 内核源代码」· C语言 代码 · 共 2,241 行 · 第 1/5 页

C
2,241
字号
   sram_address &= 0x0007FFFC;   sram_address |= (0x40000000 | count);   writel(sram_address, card->membase + CMD);   spin_unlock_irqrestore(&card->res_lock, flags);}static int __devinit ns_init_card(int i, struct pci_dev *pcidev){   int j;   struct ns_dev *card = NULL;   unsigned char pci_latency;   unsigned error;   u32 data;   u32 u32d[4];   u32 ns_cfg_rctsize;   int bcount;   unsigned long membase;   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);         pci_set_drvdata(pcidev, card);      card->index = i;   card->atmdev = NULL;   card->pcidev = pcidev;   membase = pci_resource_start(pcidev, 1);   card->membase = ioremap(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);   pci_set_master(pcidev);   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);   /* 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 = NULL;   card->scq2 = NULL;   card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0);   if (card->scq0 == 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 = __dev_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;      }      NS_SKB_CB(hb)->buf_type = BUF_NONE;      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 = __dev_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;      }      NS_SKB_CB(lb)->buf_type = BUF_LG;      skb_queue_tail(&card->lbpool.queue, lb);      skb_reserve(lb, NS_SMBUFSIZE);      push_rxbufs(card, lb);      /* 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 = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);      if (sb == NULL)      {         printk("nicstar%d: can't allocate %dth of %d small buffers.\n",                i, j, NUM_SB);         error = 15;         ns_init_card_error(card, error);	 return error;      }      NS_SKB_CB(sb)->buf_type = BUF_SM;      skb_queue_tail(&card->sbpool.queue, sb);      skb_reserve(sb, NS_AAL0_HEADER);      push_rxbufs(card, sb);   }   /* Test for strange behaviour which leads to crashes */   if ((bcount = ns_stat_sfbqc_get(readl(card->membase + STAT))) < card->sbnr.min)   {      printk("nicstar%d: Strange... Just allocated %d small buffers and sfbqc = %d.\n",             i, j, bcount);      error = 15;      ns_init_card_error(card, error);      return error;   }         /* Allocate iovec buffers */   skb_queue_head_init(&card->iovpool.queue);   card->iovpool.count = 0;   for (j = 0; j < NUM_IOVB; j++)   {      struct sk_buff *iovb;      iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL);      if (iovb == NULL)      {         printk("nicstar%d: can't allocate %dth of %d iovec buffers.\n",                i, j, NUM_IOVB);         error = 16;         ns_init_card_error(card, error);	 return error;      }      NS_SKB_CB(iovb)->buf_type = BUF_NONE;      skb_queue_tail(&card->iovpool.queue, iovb);      card->iovpool.count++;   }   /* Configure NICStAR */   if (card->rct_size == 4096)      ns_cfg_rctsize = NS_CFG_RCTSIZE_4096_ENTRIES;   else /* (card->rct_size == 16384) */      ns_cfg_rctsize = NS_CFG_RCTSIZE_16384_ENTRIES;   card->efbie = 1;   card->intcnt = 0;   if (request_irq(pcidev->irq, &ns_irq_handler, IRQF_DISABLED | IRQF_SHARED, "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;   }   /* Register device */   card->atmdev = atm_dev_register("nicstar", &atm_ops, -1, NULL);   if (card->atmdev == NULL)   {      printk("nicstar%d: can't register device.\n", i);      error = 17;      ns_init_card_error(card, error);      return error;   }         if (ns_parse_mac(mac[i], card->atmdev->esi)) {      nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET,                         card->atmdev->esi, 6);      if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) == 0) {         nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT,                         card->atmdev->esi, 6);      }   }   printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i,          card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2],          card->atmdev->esi[3], card->atmdev->esi[4], card->atmdev->esi[5]);   card->atmdev->dev_data = card;   card->atmdev->ci_range.vpi_bits = card->vpibits;   card->atmdev->ci_range.vci_bits = card->vcibits;   card->atmdev->link_rate = card->max_pcr;   card->atmdev->phy = NULL;

⌨️ 快捷键说明

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