?? dm9sw.c
字號:
/* Program operating register */ iow(db, DM9KS_NCR, 0x20); /* reg.01 cleared by write 1 */ iow(db, DM9KS_FCR, 0x20); /* RX Flow Control Enable */ #if defined(CHECKSUM) printk("<DM9SW>Enable checksum offload \n"); /* TX checksum enable */ iow(db, DM9KS_TCCR, TCCR_UDP_Chksum|TCCR_TCP_Chksum|TCCR_IP_Chksum); /* RX checksum enable */ iow(db, DM9KS_RCSR, RCSR_RX_Chksum_enable);#endif /* switch config */ /* If using EEPROM sets switch functions, don't execute dm9sw_switch_config() function */ dm9sw_switch_config(db); /* Set address filter table */ dm9000_hash_table(dev); /* Activate DM9000A/DM9010 */ /* Promisucous mode bug DM9013 V2 */ iow(db, DM9KS_RXCR, RXCR_RxEnable|RXCR_Promiscuous); iow(db, DM9KS_IMR, DM9KS_REGFF); /* Enable TX/RX interrupt mask */ /* Init Driver variable */ db->tx_pkt_cnt = 0; netif_carrier_on(dev);}inline u8 MAKE_MASK(int p3, int p2, int p1, int p0){ p3 = p3 ? 1:0; p2 = p2 ? 1:0; p1 = p1 ? 1:0; p0 = p0 ? 1:0; return (p3<<3)|(p2<<2)|(p1<<1)|p0;}static void vlan_group_map(board_info_t *db,u8 reg_group, u8 mapping){ iow(db,reg_group,mapping); }/* vlan_type 0:Port-base 1:Tag-base*/static void VLAN_SETUP(board_info_t *db, int vlan_type){ if (vlan_type)/* Tag-base */ { printk("DM9013:VLAN TAG-BASE\n"); /* enble tag-base vlan (reg 53h.0=1) */ iow (db, DM9KS_VLANCR, (ior(db,DM9KS_VLANCR)&0xff)|0x1); /* input_port output_port (1:tag-packet, 0:untag-packet) 0 1 1 0 1 1 Per-port setting 01: VID(reg 6fH.[3:0])-->output packet tagging(reg 6dH.7=1)-->Group mapping 10: Group mapping 11: output packet tagging(reg 6dH.7=1)-->Group mapping */ /*01: set port VID*/ /*vlan_port_vid(db, port_no, VID)*/ vlan_port_vid(db,0,0); /* set P0 VID=0 */ vlan_port_vid(db,1,2); /* set P1 VID=2*/ /*01,11:Per-port output packet tagging enable */ vlan_outpkt_tag(db,0); vlan_outpkt_tag(db,1); vlan_outpkt_tag(db,2); vlan_outpkt_tag(db,3); /*01,10,11:group mapping */ vlan_group_map(db, VLAN_GROUP1, MAKE_MASK(1, 1, 1, 1)); vlan_group_map(db, VLAN_GROUP2, MAKE_MASK(1, 1, 1, 1)); }else{ printk("DM9013:VLAN PORT-BASE\n"); /* enble tag-base vlan (reg 53h.0=0) */ iow (db, DM9KS_VLANCR, (ior(db,DM9KS_VLANCR)&0xfe)); /* port-base VLAN step 1:set Port VID Step 2:set Group mapping */ /* set port VID */ /* vlan_pvid(board_info_t, port_num, VID)*/ vlan_port_vid(db,0,1);/* P0 VID=1 */ vlan_port_vid(db,1,2);/* P1 VID=2 */ vlan_port_vid(db,3,3);/* P3 VID=3 */ /* group mapping */ vlan_group_map(db, VLAN_GROUP1, MAKE_MASK(1, 0, 0, 1));/* Group1 : P3, P0 */ vlan_group_map(db, VLAN_GROUP2, MAKE_MASK(1, 0, 0, 1));/* Group2 : P3, P0 */ vlan_group_map(db, VLAN_GROUP3, MAKE_MASK(1, 0, 1, 1));/* Group3 : P3, P1, P0*/ }}static int vlan_port_vid(board_info_t *db, int port, u8 VID){ if((port<0)||(port > 3)) { printk("<DM9SW>Port number error\n "); return 1; } iow(db, DM9KS_PIndex, port); iow(db, DM9KS_VLAN_TAGL, VID); return 0;}static int vlan_outpkt_tag(board_info_t *db, int port){ if(port < 0 || port > 3) { printk("<DM9SW>Port number error \n"); return 1; } iow(db, DM9KS_PIndex, port); iow(db, DM9KS_PPRI, ior(db,DM9KS_PPRI)|0x80); return 0;}static int qos_port_pri(board_info_t *db, int port, u8 priority){ u8 tmp; if(port < 0 || port > 3) { printk("<DM9SW>Port number error\n "); return 1; } iow(db, DM9KS_PIndex, port); tmp = (ior(db,DM9KS_PPRI)&0xfc)|priority; iow(db, DM9KS_PPRI,tmp); return 0;}static int qos_tos_enable(board_info_t *db, int port){ if(port < 0 || port > 3) { printk("<DM9SW>Port number error\n "); return 1; } iow(db, DM9KS_PIndex, port); iow(db, DM9KS_PPRI,ior(db,DM9KS_PPRI)|0x8); return 0;}static void QoS_SETUP(board_info_t *db, int QoS_type){ switch (QoS_type) { case 0: /* port */ printk("<DM9SW>Port Priority\n"); qos_port_pri(db,0,0); /* set P0 queue0 */ qos_port_pri(db,1,1); /* set P1 queue1 */ qos_port_pri(db,2,2); /* set P2 queue2 */ qos_port_pri(db,3,3); /* set P3 queue3 */ break; case 1: /* Tag */ /* TAG-VLAN format | 0x8100 | vlan-priority(3bit)| CFI(1bit) | VID(12bit)| VLAN-TAG priority (default) Queue 0 : vlan-priority = 0 & 1 Queue 1 : vlan-priority = 2 & 3 Queue 2 : vlan-priority = 4 & 5 Queue 3 : vlan-priority = 6 & 7 if you want to modify the priority map, please refer reg0xC0 and reg0xC1 */ printk("<DM9SW>VLAN-TAG Priority\n"); break; case 2: /* TOS */ printk("<DM9SW>TOS Priority\n"); //check most significant 6-bit of TOS //iow(db, DM9KS_VLANCR, ior(db,DM9KS_VLANCR)|0x80); qos_tos_enable(db,0); qos_tos_enable(db,1); qos_tos_enable(db,2); qos_tos_enable(db,3); /*if you want to modify the priority map, if reg0x53.[7]=1 please refer reg0xC0~reg0xCF else please refer reg0xC0 and reg0xC1 */ break; }}/* bw_type refer to reg 61H.3*/static int dm9k_bw_control(board_info_t *db, int port, u8 bw_type, u8 bit74, u8 bit30){ u8 tmp; printk("<DM9SW>Bandwidth control\n"); if(port < 0 || port > 3) { printk("<DM9SW>Port number error \n"); return 1; } iow(db, DM9KS_PIndex, port);/* set port index */ tmp = (ior(db,DM9KS_PCTRL)& 0xf7); /* clear bit3 */ bit74 &= 0x0f; bit30 &= 0x0f; if (bw_type==0) { iow(db, DM9KS_PCTRL, tmp); /* per-port Ingress/Egress control */ //Reg.66H [7:4]=RX,[3:0]=TX iow(db, DM9KS_PRATE, (bit74<<4)|bit30); }else{ /* bw_type ==1*/ tmp|= 0x8; iow(db, DM9KS_PCTRL, tmp); tmp = (ior(db, DM9KS_PBW)&0xf0)|bit30; iow(db, DM9KS_PBW, tmp); } return 0;}/* Hardware start transmission. Send a packet to media from the upper layer.*/static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev){ board_info_t *db = (board_info_t *)dev->priv; char * data_ptr; if (db->tx_pkt_cnt >= 2) return 1; /* packet counting */ db->tx_pkt_cnt++; db->stats.tx_packets++; db->stats.tx_bytes+=skb->len; // FIFO has fulled already if (db->tx_pkt_cnt == 2) { netif_stop_queue(dev); db->stop_transmit =1; } /* Disable all interrupt */ iow(db, DM9KS_IMR, DM9KS_DISINTR); /* Set TX length to reg. 0xfc & 0xfd */ iow(db, DM9KS_TXPLL, (skb->len & 0xff)); iow(db, DM9KS_TXPLH, (skb->len >> 8) & 0xff); /* Move data to TX SRAM */ data_ptr = (char *)skb->data; outb(DM9KS_MWCMD, db->io_addr); // Write data into SRAM trigger db->MoveData(db, data_ptr, skb->len, 1); /* Issue TX polling command */ iow(db, DM9KS_TCR, TCR_TX_Request); /* Saved the time stamp */ dev->trans_start = jiffies; db->cont_rx_pkt_cnt =0; /* Free this SKB */ dev_kfree_skb(skb); /* Re-enable interrupt */ iow(db, DM9KS_IMR, DM9KS_REGFF); return 0;}/* Stop the interface. The interface is stopped when it is brought.*/static int dmfe_stop(struct net_device *dev){ board_info_t *db = (board_info_t *)dev->priv; int i; DMFE_DBUG(0, "dmfe_stop", 0); /* deleted timer */ del_timer(&db->timer); netif_stop_queue(dev); /* free interrupt */ free_irq(dev->irq, dev); /* RESET devie */ for (i=0; i<=db->port_mode; i++) phy_write(db, 0x00, 0x8000,i); /* PHY RESET */ dm9sw_switch_reset(db); iow(db, 0, 1); /* software reset */ iow(db, 0x52, 0x60); /* reset switch core and analog PHY core */ iow(db, DM9KS_RXCR, 0x00); /* Disable RX */ iow(db, DM9KS_IMR, DM9KS_DISINTR); /* Disable all interrupt */ /* Dump Statistic counter */#if FALSE 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("RESET %x\n", db->reset_counter); printk("RESET: TX Timeout %x\n", db->reset_tx_timeout); printk("g_TX_nsr %x\n", g_TX_nsr);#endif return 0;}static void dmfe_tx_done(unsigned long unused){ struct net_device *dev = dmfe_dev; board_info_t *db = (board_info_t *)dev->priv; u8 nsr; DMFE_DBUG(0, "dmfe_tx_done()", 0); nsr = ior(db, DM9KS_NSR); iow(db, DM9KS_NSR, nsr); /* clear TX packet complete status */ if(nsr & NSR_TX1END) db->tx_pkt_cnt--; if(nsr & NSR_TX2END) db->tx_pkt_cnt--; if (db->tx_pkt_cnt < 0) { printk("[dmfe_tx_done] tx_pkt_cnt ERROR!!\n"); db->tx_pkt_cnt =0; } if(db->stop_transmit ) { netif_wake_queue(dev); db->stop_transmit=0; } return;}/* DM9000 insterrupt handler receive the packet to upper layer, free the transmitted packet*/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)#elsestatic irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)#endif{ struct net_device *dev = dev_id; board_info_t *db; int int_status; u8 reg_save; DMFE_DBUG(0, "dmfe_interrupt()", 0); /* A real interrupt coming */ db = (board_info_t *)dev->priv; spin_lock(&db->lock); /* Save previous register address */ reg_save = inb(db->io_addr); /* disable IMR */ iow(db, DM9KS_IMR, 0x80); /* Got DM9000A/DM9010 interrupt status */ int_status = ior(db, DM9KS_ISR); /* Got ISR */ iow(db, DM9KS_ISR, int_status); /* Clear ISR status */ /* Trnasmit Interrupt check */ if (int_status & ISR_TX_complete) dmfe_tx_done(0); /* Received the coming packet */ if (int_status & ISR_RX_coming) #ifdef NAPI { if (netif_rx_schedule_prep(dev)) { iow(db, DM9KS_IMR,DM9KS_NO_RX_INTR); __netif_rx_schedule(dev); } }#else dmfe_packet_receive(dev);#endif iow(db, DM9KS_IMR, DM9KS_REGFF); /* Restore previous register address */ outb(reg_save, db->io_addr); spin_unlock(&db->lock); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) return IRQ_HANDLED;#endif}#if !defined(CHECKSUM)#define check_rx_ready(a) ((a) == 0x01)#elseinline u8 check_rx_ready(u8 rxbyte){ if (!(rxbyte & 0x01)) return 0; return ((rxbyte >> 4) | 0x01);}#endif#ifdef NAPIstatic int dmfe_poll (struct net_device *dev, int *budget){ board_info_t *db = (board_info_t *)dev->priv; struct sk_buff *skb; u8 rxbyte, val; u16 MDRAH, MDRAL; u32 tmpdata; unsigned rx_work = dev->quota; unsigned rx; rx_t rx_desc; u8 * ptr = (u8 *)&rx_desc; u8 * rdptr;rx_status_loop: rx = 0; iow(db, DM9KS_ISR, ISR_RX_coming); //clean this bit while(1){ /*store the value of Memory Data Read address register*/ MDRAH=ior(db, DM9KS_MDRAH); MDRAL=ior(db, DM9KS_MDRAL); rxbyte =ior(db, DM9KS_MRCMDX); rxbyte =ior(db, DM9KS_ISR); /* Dummy read */ rxbyte =ior(db, DM9KS_MRCMDX); /* read the byte of packet ready */ /* packet ready to receive check */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -