📄 he.c
字号:
he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16)); he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); return 0;}static int __devinithe_init_irq(struct he_dev *he_dev){ int i; /* 2.9.3.5 tail offset for each interrupt queue is located after the end of the interrupt queue */ he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys); if (he_dev->irq_base == NULL) { hprintk("failed to allocate irq\n"); return -ENOMEM; } he_dev->irq_tailoffset = (unsigned *) &he_dev->irq_base[CONFIG_IRQ_SIZE]; *he_dev->irq_tailoffset = 0; he_dev->irq_head = he_dev->irq_base; he_dev->irq_tail = he_dev->irq_base; for (i = 0; i < CONFIG_IRQ_SIZE; ++i) he_dev->irq_base[i].isw = ITYPE_INVALID; he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE); he_writel(he_dev, IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH), IRQ0_HEAD); he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL); he_writel(he_dev, 0x0, IRQ0_DATA); he_writel(he_dev, 0x0, IRQ1_BASE); he_writel(he_dev, 0x0, IRQ1_HEAD); he_writel(he_dev, 0x0, IRQ1_CNTL); he_writel(he_dev, 0x0, IRQ1_DATA); he_writel(he_dev, 0x0, IRQ2_BASE); he_writel(he_dev, 0x0, IRQ2_HEAD); he_writel(he_dev, 0x0, IRQ2_CNTL); he_writel(he_dev, 0x0, IRQ2_DATA); he_writel(he_dev, 0x0, IRQ3_BASE); he_writel(he_dev, 0x0, IRQ3_HEAD); he_writel(he_dev, 0x0, IRQ3_CNTL); he_writel(he_dev, 0x0, IRQ3_DATA); /* 2.9.3.2 interrupt queue mapping registers */ he_writel(he_dev, 0x0, GRP_10_MAP); he_writel(he_dev, 0x0, GRP_32_MAP); he_writel(he_dev, 0x0, GRP_54_MAP); he_writel(he_dev, 0x0, GRP_76_MAP); if (request_irq(he_dev->pci_dev->irq, he_irq_handler, IRQF_DISABLED|IRQF_SHARED, DEV_LABEL, he_dev)) { hprintk("irq %d already in use\n", he_dev->pci_dev->irq); return -EINVAL; } he_dev->irq = he_dev->pci_dev->irq; return 0;}static int __devinithe_start(struct atm_dev *dev){ struct he_dev *he_dev; struct pci_dev *pci_dev; unsigned long membase; u16 command; u32 gen_cntl_0, host_cntl, lb_swap; u8 cache_size, timer; unsigned err; unsigned int status, reg; int i, group; he_dev = HE_DEV(dev); pci_dev = he_dev->pci_dev; membase = pci_resource_start(pci_dev, 0); HPRINTK("membase = 0x%lx irq = %d.\n", membase, pci_dev->irq); /* * pci bus controller initialization */ /* 4.3 pci bus controller-specific initialization */ if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0) { hprintk("can't read GEN_CNTL_0\n"); return -EINVAL; } gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT); if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0) { hprintk("can't write GEN_CNTL_0.\n"); return -EINVAL; } if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0) { hprintk("can't read PCI_COMMAND.\n"); return -EINVAL; } command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0) { hprintk("can't enable memory.\n"); return -EINVAL; } if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size)) { hprintk("can't read cache line size?\n"); return -EINVAL; } if (cache_size < 16) { cache_size = 16; if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size)) hprintk("can't set cache line size to %d\n", cache_size); } if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer)) { hprintk("can't read latency timer?\n"); return -EINVAL; } /* from table 3.9 * * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE * * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles] * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles] * */ #define LAT_TIMER 209 if (timer < LAT_TIMER) { HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER); timer = LAT_TIMER; if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer)) hprintk("can't set latency timer to %d\n", timer); } if (!(he_dev->membase = ioremap(membase, HE_REGMAP_SIZE))) { hprintk("can't set up page mapping\n"); return -EINVAL; } /* 4.4 card reset */ he_writel(he_dev, 0x0, RESET_CNTL); he_writel(he_dev, 0xff, RESET_CNTL); udelay(16*1000); /* 16 ms */ status = he_readl(he_dev, RESET_CNTL); if ((status & BOARD_RST_STATUS) == 0) { hprintk("reset failed\n"); return -EINVAL; } /* 4.5 set bus width */ host_cntl = he_readl(he_dev, HOST_CNTL); if (host_cntl & PCI_BUS_SIZE64) gen_cntl_0 |= ENBL_64; else gen_cntl_0 &= ~ENBL_64; if (disable64 == 1) { hprintk("disabling 64-bit pci bus transfers\n"); gen_cntl_0 &= ~ENBL_64; } if (gen_cntl_0 & ENBL_64) hprintk("64-bit transfers enabled\n"); pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); /* 4.7 read prom contents */ for (i = 0; i < PROD_ID_LEN; ++i) he_dev->prod_id[i] = read_prom_byte(he_dev, PROD_ID + i); he_dev->media = read_prom_byte(he_dev, MEDIA); for (i = 0; i < 6; ++i) dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i); hprintk("%s%s, %x:%x:%x:%x:%x:%x\n", he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM", dev->esi[0], dev->esi[1], dev->esi[2], dev->esi[3], dev->esi[4], dev->esi[5]); he_dev->atm_dev->link_rate = he_is622(he_dev) ? ATM_OC12_PCR : ATM_OC3_PCR; /* 4.6 set host endianess */ lb_swap = he_readl(he_dev, LB_SWAP); if (he_is622(he_dev)) lb_swap &= ~XFER_SIZE; /* 4 cells */ else lb_swap |= XFER_SIZE; /* 8 cells */#ifdef __BIG_ENDIAN lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST;#else lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST | DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP);#endif /* __BIG_ENDIAN */ he_writel(he_dev, lb_swap, LB_SWAP); /* 4.8 sdram controller initialization */ he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL); /* 4.9 initialize rnum value */ lb_swap |= SWAP_RNUM_MAX(0xf); he_writel(he_dev, lb_swap, LB_SWAP); /* 4.10 initialize the interrupt queues */ if ((err = he_init_irq(he_dev)) != 0) return err; /* 4.11 enable pci bus controller state machines */ host_cntl |= (OUTFF_ENB | CMDFF_ENB | QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB); he_writel(he_dev, host_cntl, HOST_CNTL); gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB; pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); /* * atm network controller initialization */ /* 5.1.1 generic configuration state */ /* * local (cell) buffer memory map * * HE155 HE622 * * 0 ____________1023 bytes 0 _______________________2047 bytes * | | | | | * | utility | | rx0 | | * 5|____________| 255|___________________| u | * 6| | 256| | t | * | | | | i | * | rx0 | row | tx | l | * | | | | i | * | | 767|___________________| t | * 517|____________| 768| | y | * row 518| | | rx1 | | * | | 1023|___________________|___| * | | * | tx | * | | * | | * 1535|____________| * 1536| | * | rx1 | * 2047|____________| * */ /* total 4096 connections */ he_dev->vcibits = CONFIG_DEFAULT_VCIBITS; he_dev->vpibits = CONFIG_DEFAULT_VPIBITS; if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS) { hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS); return -ENODEV; } if (nvpibits != -1) { he_dev->vpibits = nvpibits; he_dev->vcibits = HE_MAXCIDBITS - nvpibits; } if (nvcibits != -1) { he_dev->vcibits = nvcibits; he_dev->vpibits = HE_MAXCIDBITS - nvcibits; } if (he_is622(he_dev)) { he_dev->cells_per_row = 40; he_dev->bytes_per_row = 2048; he_dev->r0_numrows = 256; he_dev->tx_numrows = 512; he_dev->r1_numrows = 256; he_dev->r0_startrow = 0; he_dev->tx_startrow = 256; he_dev->r1_startrow = 768; } else { he_dev->cells_per_row = 20; he_dev->bytes_per_row = 1024; he_dev->r0_numrows = 512; he_dev->tx_numrows = 1018; he_dev->r1_numrows = 512; he_dev->r0_startrow = 6; he_dev->tx_startrow = 518; he_dev->r1_startrow = 1536; } he_dev->cells_per_lbuf = 4; he_dev->buffer_limit = 4; he_dev->r0_numbuffs = he_dev->r0_numrows * he_dev->cells_per_row / he_dev->cells_per_lbuf; if (he_dev->r0_numbuffs > 2560) he_dev->r0_numbuffs = 2560; he_dev->r1_numbuffs = he_dev->r1_numrows * he_dev->cells_per_row / he_dev->cells_per_lbuf; if (he_dev->r1_numbuffs > 2560) he_dev->r1_numbuffs = 2560; he_dev->tx_numbuffs = he_dev->tx_numrows * he_dev->cells_per_row / he_dev->cells_per_lbuf; if (he_dev->tx_numbuffs > 5120) he_dev->tx_numbuffs = 5120; /* 5.1.2 configure hardware dependent registers */ he_writel(he_dev, SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) | RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) | (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) | (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)), LBARB); he_writel(he_dev, BANK_ON | (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)), SDRAMCON); he_writel(he_dev, (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) | RM_RW_WAIT(1), RCMCONFIG); he_writel(he_dev, (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) | TM_RW_WAIT(1), TCMCONFIG); he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG); he_writel(he_dev, (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) | (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) | RX_VALVP(he_dev->vpibits) | RX_VALVC(he_dev->vcibits), RC_CONFIG); he_writel(he_dev, DRF_THRESH(0x20) | (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) | TX_VCI_MASK(he_dev->vcibits) | LBFREE_CNT(he_dev->tx_numbuffs), TX_CONFIG); he_writel(he_dev, 0x0, TXAAL5_PROTO); he_writel(he_dev, PHY_INT_ENB | (he_is622(he_dev) ? PTMR_PRE(67 - 1) : PTMR_PRE(50 - 1)), RH_CONFIG); /* 5.1.3 initialize connection memory */ for (i = 0; i < TCM_MEM_SIZE; ++i) he_writel_tcm(he_dev, 0, i); for (i = 0; i < RCM_MEM_SIZE; ++i) he_writel_rcm(he_dev, 0, i); /* * transmit connection memory map * * tx memory * 0x0 ___________________ * | | * | | * | TSRa | * | | * | | * 0x8000|___________________| * | | * | TSRb | * 0xc000|___________________| * | | * | TSRc | * 0xe000|___________________| * | TSRd | * 0xf000|___________________| * | tmABR | * 0x10000|___________________| * | | * | tmTPD | * |___________________| * | | * .... * 0x1ffff|___________________| * * */ he_writel(he_dev, CONFIG_TSRB, TSRB_BA); he_writel(he_dev, CONFIG_TSRC, TSRC_BA); he_writel(he_dev, CONFIG_TSRD, TSRD_BA); he_writel(he_dev, CONFIG_TMABR, TMABR_BA); he_writel(he_dev, CONFIG_TPDBA, TPD_BA); /* * receive connection memory map * * 0x0 ___________________ * | | * | | * | RSRa | * | | * | | * 0x8000|___________________| * | | * | rx0/1 | * | LBM | link lists of local * | tx | buffer memory * | | * 0xd000|___________________| * | | * | rmABR | * 0xe000|___________________| * | | * | RSRb | * |___________________| * | | * .... * 0xffff|___________________| */ he_writel(he_dev, 0x08000, RCMLBM_BA); he_writel(he_dev, 0x0e000, RCMRSRB_BA); he_writel(he_dev, 0x0d800, RCMABR_BA); /* 5.1.4 initialize local buffer free pools linked lists */ he_init_rx_lbfp0(he_dev); he_init_rx_lbfp1(he_dev); he_writel(he_dev, 0x0, RLBC_H); he_writel(he_dev, 0x0, RLBC_T); he_writel(he_dev, 0x0, RLBC_H2); he_writel(he_dev, 512, RXTHRSH); /* 10% of r0+r1 buffers */ he_writel(he_dev, 256, LITHRSH); /* 5% of r0+r1 buffers */ he_init_tx_lbfp(he_dev); he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA); /* 5.1.5 initialize intermediate receive queues */ if (he_is622(he_dev)) { he_writel(he_dev, 0x000f, G0_INMQ_S); he_writel(he_dev, 0x200f, G0_INMQ_L); he_writel(he_dev, 0x001f, G1_INMQ_S); he_writel(he_dev, 0x201f, G1_INMQ_L); he_writel(he_dev, 0x002f, G2_INMQ_S); he_writel(he_dev, 0x202f, G2_INMQ_L); he_writel(he_dev, 0x003f, G3_INMQ_S); he_writel(he_dev, 0x203f, G3_INMQ_L); he_writel(he_dev, 0x004f, G4_INMQ_S); he_writel(he_dev, 0x204f, G4_INMQ_L); he_writel(he_dev, 0x005f, G5_INMQ_S); he_writel(he_dev, 0x205f, G5_INMQ_L);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -