📄 3c359.c
字号:
int i ; if (dev->flags & IFF_PROMISC) options = 0x0004 ; else options = 0x0000 ; if (options ^ xl_priv->xl_copy_all_options) { /* Changed, must send command */ xl_priv->xl_copy_all_options = options ; xl_srb_cmd(dev, SET_RECEIVE_MODE) ; return ; } dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { dev_mc_address[0] |= dmi->dmi_addr[2] ; dev_mc_address[1] |= dmi->dmi_addr[3] ; dev_mc_address[2] |= dmi->dmi_addr[4] ; dev_mc_address[3] |= dmi->dmi_addr[5] ; } if (memcmp(xl_priv->xl_functional_addr,dev_mc_address,4) != 0) { /* Options have changed, run the command */ memcpy(xl_priv->xl_functional_addr, dev_mc_address,4) ; xl_srb_cmd(dev, SET_FUNC_ADDRESS) ; } return ; }/* * We issued an srb command and now we must read * the response from the completed command. */static void xl_srb_bh(struct net_device *dev) { struct xl_private *xl_priv = (struct xl_private *) dev->priv ; u8 __iomem * xl_mmio = xl_priv->xl_mmio ; u8 srb_cmd, ret_code ; int i ; writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; srb_cmd = readb(xl_mmio + MMIO_MACDATA) ; writel((MEM_BYTE_READ | 0xd0000 | xl_priv->srb) +2, xl_mmio + MMIO_MAC_ACCESS_CMD) ; ret_code = readb(xl_mmio + MMIO_MACDATA) ; /* Ret_code is standard across all commands */ switch (ret_code) { case 1: printk(KERN_INFO "%s: Command: %d - Invalid Command code\n",dev->name,srb_cmd) ; break ; case 4: printk(KERN_INFO "%s: Command: %d - Adapter is closed, must be open for this command \n",dev->name,srb_cmd) ; break ; case 6: printk(KERN_INFO "%s: Command: %d - Options Invalid for command \n",dev->name,srb_cmd) ; break ; case 0: /* Successful command execution */ switch (srb_cmd) { case READ_LOG: /* Returns 14 bytes of data from the NIC */ if(xl_priv->xl_message_level) printk(KERN_INFO "%s: READ.LOG 14 bytes of data ",dev->name) ; /* * We still have to read the log even if message_level = 0 and we don't want * to see it */ for (i=0;i<14;i++) { writel(MEM_BYTE_READ | 0xd0000 | xl_priv->srb | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; if(xl_priv->xl_message_level) printk("%02x:",readb(xl_mmio + MMIO_MACDATA)) ; } printk("\n") ; break ; case SET_FUNC_ADDRESS: if(xl_priv->xl_message_level) printk(KERN_INFO "%s: Functional Address Set \n",dev->name) ; break ; case CLOSE_NIC: if(xl_priv->xl_message_level) printk(KERN_INFO "%s: Received CLOSE_NIC interrupt in interrupt handler \n",dev->name) ; break ; case SET_MULTICAST_MODE: if(xl_priv->xl_message_level) printk(KERN_INFO "%s: Multicast options successfully changed\n",dev->name) ; break ; case SET_RECEIVE_MODE: if(xl_priv->xl_message_level) { if (xl_priv->xl_copy_all_options == 0x0004) printk(KERN_INFO "%s: Entering promiscuous mode \n", dev->name) ; else printk(KERN_INFO "%s: Entering normal receive mode \n",dev->name) ; } break ; } /* switch */ break ; } /* switch */ return ; } static struct net_device_stats * xl_get_stats(struct net_device *dev){ struct xl_private *xl_priv = (struct xl_private *) dev->priv ; return (struct net_device_stats *) &xl_priv->xl_stats; }static int xl_set_mac_address (struct net_device *dev, void *addr) { struct sockaddr *saddr = addr ; struct xl_private *xl_priv = (struct xl_private *)dev->priv ; if (netif_running(dev)) { printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ; return -EIO ; } memcpy(xl_priv->xl_laa, saddr->sa_data,dev->addr_len) ; if (xl_priv->xl_message_level) { printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n",dev->name, xl_priv->xl_laa[0], xl_priv->xl_laa[1], xl_priv->xl_laa[2], xl_priv->xl_laa[3], xl_priv->xl_laa[4], xl_priv->xl_laa[5]); } return 0 ; }static void xl_arb_cmd(struct net_device *dev){ struct xl_private *xl_priv = (struct xl_private *) dev->priv; u8 __iomem * xl_mmio = xl_priv->xl_mmio ; u8 arb_cmd ; u16 lan_status, lan_status_diff ; writel( ( MEM_BYTE_READ | 0xD0000 | xl_priv->arb), xl_mmio + MMIO_MAC_ACCESS_CMD) ; arb_cmd = readb(xl_mmio + MMIO_MACDATA) ; if (arb_cmd == RING_STATUS_CHANGE) { /* Ring.Status.Change */ writel( ( (MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ; printk(KERN_INFO "%s: Ring Status Change: New Status = %04x\n", dev->name, ntohs(readw(xl_mmio + MMIO_MACDATA) )) ; lan_status = ntohs(readw(xl_mmio + MMIO_MACDATA)); /* Acknowledge interrupt, this tells nic we are done with the arb */ writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; lan_status_diff = xl_priv->xl_lan_status ^ lan_status ; if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR) ) { if (lan_status_diff & LSC_LWF) printk(KERN_WARNING "%s: Short circuit detected on the lobe\n",dev->name); if (lan_status_diff & LSC_ARW) printk(KERN_WARNING "%s: Auto removal error\n",dev->name); if (lan_status_diff & LSC_FPE) printk(KERN_WARNING "%s: FDX Protocol Error\n",dev->name); if (lan_status_diff & LSC_RR) printk(KERN_WARNING "%s: Force remove MAC frame received\n",dev->name); /* Adapter has been closed by the hardware */ netif_stop_queue(dev); xl_freemem(dev) ; free_irq(dev->irq,dev); printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; } /* If serious error */ if (xl_priv->xl_message_level) { if (lan_status_diff & LSC_SIG_LOSS) printk(KERN_WARNING "%s: No receive signal detected \n", dev->name) ; if (lan_status_diff & LSC_HARD_ERR) printk(KERN_INFO "%s: Beaconing \n",dev->name); if (lan_status_diff & LSC_SOFT_ERR) printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n",dev->name); if (lan_status_diff & LSC_TRAN_BCN) printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name); if (lan_status_diff & LSC_SS) printk(KERN_INFO "%s: Single Station on the ring \n", dev->name); if (lan_status_diff & LSC_RING_REC) printk(KERN_INFO "%s: Ring recovery ongoing\n",dev->name); if (lan_status_diff & LSC_FDX_MODE) printk(KERN_INFO "%s: Operating in FDX mode\n",dev->name); } if (lan_status_diff & LSC_CO) { if (xl_priv->xl_message_level) printk(KERN_INFO "%s: Counter Overflow \n", dev->name); /* Issue READ.LOG command */ xl_srb_cmd(dev, READ_LOG) ; } /* There is no command in the tech docs to issue the read_sr_counters */ if (lan_status_diff & LSC_SR_CO) { if (xl_priv->xl_message_level) printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name); } xl_priv->xl_lan_status = lan_status ; } /* Lan.change.status */ else if ( arb_cmd == RECEIVE_DATA) { /* Received.Data */#if XL_DEBUG printk(KERN_INFO "Received.Data \n") ; #endif writel( ((MEM_WORD_READ | 0xD0000 | xl_priv->arb) + 6), xl_mmio + MMIO_MAC_ACCESS_CMD) ; xl_priv->mac_buffer = ntohs(readw(xl_mmio + MMIO_MACDATA)) ; /* Now we are going to be really basic here and not do anything * with the data at all. The tech docs do not give me enough * information to calculate the buffers properly so we're * just going to tell the nic that we've dealt with the frame * anyway. */ dev->last_rx = jiffies ; /* Acknowledge interrupt, this tells nic we are done with the arb */ writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; /* Is the ASB free ? */ xl_priv->asb_queued = 0 ; writel( ((MEM_BYTE_READ | 0xD0000 | xl_priv->asb) + 2), xl_mmio + MMIO_MAC_ACCESS_CMD) ; if (readb(xl_mmio + MMIO_MACDATA) != 0xff) { xl_priv->asb_queued = 1 ; xl_wait_misr_flags(dev) ; writel(MEM_BYTE_WRITE | MF_ASBFR, xl_mmio + MMIO_MAC_ACCESS_CMD); writeb(0xff, xl_mmio + MMIO_MACDATA) ; writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(MISR_ASBFR, xl_mmio + MMIO_MACDATA) ; return ; /* Drop out and wait for the bottom half to be run */ } xl_asb_cmd(dev) ; } else { printk(KERN_WARNING "%s: Received unknown arb (xl_priv) command: %02x \n",dev->name,arb_cmd) ; } /* Acknowledge the arb interrupt */ writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK , xl_mmio + MMIO_COMMAND) ; return ; }/* * There is only one asb command, but we can get called from different * places. */static void xl_asb_cmd(struct net_device *dev){ struct xl_private *xl_priv = (struct xl_private *) dev->priv ; u8 __iomem * xl_mmio = xl_priv->xl_mmio ; if (xl_priv->asb_queued == 1) writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ; writel(MEM_BYTE_WRITE | 0xd0000 | xl_priv->asb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(0x81, xl_mmio + MMIO_MACDATA) ; writel(MEM_WORD_WRITE | 0xd0000 | xl_priv->asb | 6, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writew(ntohs(xl_priv->mac_buffer), xl_mmio + MMIO_MACDATA) ; xl_wait_misr_flags(dev) ; writel(MEM_BYTE_WRITE | MF_RASB, xl_mmio + MMIO_MAC_ACCESS_CMD); writeb(0xff, xl_mmio + MMIO_MACDATA) ; writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(MISR_RASB, xl_mmio + MMIO_MACDATA) ; xl_priv->asb_queued = 2 ; return ; }/* * This will only get called if there was an error * from the asb cmd. */static void xl_asb_bh(struct net_device *dev) { struct xl_private *xl_priv = (struct xl_private *) dev->priv ; u8 __iomem * xl_mmio = xl_priv->xl_mmio ; u8 ret_code ; writel(MMIO_BYTE_READ | 0xd0000 | xl_priv->asb | 2, xl_mmio + MMIO_MAC_ACCESS_CMD) ; ret_code = readb(xl_mmio + MMIO_MACDATA) ; switch (ret_code) { case 0x01: printk(KERN_INFO "%s: ASB Command, unrecognized command code \n",dev->name) ; break ; case 0x26: printk(KERN_INFO "%s: ASB Command, unexpected receive buffer \n", dev->name) ; break ; case 0x40: printk(KERN_INFO "%s: ASB Command, Invalid Station ID \n", dev->name) ; break ; } xl_priv->asb_queued = 0 ; writel(ACK_INTERRUPT | LATCH_ACK | ASBFACK, xl_mmio + MMIO_COMMAND) ; return ; }/* * Issue srb commands to the nic */static void xl_srb_cmd(struct net_device *dev, int srb_cmd) { struct xl_private *xl_priv = (struct xl_private *) dev->priv ; u8 __iomem * xl_mmio = xl_priv->xl_mmio ; switch (srb_cmd) { case READ_LOG: writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(READ_LOG, xl_mmio + MMIO_MACDATA) ; break; case CLOSE_NIC: writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(CLOSE_NIC, xl_mmio + MMIO_MACDATA) ; break ; case SET_RECEIVE_MODE: writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(SET_RECEIVE_MODE, xl_mmio + MMIO_MACDATA) ; writel(MEM_WORD_WRITE | 0xD0000 | xl_priv->srb | 4, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writew(xl_priv->xl_copy_all_options, xl_mmio + MMIO_MACDATA) ; break ; case SET_FUNC_ADDRESS: writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(SET_FUNC_ADDRESS, xl_mmio + MMIO_MACDATA) ; writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 6 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(xl_priv->xl_functional_addr[0], xl_mmio + MMIO_MACDATA) ; writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 7 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(xl_priv->xl_functional_addr[1], xl_mmio + MMIO_MACDATA) ; writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 8 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(xl_priv->xl_functional_addr[2], xl_mmio + MMIO_MACDATA) ; writel(MEM_BYTE_WRITE | 0xD0000 | xl_priv->srb | 9 , xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(xl_priv->xl_functional_addr[3], xl_mmio + MMIO_MACDATA) ; break ; } /* switch */ xl_wait_misr_flags(dev) ; /* Write 0xff to the CSRB flag */ writel(MEM_BYTE_WRITE | MF_CSRB , xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(0xFF, xl_mmio + MMIO_MACDATA) ; /* Set csrb bit in MISR register to process command */ writel(MMIO_BYTE_WRITE | MISR_SET, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(MISR_CSRB, xl_mmio + MMIO_MACDATA) ; xl_priv->srb_queued = 1 ; return ; }/* * This is nasty, to use the MISR command you have to wait for 6 memory locations * to be zero. This is the way the driver does on other OS'es so we should be ok with * the empty loop. */static void xl_wait_misr_flags(struct net_device *dev) { struct xl_private *xl_priv = (struct xl_private *) dev->priv ; u8 __iomem * xl_mmio = xl_priv->xl_mmio ; int i ; writel(MMIO_BYTE_READ | MISR_RW, xl_mmio + MMIO_MAC_ACCESS_CMD) ; if (readb(xl_mmio + MMIO_MACDATA) != 0) { /* Misr not clear */ for (i=0; i<6; i++) { writel(MEM_BYTE_READ | 0xDFFE0 | i, xl_mmio + MMIO_MAC_ACCESS_CMD) ; while (readb(xl_mmio + MMIO_MACDATA) != 0 ) {} ; /* Empty Loop */ } } writel(MMIO_BYTE_WRITE | MISR_AND, xl_mmio + MMIO_MAC_ACCESS_CMD) ; writeb(0x80, xl_mmio + MMIO_MACDATA) ; return ; } /* * Change mtu size, this should work the same as olympic */static int xl_change_mtu(struct net_device *dev, int mtu) { struct xl_private *xl_priv = (struct xl_private *) dev->priv; u16 max_mtu ; if (xl_priv->xl_ring_speed == 4) max_mtu = 4500 ; else max_mtu = 18000 ; if (mtu > max_mtu) return -EINVAL ; if (mtu < 100) return -EINVAL ; dev->mtu = mtu ; xl_priv->pkt_buf_sz = mtu + TR_HLEN ; return 0 ; }static void __devexit xl_remove_one (struct pci_dev *pdev){ struct net_device *dev = pci_get_drvdata(pdev); struct xl_private *xl_priv=(struct xl_private *)dev->priv; unregister_netdev(dev); iounmap(xl_priv->xl_mmio) ; pci_release_regions(pdev) ; pci_set_drvdata(pdev,NULL) ; free_netdev(dev); return ; }static struct pci_driver xl_3c359_driver = { .name = "3c359", .id_table = xl_pci_tbl, .probe = xl_probe, .remove = __devexit_p(xl_remove_one),};static int __init xl_pci_init (void){ return pci_module_init (&xl_3c359_driver);}static void __exit xl_pci_cleanup (void){ pci_unregister_driver (&xl_3c359_driver);}module_init(xl_pci_init);module_exit(xl_pci_cleanup);MODULE_LICENSE("GPL") ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -