📄 olympic.c
字号:
pci_unmap_single(olympic_priv->pdev, olympic_priv->tx_ring_dma_addr, sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE, PCI_DMA_TODEVICE); /* 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 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 *olympic_mmio = olympic_priv->olympic_mmio ; u8 options = 0; u8 *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 *olympic_mmio = olympic_priv->olympic_mmio ; u8 *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){ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; u8 *olympic_mmio=olympic_priv->olympic_mmio; u8 *arb_block, *asb_block, *srb ; u8 header_len ; u16 frame_len, buffer_len ; struct sk_buff *mac_frame ; u8 *buf_ptr ; u8 *frame_data ; u16 buff_off ; u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */ u8 fdx_prot_error ; u16 next_ptr; int i ; arb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; asb_block = (u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; srb = (u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; writel(readl(olympic_mmio+LAPA),olympic_mmio+LAPWWO); if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */ header_len = readb(arb_block+8) ; /* 802.5 Token-Ring Header Length */ frame_len = swab16(readw(arb_block + 10)) ; buff_off = swab16(readw(arb_block + 6)) ; buf_ptr = olympic_priv->olympic_lap + buff_off ; #if OLYMPIC_DEBUG{ int i; frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; for (i=0 ; i < 14 ; i++) { printk("Loc %d = %02x\n",i,readb(frame_data + i)); } printk("next %04x, fs %02x, len %04x \n",readw(buf_ptr+offsetof(struct mac_receive_buffer,next)), readb(buf_ptr+offsetof(struct mac_receive_buffer,frame_status)), readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); }#endif mac_frame = dev_alloc_skb(frame_len) ; if (!mac_frame) { printk(KERN_WARNING "%s: Memory squeeze, dropping frame.\n", dev->name); goto drop_frame; } /* Walk the buffer chain, creating the frame */ do { frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; buffer_len = swab16(readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); memcpy_fromio(skb_put(mac_frame, buffer_len), frame_data , buffer_len ) ; next_ptr=readw(buf_ptr+offsetof(struct mac_receive_buffer,next)); } while (next_ptr && (buf_ptr=olympic_priv->olympic_lap + ntohs(next_ptr))); if (olympic_priv->olympic_network_monitor) { struct trh_hdr *mac_hdr ; printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name) ; mac_hdr = (struct trh_hdr *)mac_frame->data ; printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->daddr[0], mac_hdr->daddr[1], mac_hdr->daddr[2], mac_hdr->daddr[3], mac_hdr->daddr[4], mac_hdr->daddr[5]) ; printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->saddr[0], mac_hdr->saddr[1], mac_hdr->saddr[2], mac_hdr->saddr[3], mac_hdr->saddr[4], mac_hdr->saddr[5]) ; } mac_frame->dev = dev ; mac_frame->protocol = tr_type_trans(mac_frame,dev); netif_rx(mac_frame) ; dev->last_rx = jiffies;drop_frame: /* Now tell the card we have dealt with the received frame */ /* Set LISR Bit 1 */ writel(LISR_ARB_FREE,olympic_priv->olympic_lap + LISR_SUM); /* Is the ASB free ? */ if (readb(asb_block + 2) != 0xff) { olympic_priv->asb_queued = 1 ; writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); return ; /* Drop out and wait for the bottom half to be run */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -