📄 dm9000x.c
字号:
dev->dev_addr[i] = eth3_mac_addr[i];//db->srom[i]; // printk("%02X:",dev->dev_addr[i]); } //printk("\n"); }else return 0; //printk("HHTech <DM9000> I/O: %x, VID: succ\n", iobase); //return; //printk("Device Name=%s,name=%s\n",dev->name,dev->priv); //DMFE_DBUG(0, "dmfe_probe()",0); //iow(db, 0xfe, 0x0f); /* Clear interrupt status */ //printk("222\n"); /* Disable all interrupt */ //iow(db, 0xff, 0x80);///////////////////////////////////////////////////////////////////////// /* Search All DM9000 NIC */ //{ //printk("iobase=%x,value=%x\n",iobase,DM9000_VID_L); outb(DM9000_VID_L, iobase); id_val = inb(iobase + 4); outb(DM9000_VID_H, iobase); id_val |= inb(iobase + 4) << 8; outb(DM9000_PID_L, iobase); id_val |= inb(iobase + 4) << 16; outb(DM9000_PID_H, iobase); id_val |= inb(iobase + 4) << 24; if (id_val == DM9000_ID) { printk("HHTech DM9000 %s I/O: %x,VID: %x,MAC: ", dev->name,iobase, id_val); dm9000_count++; /* Init network device */ dev = init_etherdev(dev, 0); /* Allocated board information structure */ irqline = 3; db = (void *)(kmalloc(sizeof(*db), GFP_KERNEL|GFP_DMA)); memset(db, 0, sizeof(*db)); dev->priv = db; /* link device and board info */ db->next_dev = dmfe_root_dev; dmfe_root_dev = dev; db->ioaddr = iobase; db->io_data = iobase + 4; /* driver system function */ dev->base_addr = iobase; //dev->irq = 68; //INT4 166;//irqline; dev->open = &dmfe_open; dev->hard_start_xmit = &dmfe_start_xmit; dev->stop = &dmfe_stop; dev->get_stats = &dmfe_get_stats; dev->set_multicast_list = &dm9000_hash_table; dev->do_ioctl = &dmfe_do_ioctl; /* Read SROM content */ /*for (i=0; i<64; i++) ((u16 *)db->srom)[i] = read_srom_word(db, i);*/ /* Set Node Address */ //add by zy //i2c_read(0x7a,buff,6); //we set lan-switch data to first 24 bytes,then put mac data to the last 6 bytes. //printk("MAC set to "); for (i=0; i<6; i++){ // dev->dev_addr[i] = eth_mac_addr[i];//db->srom[i]; printk("%02X:",dev->dev_addr[i]); } printk("\n"); } if (dm9000_count) { //request_irq(db->irq, &dmfe_interrupt,0,"DM9000 device",dev);/* Enable interrupts for GPIO6 *///L-->H//HHTECH//*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_GPIOINTENABLE)) |=0x00000040;/* Enable interrupt level for GPIO6 - VEC38 *///*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_INTLEVEL5)) |=0x04000000; }//printk("**** request_irq=%x\n",dev->irq);//if(request_irq(dev->irq, &dmfe_interrupt,SA_SHIRQ,"DM9000 device",dev)) // return -EAGAIN;// printk(" ****** success rquest_irq\n"); /* Re-enable interrupt mask */ //iow(db, 0xff, 0x83); return dm9000_count ? 0:-ENODEV;}/* Open the interface. The interface is opened whenever "ifconfig" actives it.*/static int dmfe_open(struct DEVICE *dev){ board_info_t * db = (board_info_t *)dev->priv; DMFE_DBUG(0, "dmfe_open", 0); //minor = MINOR(dev->priv); //printk("minor=%x\n",dev->minor); //if (request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev)) //printk("request_irq,irq=%x\n",dev->irq); if(request_irq(dev->irq, &dmfe_interrupt,SA_INTERRUPT/*SA_SHIRQ*/,"DM9000 device",dev)) return -EAGAIN; /* Initilize DM910X board */ dmfe_init_dm9000(dev); // printk("end init\n"); /* Init driver variable */ db->dbug_cnt = 0; db->runt_length_counter = 0; db->long_length_counter = 0; db->reset_counter = 0; /* Active System Interface */ //dev->tbusy = 0; /* Can transmit packet */ //dev->start = 1; /* interface ready */ //mark above for kernel 2.4 netif_wake_queue(dev); //add by simon 2001.9.4 for kernel 2.4 MOD_INC_USE_COUNT;// printk("init timer\n"); /* set and active a timer process */ init_timer(&db->timer);// printk("end timer\n"); db->timer.expires = DMFE_TIMER_WUT * 2; db->timer.data = (unsigned long)dev; db->timer.function = &dmfe_timer; add_timer(&db->timer); return 0;}/* Set PHY operationg mode*/static void set_PHY_mode(board_info_t *db){ u16 phy_reg4 = 0x01e1, phy_reg0=0x1000; if ( !(db->op_mode & DM9000_AUTO) ) { switch(db->op_mode) { case DM9000_10MHD: phy_reg4 = 0x21; phy_reg0 = 0x0000; break; case DM9000_10MFD: phy_reg4 = 0x41; //phy_reg0 = 0x0100; phy_reg0 = 0x1100; //add by simon 2001.11.8 break; case DM9000_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x2000; break; case DM9000_100MFD: phy_reg4 = 0x101; //phy_reg0 = 0x2100; phy_reg0 =0x3100; //add by simon 2001.11.8 break; } phy_write(db, 4, phy_reg4); /* Set PHY media mode */ phy_write(db, 0, phy_reg0); /* Tmp */ } iow(db, 0x1e, 0x01); /* Let GPIO0 output */ iow(db, 0x1f, 0x00); /* Enable PHY */}/* Init HomeRun DM9801*/static void program_dm9801(board_info_t *db, u16 HPNA_rev){ __u16 reg16, reg17, reg24, reg25; if ( !nfloor ) nfloor = DM9801_NOISE_FLOOR; reg16 = phy_read(db, 16); reg17 = phy_read(db, 17); reg24 = phy_read(db, 24); reg25 = phy_read(db, 25); switch(HPNA_rev) { case 0xb900: /* DM9801 E3 */ reg16 |= 0x1000; reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xf000; break; case 0xb901: /* DM9801 E4 */ reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xc200; reg17 = (reg17 & 0xfff0) + nfloor + 3; break; case 0xb902: /* DM9801 E5 */ case 0xb903: /* DM9801 E6 */ default: reg16 |= 0x1000; reg25 = ( (reg24 + nfloor - 3) & 0x00ff) | 0xc200; reg17 = (reg17 & 0xfff0) + nfloor; break; } phy_write(db, 16, reg16); phy_write(db, 17, reg17); phy_write(db, 25, reg25);}/* Init LongRun DM9802*/static void program_dm9802(board_info_t *db){ __u16 reg25; if ( !nfloor ) nfloor = DM9802_NOISE_FLOOR; reg25 = phy_read(db, 25); reg25 = (reg25 & 0xff00) + nfloor; phy_write(db, 25, reg25);}/* Identify NIC type*/static void identify_nic(board_info_t *db){ u16 phy_reg3; iow(db, 0, DM9000_EXT_MII); phy_reg3 = phy_read(db, 3); switch(phy_reg3 & 0xfff0) { case 0xb900: if (phy_read(db, 31) == 0x4404) { db->nic_type = HOMERUN_NIC; program_dm9801(db, phy_reg3); } else { db->nic_type = LONGRUN_NIC; program_dm9802(db); } break; default: db->nic_type = FASTETHER_NIC; break; } iow(db, 0, DM9000_INT_MII); }/* Initilize dm9000 board*/static void dmfe_init_dm9000(struct DEVICE *dev){ board_info_t *db = (board_info_t *)dev->priv; DMFE_DBUG(0, "dmfe_init_dm9000()", 0); /* RESET device */ iow(db, 0, 1); udelay(100); /* delay 100us */ /* I/O mode */ db->io_mode = ior(db, 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */ /* NIC Type: FASTETHER, HOMERUN, LONGRUN */ identify_nic(db); /* Set PHY */ db->op_mode = media_mode; set_PHY_mode(db); /* Init needed register value */ db->reg0 = DM9000_REG00; if ( (db->nic_type != FASTETHER_NIC) && (db->op_mode & DM9000_1M_HPNA) ) db->reg0 |= DM9000_EXT_MII; /* User passed argument */ db->reg5 = reg5; db->reg8 = reg8; db->reg9 = reg9; db->rega = rega; /* Program operating register */ iow(db, 0x00, db->reg0); iow(db, 0x02, 0); /* TX Polling clear */ iow(db, 0x08, 0x3f); /* Less 3Kb, 200us */ iow(db, 0x09, db->reg9);/* Flow Control : High/Low Water */ iow(db, 0x0a, db->rega);/* Flow Control */ iow(db, 0x2f, 0); /* Special Mode */ iow(db, 0x01, 0x2c); /* clear TX status */ iow(db, 0xfe, 0x0f); /* Clear interrupt status */ /* Re-enable interrupt mask */ iow(db, 0xff, 0x83); /* Set address filter table */ dm9000_hash_table(dev); /* Activate DM9000 */ iow(db, 0x05, db->reg5 | 1); /* RX enable */ iow(db, 0xff, DM9000_REGFF); /* Enable TX/RX interrupt mask */ /* Init Driver variable */ db->link_failed = 1; db->tx_pkt_cnt = 0; db->queue_pkt_len = 0; dev->trans_start = 0;//HHTECH/hn: to solve reboot problem: //../5307/ints.c(47): default irq handler vec=166 [0xa6]/* Enable interrupts for GPIO6 *///L-->H//*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_GPIOINTENABLE)) |=0x00000040;/* Enable interrupt level for GPIO6 - VEC38 *///*((volatile unsigned long *) (MCF_MBAR2+MCFSIM2_INTLEVEL5)) |=0x04000000; //HHTECH#if 0switch(dev->irq){ case 68:*(volatile unsigned long *)0x10000034|=0x10000000; *(volatile unsigned long *)0x10000020|=0x000b0000; break; case 90:*(volatile unsigned long *)0x10000034|=0x00000040; *(volatile unsigned long *)0x1000002c|=0x0b000000; break; case 91:*(volatile unsigned long *)0x10000034|=0x00000020; *(volatile unsigned long *)0x1000002c|=0x00b00000; } #endif ///////////////////////////////////////////////////////////////////// spin_lock_init(&db->lock); //add by simon 2001.9.7 init the spinlock var}/* Hardware start transmission. Send a packet to media from the upper layer.*/static int dmfe_start_xmit(struct sk_buff *skb, struct DEVICE *dev){ board_info_t *db = (board_info_t *)dev->priv; char * data_ptr; int i, tmplen; DMFE_DBUG(0, "dmfe_start_xmit", 0); /* Resource flag check */ //if ( test_and_set_bit(0, (void *)&dev->tbusy) || (db->tx_pkt_cnt > 1) ) // return 1; //mark above by simon 2001.9.4 for kernel 2.4 if (db->tx_pkt_cnt > 1) return 1; //add by simon 2001.9.4 netif_stop_queue(dev); //add by simon 2001.9.4 for kernel 2.4 /* Disable all interrupt */ iow(db, 0xff, 0x80); /* Move data to DM9000 TX RAM */ data_ptr = (char *)skb->data; outb(0xf8, db->ioaddr); tmplen = (skb->len + 1) / 2; /* Word mode*/ for (i = 0; i < tmplen; i++) outw(((u16 *)data_ptr)[i], db->io_data); /* TX control: First packet immediately send, second packet queue */ if (db->tx_pkt_cnt == 0) { /* First Packet */ db->tx_pkt_cnt++; /* Set TX length to DM9000 */ iow(db, 0xfc, skb->len & 0xff); iow(db, 0xfd, (skb->len >> 8) & 0xff); /* Issue TX polling command */ iow(db, 0x2, 0x1); /* Cleared after TX complete */ dev->trans_start = jiffies; /* saved the time stamp */ } else { /* Second packet */ db->tx_pkt_cnt++; db->queue_pkt_len = skb->len; } /* free this SKB */ dev_kfree_skb(skb); /* Re-enable resource check */ if (db->tx_pkt_cnt == 1) //clear_bit(0, (void*)&dev->tbusy); //mark by simon 2001.9.4 for kernel 2.4 netif_wake_queue(dev); //add by simon 2001.9.4 for kernel 2.4 /* Re-enable interrupt mask */ iow(db, 0xff, 0x83); return 0;}/* Stop the interface. The interface is stopped when it is brought.*/static int dmfe_stop(struct DEVICE *dev){ board_info_t *db = (board_info_t *)dev->priv; DMFE_DBUG(0, "dmfe_stop", 0); /* deleted timer */ del_timer(&db->timer); /* disable system */ //dev->start = 0; /* interface disable */ //dev->tbusy = 1; /* can't transmit */ //mark above by simon 2001.9.4 netif_stop_queue(dev); //add by simon 2001.9.4 for kernel 2.4 /* free interrupt */ free_irq(dev->irq, dev); /* RESET devie */ phy_write(db, 0x00, 0x8000); /* PHY RESET */ iow(db, 0x1f, 0x01); /* Power-Down PHY */ iow(db, 0xff, 0x80); /* Disable all interrupt */ iow(db, 0x05, 0x00); /* Disable RX */ MOD_DEC_USE_COUNT; /* Dump Statistic counter */#if 0 printk("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors++); printk("RX CRC %lx\n", db->stats.rx_crc_errors++); printk("RX LEN Err %lx\n", db->stats.rx_length_errors++); printk("RX LEN<64byte %x\n", db->runt_length_counter); printk("RX LEN>1514byte %x\n", db->long_length_counter); printk("RESET %x\n", db->reset_counter); printk("RESET: TX Timeout %x\n", db->reset_tx_timeout); printk("RESET: RX Status Wrong %x\n", db->reset_rx_status);#endif return 0;}/* DM9102 insterrupt handler receive the packet to upper layer, free the transmitted packet*/static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct DEVICE *dev = dev_id; board_info_t *db; int int_status, tx_status; u8 reg_save; //printk("Intrrupt happened\n"); DMFE_DBUG(0, "dmfe_interrupt()", 0); if (!dev) { DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0); return; } //mark below if-block by simon 2001.9.4 // for kernel 2.4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -