📄 hp100.c
字号:
#ifdef HP100_DEBUG_B hp100_outw( 0x4202, TRACE ); printk("hp100: %s: hwinit\n", dev->name);#endif /* Initialise the card. -------------------------------------------- */ /* Clear all pending Ints and disable Ints */ hp100_page( PERFORMANCE ); hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */ hp100_outw( 0xffff, IRQ_STATUS ); /* clear all pending ints */ 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 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 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; } MOD_INC_USE_COUNT; dev->tbusy = 0; dev->trans_start = jiffies; dev->interrupt = 0; dev->start = 1; 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 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 ); dev->tbusy = 1; dev->start = 0; free_irq( dev->irq, dev );#ifdef HP100_DEBUG printk( "hp100: %s: close LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW) );#endif MOD_DEC_USE_COUNT; return 0;}/* * Configure the PDL Rx rings and LAN */static void hp100_init_pdls( struct 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 device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr ){ /* pdlptr is starting adress for this pdl */ if( 0!=( ((unsigned)pdlptr) & 0xf) ) printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned)pdlptr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -