📄 hp100.c
字号:
hp100_outw(HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); hp100_outw(HP100_TRI_INT | HP100_SET_HB, OPTION_LSW); if (lp->mode == 1) { hp100_BM_shutdown(dev); /* disables BM, puts cascade in reset */ wait(); } else { hp100_outw(HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); hp100_cascade_reset(dev, TRUE); hp100_page(MAC_CTRL); hp100_andb(~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1); } /* Initiate EEPROM reload */ hp100_load_eeprom(dev, 0); wait(); /* Go into reset again. */ hp100_cascade_reset(dev, TRUE); /* Set Option Registers to a safe state */ hp100_outw(HP100_DEBUG_EN | HP100_RX_HDR | HP100_EE_EN | HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB | HP100_FAKE_INT | HP100_INT_EN | HP100_MEM_EN | HP100_IO_EN | HP100_RESET_LB, OPTION_LSW); hp100_outw(HP100_TRI_INT | HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW); hp100_outb(HP100_PRIORITY_TX | HP100_ADV_NXT_PKT | HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW); /* TODO: Configure MMU for Ram Test. */ /* TODO: Ram Test. */ /* Re-check if adapter is still at same i/o location */ /* (If the base i/o in eeprom has been changed but the */ /* registers had not been changed, a reload of the eeprom */ /* would move the adapter to the address stored in eeprom */ /* TODO: Code to implement. */ /* Until here it was code from HWdiscover procedure. */ /* Next comes code from mmuinit procedure of SCO BM driver which is * called from HWconfigure in the SCO driver. */ /* Initialise MMU, eventually switch on Busmaster Mode, initialise * multicast filter... */ hp100_mmuinit(dev); /* We don't turn the interrupts on here - this is done by start_interface. */ wait(); /* TODO: Do we really need this? */ /* Enable Hardware (e.g. unreset) */ hp100_cascade_reset(dev, FALSE); /* ------- initialisation complete ----------- */ /* Finally try to log in the Hub if there may be a VG connection. */ if (lp->lan_type != HP100_LAN_10) hp100_login_to_vg_hub(dev, FALSE); /* relogin */}/* * mmuinit - Reinitialise Cascade MMU and MAC settings. * Note: Must already be in reset and leaves card in reset. */static void hp100_mmuinit(struct net_device *dev){ int ioaddr = dev->base_addr; struct hp100_private *lp = (struct hp100_private *) dev->priv; int i;#ifdef HP100_DEBUG_B hp100_outw(0x4203, TRACE); printk("hp100: %s: mmuinit\n", dev->name);#endif#ifdef HP100_DEBUG if (0 != (hp100_inw(OPTION_LSW) & HP100_HW_RST)) { printk("hp100: %s: Not in reset when entering mmuinit. Fix me.\n", dev->name); return; }#endif /* Make sure IRQs are masked off and ack'ed. */ hp100_page(PERFORMANCE); hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ hp100_outw(0xffff, IRQ_STATUS); /* ack IRQ */ /* * Enable Hardware * - Clear Debug En, Rx Hdr Pipe, EE En, I/O En, Fake Int and Intr En * - Set Tri-State Int, Bus Master Rd/Wr, and Mem Map Disable * - Clear Priority, Advance Pkt and Xmit Cmd */ hp100_outw(HP100_DEBUG_EN | HP100_RX_HDR | HP100_EE_EN | HP100_RESET_HB | HP100_IO_EN | HP100_FAKE_INT | HP100_INT_EN | HP100_RESET_LB, OPTION_LSW); hp100_outw(HP100_TRI_INT | HP100_SET_HB, OPTION_LSW); if (lp->mode == 1) { /* busmaster */ hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW); } else if (lp->mode == 2) { /* memory mapped */ hp100_outw(HP100_BM_WRITE | HP100_BM_READ | HP100_RESET_HB, OPTION_LSW); hp100_outw(HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW); hp100_outw(HP100_MEM_EN | HP100_SET_LB, OPTION_LSW); hp100_outw(HP100_IO_EN | HP100_SET_LB, OPTION_LSW); } else if (lp->mode == 3) { /* i/o mapped mode */ hp100_outw(HP100_MMAP_DIS | HP100_SET_HB | HP100_IO_EN | HP100_SET_LB, OPTION_LSW); } hp100_page(HW_MAP); hp100_outb(0, EARLYRXCFG); hp100_outw(0, EARLYTXCFG); /* * Enable Bus Master mode */ if (lp->mode == 1) { /* busmaster */ /* Experimental: Set some PCI configuration bits */ hp100_page(HW_MAP); hp100_andb(~HP100_PDL_USE3, MODECTRL1); /* BM engine read maximum */ hp100_andb(~HP100_TX_DUALQ, MODECTRL1); /* No Queue for Priority TX */ /* PCI Bus failures should result in a Misc. Interrupt */ hp100_orb(HP100_EN_BUS_FAIL, MODECTRL2); hp100_outw(HP100_BM_READ | HP100_BM_WRITE | HP100_SET_HB, OPTION_LSW); hp100_page(HW_MAP); /* Use Burst Mode and switch on PAGE_CK */ hp100_orb(HP100_BM_BURST_RD | HP100_BM_BURST_WR, BM); if ((lp->chip == HP100_CHIPID_RAINIER) || (lp->chip == HP100_CHIPID_SHASTA)) hp100_orb(HP100_BM_PAGE_CK, BM); hp100_orb(HP100_BM_MASTER, BM); } else { /* not busmaster */ hp100_page(HW_MAP); hp100_andb(~HP100_BM_MASTER, BM); } /* * Divide card memory into regions for Rx, Tx and, if non-ETR chip, PDLs */ hp100_page(MMU_CFG); if (lp->mode == 1) { /* only needed for Busmaster */ int xmit_stop, recv_stop; if ((lp->chip == HP100_CHIPID_RAINIER) || (lp->chip == HP100_CHIPID_SHASTA)) { int pdl_stop; /* * Each pdl is 508 bytes long. (63 frags * 4 bytes for address and * 4 bytes for header). We will leave NUM_RXPDLS * 508 (rounded * to the next higher 1k boundary) bytes for the rx-pdl's * Note: For non-etr chips the transmit stop register must be * programmed on a 1k boundary, i.e. bits 9:0 must be zero. */ pdl_stop = lp->memory_size; xmit_stop = (pdl_stop - 508 * (MAX_RX_PDL) - 16) & ~(0x03ff); recv_stop = (xmit_stop * (lp->rx_ratio) / 100) & ~(0x03ff); hp100_outw((pdl_stop >> 4) - 1, PDL_MEM_STOP);#ifdef HP100_DEBUG_BM printk("hp100: %s: PDL_STOP = 0x%x\n", dev->name, pdl_stop);#endif } else { /* ETR chip (Lassen) in busmaster mode */ xmit_stop = (lp->memory_size) - 1; recv_stop = ((lp->memory_size * lp->rx_ratio) / 100) & ~(0x03ff); } hp100_outw(xmit_stop >> 4, TX_MEM_STOP); hp100_outw(recv_stop >> 4, RX_MEM_STOP);#ifdef HP100_DEBUG_BM printk("hp100: %s: TX_STOP = 0x%x\n", dev->name, xmit_stop >> 4); printk("hp100: %s: RX_STOP = 0x%x\n", dev->name, recv_stop >> 4);#endif } else { /* Slave modes (memory mapped and programmed io) */ hp100_outw((((lp->memory_size * lp->rx_ratio) / 100) >> 4), RX_MEM_STOP); hp100_outw(((lp->memory_size - 1) >> 4), TX_MEM_STOP);#ifdef HP100_DEBUG printk("hp100: %s: TX_MEM_STOP: 0x%x\n", dev->name, hp100_inw(TX_MEM_STOP)); printk("hp100: %s: RX_MEM_STOP: 0x%x\n", dev->name, hp100_inw(RX_MEM_STOP));#endif } /* Write MAC address into page 1 */ hp100_page(MAC_ADDRESS); for (i = 0; i < 6; i++) hp100_outb(dev->dev_addr[i], MAC_ADDR + i); /* Zero the multicast hash registers */ for (i = 0; i < 8; i++) hp100_outb(0x0, HASH_BYTE0 + i); /* Set up MAC defaults */ hp100_page(MAC_CTRL); /* Go to LAN Page and zero all filter bits */ /* Zero accept error, accept multicast, accept broadcast and accept */ /* all directed packet bits */ hp100_andb(~(HP100_RX_EN | HP100_TX_EN | HP100_ACC_ERRORED | HP100_ACC_MC | HP100_ACC_BC | HP100_ACC_PHY), MAC_CFG_1); hp100_outb(0x00, MAC_CFG_2); /* Zero the frame format bit. This works around a training bug in the */ /* new hubs. */ hp100_outb(0x00, VG_LAN_CFG_2); /* (use 802.3) */ if (lp->priority_tx) hp100_outb(HP100_PRIORITY_TX | HP100_SET_LB, OPTION_MSW); else hp100_outb(HP100_PRIORITY_TX | HP100_RESET_LB, OPTION_MSW); hp100_outb(HP100_ADV_NXT_PKT | HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW); /* If busmaster, initialize the PDLs */ if (lp->mode == 1) hp100_init_pdls(dev); /* Go to performance page and initalize isr and imr registers */ hp100_page(PERFORMANCE); hp100_outw(0xfefe, IRQ_MASK); /* mask off all ints */ hp100_outw(0xffff, IRQ_STATUS); /* ack IRQ */}/* * open/close functions */static int hp100_open(struct net_device *dev){ struct hp100_private *lp = (struct hp100_private *) dev->priv;#ifdef HP100_DEBUG_B int ioaddr = dev->base_addr;#endif#ifdef HP100_DEBUG_B hp100_outw(0x4204, TRACE); printk("hp100: %s: open\n", dev->name);#endif /* New: if bus is PCI or EISA, interrupts might be shared interrupts */ if (request_irq(dev->irq, hp100_interrupt, lp->bus == HP100_BUS_PCI || lp->bus == HP100_BUS_EISA ? SA_SHIRQ : SA_INTERRUPT, lp->id->name, dev)) { printk("hp100: %s: unable to get IRQ %d\n", dev->name, dev->irq); return -EAGAIN; } dev->trans_start = jiffies; netif_start_queue(dev); lp->lan_type = hp100_sense_lan(dev); lp->mac1_mode = HP100_MAC1MODE3; lp->mac2_mode = HP100_MAC2MODE3; memset(&lp->hash_bytes, 0x00, 8); hp100_stop_interface(dev); hp100_hwinit(dev); hp100_start_interface(dev); /* sets mac modes, enables interrupts */ return 0;}/* The close function is called when the interface is to be brought down */static int hp100_close(struct net_device *dev){ int ioaddr = dev->base_addr; struct hp100_private *lp = (struct hp100_private *) dev->priv;#ifdef HP100_DEBUG_B hp100_outw(0x4205, TRACE); printk("hp100: %s: close\n", dev->name);#endif hp100_page(PERFORMANCE); hp100_outw(0xfefe, IRQ_MASK); /* mask off all IRQs */ hp100_stop_interface(dev); if (lp->lan_type == HP100_LAN_100) lp->hub_status = hp100_login_to_vg_hub(dev, FALSE); netif_stop_queue(dev); free_irq(dev->irq, dev);#ifdef HP100_DEBUG printk("hp100: %s: close LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW));#endif return 0;}/* * Configure the PDL Rx rings and LAN */static void hp100_init_pdls(struct net_device *dev){ struct hp100_private *lp = (struct hp100_private *) dev->priv; hp100_ring_t *ringptr; u_int *pageptr; int i;#ifdef HP100_DEBUG_B int ioaddr = dev->base_addr;#endif#ifdef HP100_DEBUG_B hp100_outw(0x4206, TRACE); printk("hp100: %s: init pdls\n", dev->name);#endif if (0 == lp->page_vaddr_algn) printk("hp100: %s: Warning: lp->page_vaddr_algn not initialised!\n", dev->name); else { /* pageptr shall point into the DMA accessible memory region */ /* we use this pointer to status the upper limit of allocated */ /* memory in the allocated page. */ /* note: align the pointers to the pci cache line size */ memset(lp->page_vaddr_algn, 0, MAX_RINGSIZE); /* Zero Rx/Tx ring page */ pageptr = lp->page_vaddr_algn; lp->rxrcommit = 0; ringptr = lp->rxrhead = lp->rxrtail = &(lp->rxring[0]); /* Initialise Rx Ring */ for (i = MAX_RX_PDL - 1; i >= 0; i--) { lp->rxring[i].next = ringptr; ringptr = &(lp->rxring[i]); pageptr += hp100_init_rxpdl(dev, ringptr, pageptr); } /* Initialise Tx Ring */ lp->txrcommit = 0; ringptr = lp->txrhead = lp->txrtail = &(lp->txring[0]); for (i = MAX_TX_PDL - 1; i >= 0; i--) { lp->txring[i].next = ringptr; ringptr = &(lp->txring[i]); pageptr += hp100_init_txpdl(dev, ringptr, pageptr); } }}/* These functions "format" the entries in the pdl structure *//* They return how much memory the fragments need. */static int hp100_init_rxpdl(struct net_device *dev, register hp100_ring_t * ringptr, register u32 * pdlptr){ /* pdlptr is starting address for this pdl */ if (0 != (((unsigned) pdlptr) & 0xf)) printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n", dev->name, (unsigned) pdlptr); ringptr->pdl = pdlptr + 1; ringptr->pdl_paddr = virt_to_bus(pdlptr + 1); ringptr->skb = (void *) NULL; /* * Write address and length of first PDL Fragment (which is used for * storing the RX-Header * We use the 4 bytes _before_ the PDH in the pdl memory area to * store this information. (PDH is at offset 0x04) */ /* Note that pdlptr+1 and not pdlptr is the pointer to the PDH */ *(pdlptr + 2) = (u_int) virt_to_bus(pdlptr); /* Address Frag 1 */ *(pdlptr + 3) = 4; /* Length Frag 1 */ return ((((MAX_RX_FRAG * 2 + 2) + 3) / 4) * 4);}static int hp100_init_txpdl(struct net_device *dev, register hp100_ring_t * ringptr, register u32 * pdlptr){ if (0 != (((unsigned) pdlptr) & 0xf)) printk("hp100: %s: Init txpdl: Unaligned pdlptr 0x%x.\n", dev->name, (unsigned) pdlptr); ringptr->pdl = pdlptr; /* +1; */ ringptr->pdl_paddr = virt_to_bus(pdlptr); /* +1 */ ringptr->skb = (void *) NULL; return ((((MAX_TX_FRAG * 2 + 2) + 3) / 4) * 4);}/* * hp100_build_rx_pdl allocates an skb_buff of maximum size plus two bytes * for possible odd word alignment rounding up to next dword and set PDL * address for fragment#2 * Returns: 0 if unable to allocate skb_buff * 1 if successful
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -