📄 olympic.c
字号:
return IRQ_HANDLED;} static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio; unsigned long flags ; spin_lock_irqsave(&olympic_priv->olympic_lock, flags); netif_stop_queue(dev); if(olympic_priv->free_tx_ring_entries) { olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer = cpu_to_le32(pci_map_single(olympic_priv->pdev, skb->data, skb->len,PCI_DMA_TODEVICE)); olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length = cpu_to_le32(skb->len | (0x80000000)); olympic_priv->tx_ring_skb[olympic_priv->tx_ring_free]=skb; olympic_priv->free_tx_ring_entries--; olympic_priv->tx_ring_free++; olympic_priv->tx_ring_free &= (OLYMPIC_TX_RING_SIZE-1); writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1); netif_wake_queue(dev); spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); return 0; } else { spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); return 1; } } static int olympic_close(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*srb; unsigned long t,flags; DECLARE_WAITQUEUE(wait,current) ; netif_stop_queue(dev); writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); writeb(SRB_CLOSE_ADAPTER,srb+0); writeb(0,srb+1); writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); add_wait_queue(&olympic_priv->srb_wait,&wait) ; set_current_state(TASK_INTERRUPTIBLE) ; spin_lock_irqsave(&olympic_priv->olympic_lock,flags); olympic_priv->srb_queued=1; writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags); while(olympic_priv->srb_queued) { t = schedule_timeout_interruptible(60*HZ); if(signal_pending(current)) { printk(KERN_WARNING "%s: SRB timed out.\n",dev->name); printk(KERN_WARNING "SISR=%x MISR=%x\n",readl(olympic_mmio+SISR),readl(olympic_mmio+LISR)); olympic_priv->srb_queued=0; break; } if (t == 0) { printk(KERN_WARNING "%s: SRB timed out. May not be fatal. \n",dev->name) ; } olympic_priv->srb_queued=0; } remove_wait_queue(&olympic_priv->srb_wait,&wait) ; olympic_priv->rx_status_last_received++; olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1; olympic_freemem(dev) ; /* reset tx/rx fifo's and busmaster logic */ writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL); udelay(1); writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);#if OLYMPIC_DEBUG { int i ; printk("srb(%p): ",srb); for(i=0;i<4;i++) printk("%x ",readb(srb+i)); printk("\n"); }#endif free_irq(dev->irq,dev); return 0; }static void olympic_set_rx_mode(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; u8 options = 0; u8 __iomem *srb; struct dev_mc_list *dmi ; unsigned char dev_mc_address[4] ; int i ; writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); options = olympic_priv->olympic_copy_all_options; if (dev->flags&IFF_PROMISC) options |= 0x61 ; else options &= ~0x61 ; /* Only issue the srb if there is a change in options */ if ((options ^ olympic_priv->olympic_copy_all_options)) { /* Now to issue the srb command to alter the copy.all.options */ writeb(SRB_MODIFY_RECEIVE_OPTIONS,srb); writeb(0,srb+1); writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); writeb(0,srb+3); writeb(olympic_priv->olympic_receive_options,srb+4); writeb(options,srb+5); olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); olympic_priv->olympic_copy_all_options = options ; return ; } /* Set the functional addresses we need for multicast */ 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] ; } writeb(SRB_SET_FUNC_ADDRESS,srb+0); writeb(0,srb+1); writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); writeb(0,srb+3); writeb(0,srb+4); writeb(0,srb+5); writeb(dev_mc_address[0],srb+6); writeb(dev_mc_address[1],srb+7); writeb(dev_mc_address[2],srb+8); writeb(dev_mc_address[3],srb+9); olympic_priv->srb_queued = 2 ; writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);}static void olympic_srb_bh(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; u8 __iomem *olympic_mmio = olympic_priv->olympic_mmio ; u8 __iomem *srb; writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); switch (readb(srb)) { /* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous) * At some point we should do something if we get an error, such as * resetting the IFF_PROMISC flag in dev */ case SRB_MODIFY_RECEIVE_OPTIONS: switch (readb(srb+2)) { case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command\n",dev->name) ; break ; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name); break ; default: if (olympic_priv->olympic_message_level) printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n",dev->name,olympic_priv->olympic_copy_all_options, olympic_priv->olympic_receive_options) ; break ; } /* switch srb[2] */ break ; /* SRB_SET_GROUP_ADDRESS - Multicast group setting */ case SRB_SET_GROUP_ADDRESS: switch (readb(srb+2)) { case 0x00: break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; break ; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name); break ; case 0x3c: printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n",dev->name) ; break ; case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */ printk(KERN_WARNING "%s: Group address registers full\n",dev->name) ; break ; case 0x55: printk(KERN_INFO "%s: Group Address already set.\n",dev->name) ; break ; default: break ; } /* switch srb[2] */ break ; /* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list */ case SRB_RESET_GROUP_ADDRESS: switch (readb(srb+2)) { case 0x00: break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; break ; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; break ; case 0x39: /* Must deal with this if individual multicast addresses used */ printk(KERN_INFO "%s: Group address not found \n",dev->name); break ; default: break ; } /* switch srb[2] */ break ; /* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode */ case SRB_SET_FUNC_ADDRESS: switch (readb(srb+2)) { case 0x00: if (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Functional Address Mask Set \n",dev->name) ; break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; break ; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; break ; default: break ; } /* switch srb[2] */ break ; /* SRB_READ_LOG - Read and reset the adapter error counters */ case SRB_READ_LOG: switch (readb(srb+2)) { case 0x00: if (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Read Log issued\n",dev->name) ; break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; break ; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; break ; } /* switch srb[2] */ break ; /* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */ case SRB_READ_SR_COUNTERS: switch (readb(srb+2)) { case 0x00: if (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Read Source Routing Counters issued\n",dev->name) ; break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; break ; case 0x04: printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; break ; default: break ; } /* switch srb[2] */ break ; default: printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n",dev->name); break ; } /* switch srb[0] */} static struct net_device_stats * olympic_get_stats(struct net_device *dev){ struct olympic_private *olympic_priv ; olympic_priv=(struct olympic_private *) dev->priv; return (struct net_device_stats *) &olympic_priv->olympic_stats; }static int olympic_set_mac_address (struct net_device *dev, void *addr) { struct sockaddr *saddr = addr ; struct olympic_private *olympic_priv = (struct olympic_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(olympic_priv->olympic_laa, saddr->sa_data,dev->addr_len) ; if (olympic_priv->olympic_message_level) { printk(KERN_INFO "%s: MAC/LAA Set to = %x.%x.%x.%x.%x.%x\n",dev->name, olympic_priv->olympic_laa[0], olympic_priv->olympic_laa[1], olympic_priv->olympic_laa[2], olympic_priv->olympic_laa[3], olympic_priv->olympic_laa[4], olympic_priv->olympic_laa[5]); } return 0 ; }static void olympic_arb_cmd(struct net_device *dev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -