📄 hp100.c
字号:
if ( dev->irq == 2 ) dev->irq = 9;#ifdef LINUX_2_1 }#endif if(lp->mode==1) /* busmaster */ dev->dma=4; /* Ask the card for its MAC address and store it for later use. */ hp100_page( ID_MAC_ADDR ); for ( i = uc = 0; i < 6; i++ ) dev->dev_addr[ i ] = hp100_inb( LAN_ADDR + i ); /* Reset statistics (counters) */ hp100_clear_stats( ioaddr ); ether_setup( dev ); /* If busmaster mode is wanted, a dma-capable memory area is needed for * the rx and tx PDLs * PCI cards can access the whole PC memory. Therefore GFP_DMA is not * needed for the allocation of the memory area. */ /* TODO: We do not need this with old cards, where PDLs are stored * in the cards shared memory area. But currently, busmaster has been * implemented/tested only with the lassen chip anyway... */ if(lp->mode==1) /* busmaster */ { /* Get physically continous memory for TX & RX PDLs */ if ( (lp->page_vaddr=kmalloc(MAX_RINGSIZE+0x0f,GFP_KERNEL) ) == NULL) return -ENOMEM; lp->page_vaddr_algn=((u_int *) ( ((u_int)(lp->page_vaddr)+0x0f) &~0x0f)); memset(lp->page_vaddr, 0, MAX_RINGSIZE+0x0f);#ifdef HP100_DEBUG_BM printk("hp100: %s: Reserved DMA memory from 0x%x to 0x%x\n", dev->name, (u_int)lp->page_vaddr_algn, (u_int)lp->page_vaddr_algn+MAX_RINGSIZE);#endif lp->rxrcommit = lp->txrcommit = 0; lp->rxrhead = lp->rxrtail = &(lp->rxring[0]); lp->txrhead = lp->txrtail = &(lp->txring[0]); } /* Initialise the card. */ /* (I'm not really sure if it's a good idea to do this during probing, but * like this it's assured that the lan connection type can be sensed * correctly) */ hp100_hwinit( dev ); /* Try to find out which kind of LAN the card is connected to. */ lp->lan_type = hp100_sense_lan( dev ); /* Print out a message what about what we think we have probed. */ printk( "hp100: %s: %s at 0x%x, IRQ %d, ", dev->name, lp->id->name, ioaddr, dev->irq ); switch ( bus ) { case HP100_BUS_EISA: printk( "EISA" ); break; case HP100_BUS_PCI: printk( "PCI" ); break; default: printk( "ISA" ); break; } printk( " bus, %dk SRAM (rx/tx %d%%).\n", lp->memory_size >> 10, lp->rx_ratio ); if ( lp->mode==2 ) /* memory mapped */ { printk( "hp100: %s: Memory area at 0x%lx-0x%lx", dev->name,(u_long)mem_ptr_phys, ((u_long)mem_ptr_phys+(mem_ptr_phys>(u_int *)0x100000?(u_long)lp->memory_size:16*1024))-1 ); if ( mem_ptr_virt ) printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt ); printk( ".\n" ); /* Set for info when doing ifconfig */ dev->mem_start = (u_long)mem_ptr_phys; dev->mem_end = (u_long)mem_ptr_phys+(u_long)lp->memory_size; } printk( "hp100: %s: ", dev->name ); if ( lp->lan_type != HP100_LAN_ERR ) printk( "Adapter is attached to " ); switch ( lp->lan_type ) { case HP100_LAN_100: printk( "100Mb/s Voice Grade AnyLAN network.\n" ); break; case HP100_LAN_10: printk( "10Mb/s network.\n" ); break; default: printk( "Warning! Link down.\n" ); } return 0;}/* This procedure puts the card into a stable init state */static void hp100_hwinit( struct device *dev ){ int ioaddr = dev->base_addr; struct hp100_private *lp = (struct hp100_private *)dev->priv;#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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -