📄 olympic.c
字号:
int i; printk("init_srb(%p): ",init_srb); for(i=0;i<20;i++) printk("%x ",readb(init_srb+i)); printk("\n");}#endif if(readw(init_srb+6)) { printk(KERN_INFO "tokenring card intialization failed. errorcode : %x\n",readw(init_srb+6)); return -ENODEV; } if (olympic_priv->olympic_message_level) { if ( readb(init_srb +2) & 0x40) { printk(KERN_INFO "Olympic: Adapter is FDX capable.\n") ; } else { printk(KERN_INFO "Olympic: Adapter cannot do FDX.\n"); } } uaa_addr=swab16(readw(init_srb+8));#if OLYMPIC_DEBUG printk("UAA resides at %x\n",uaa_addr);#endif writel(uaa_addr,olympic_mmio+LAPA); adapter_addr=olympic_priv->olympic_lap + (uaa_addr & (~0xf800));#if OLYMPIC_DEBUG printk("adapter address: %02x:%02x:%02x:%02x:%02x:%02x\n", readb(adapter_addr), readb(adapter_addr+1),readb(adapter_addr+2), readb(adapter_addr+3),readb(adapter_addr+4),readb(adapter_addr+5));#endif memcpy_fromio(&dev->dev_addr[0], adapter_addr,6); olympic_priv->olympic_addr_table_addr = swab16(readw(init_srb + 12)); olympic_priv->olympic_parms_addr = swab16(readw(init_srb + 14)); return 0;}static int olympic_open(struct net_device *dev) { struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb; unsigned long flags, t; char open_error[255] ; int i, open_finished = 1 ; if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) { return -EAGAIN; }#if OLYMPIC_DEBUG printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM)); printk("pending ints: %x\n",readl(olympic_mmio+SISR_RR));#endif writel(SISR_MI,olympic_mmio+SISR_MASK_SUM); writel(SISR_MI | SISR_SRB_REPLY, olympic_mmio+SISR_MASK); /* more ints later, doesn't stop arb cmd interrupt */ writel(LISR_LIE,olympic_mmio+LISR); /* more ints later */ /* adapter is closed, so SRB is pointed to by LAPWWO */ writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA); init_srb=olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWO)) & (~0xf800)); #if OLYMPIC_DEBUG printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA)); printk("SISR Mask = %04x\n", readl(olympic_mmio+SISR_MASK)); printk("Before the open command \n");#endif do { int i; save_flags(flags); cli(); for(i=0;i<SRB_COMMAND_SIZE;i+=4) writel(0,init_srb+i); if(SRB_COMMAND_SIZE & 2) writew(0,init_srb+(SRB_COMMAND_SIZE & ~3)); if(SRB_COMMAND_SIZE & 1) writeb(0,init_srb+(SRB_COMMAND_SIZE & ~1)); writeb(SRB_OPEN_ADAPTER,init_srb) ; /* open */ writeb(OLYMPIC_CLEAR_RET_CODE,init_srb+2); /* If Network Monitor, instruct card to copy MAC frames through the ARB */ if (olympic_priv->olympic_network_monitor) writew(swab16(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON), init_srb+8); else writew(swab16(OPEN_ADAPTER_ENABLE_FDX), init_srb+8); if (olympic_priv->olympic_laa[0]) { writeb(olympic_priv->olympic_laa[0],init_srb+12); writeb(olympic_priv->olympic_laa[1],init_srb+13); writeb(olympic_priv->olympic_laa[2],init_srb+14); writeb(olympic_priv->olympic_laa[3],init_srb+15); writeb(olympic_priv->olympic_laa[4],init_srb+16); writeb(olympic_priv->olympic_laa[5],init_srb+17); memcpy(dev->dev_addr,olympic_priv->olympic_laa,dev->addr_len) ; } writeb(1,init_srb+30); olympic_priv->srb_queued=1; writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); t = jiffies ; while(olympic_priv->srb_queued) { interruptible_sleep_on_timeout(&olympic_priv->srb_wait, 60*HZ); if(signal_pending(current)) { printk(KERN_WARNING "%s: Signal received in open.\n", dev->name); printk(KERN_WARNING "SISR=%x LISR=%x\n", readl(olympic_mmio+SISR), readl(olympic_mmio+LISR)); olympic_priv->srb_queued=0; break; } if ((jiffies-t) > 60*HZ) { printk(KERN_WARNING "%s: SRB timed out. \n",dev->name) ; olympic_priv->srb_queued=0; break ; } } restore_flags(flags);#if OLYMPIC_DEBUG printk("init_srb(%p): ",init_srb); for(i=0;i<20;i++) printk("%02x ",readb(init_srb+i)); printk("\n");#endif /* If we get the same return response as we set, the interrupt wasn't raised and the open * timed out. */ if(readb(init_srb+2)== OLYMPIC_CLEAR_RET_CODE) { printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name) ; return -EIO ; } if(readb(init_srb+2)!=0) { if (readb(init_srb+2) == 0x07) { if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */ printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name); open_finished = 0 ; } else { strcpy(open_error, open_maj_error[(readb(init_srb+7) & 0xf0) >> 4]) ; strcat(open_error," - ") ; strcat(open_error, open_min_error[(readb(init_srb+7) & 0x0f)]) ; if (!olympic_priv->olympic_ring_speed && ((readb(init_srb+7) & 0x0f) == 0x0d)) { printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name); printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name); free_irq(dev->irq, dev); return -EIO ; } printk(KERN_WARNING "%s: %s\n",dev->name,open_error); free_irq(dev->irq,dev) ; return -EIO ; } /* if autosense && open_finished */ } else { printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name,init_srb[2]); free_irq(dev->irq, dev); return -EIO; } } else open_finished = 1 ; } while (!(open_finished)) ; /* Will only loop if ring speed mismatch re-open attempted && autosense is on */ if (readb(init_srb+18) & (1<<3)) if (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Opened in FDX Mode\n",dev->name); if (readb(init_srb+18) & (1<<1)) olympic_priv->olympic_ring_speed = 100 ; else if (readb(init_srb+18) & 1) olympic_priv->olympic_ring_speed = 16 ; else olympic_priv->olympic_ring_speed = 4 ; if (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Opened in %d Mbps mode\n",dev->name, olympic_priv->olympic_ring_speed); olympic_priv->asb = swab16(readw(init_srb+8)); olympic_priv->srb = swab16(readw(init_srb+10)); olympic_priv->arb = swab16(readw(init_srb+12)); olympic_priv->trb = swab16(readw(init_srb+16)); olympic_priv->olympic_receive_options = 0x01 ; olympic_priv->olympic_copy_all_options = 0 ; /* setup rx ring */ writel((3<<16),olympic_mmio+BMCTL_RWM); /* Ensure end of frame generated interrupts */ writel(BMCTL_RX_DIS|3,olympic_mmio+BMCTL_RWM); /* Yes, this the enables RX channel */ for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) { struct sk_buff *skb; skb=dev_alloc_skb(olympic_priv->pkt_buf_sz); if(skb == NULL) break; skb->dev = dev; olympic_priv->olympic_rx_ring[i].buffer = cpu_to_le32(pci_map_single(olympic_priv->pdev, skb->data,olympic_priv->pkt_buf_sz, PCI_DMA_FROMDEVICE)) ; olympic_priv->olympic_rx_ring[i].res_length = cpu_to_le32(olympic_priv->pkt_buf_sz); olympic_priv->rx_ring_skb[i]=skb; } if (i==0) { printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n",dev->name); free_irq(dev->irq, dev); return -EIO; } olympic_priv->rx_ring_dma_addr = pci_map_single(olympic_priv->pdev,olympic_priv->olympic_rx_ring, sizeof(struct olympic_rx_desc) * OLYMPIC_RX_RING_SIZE, PCI_DMA_TODEVICE); writel(olympic_priv->rx_ring_dma_addr, olympic_mmio+RXDESCQ); writel(olympic_priv->rx_ring_dma_addr, olympic_mmio+RXCDA); writew(i, olympic_mmio+RXDESCQCNT); olympic_priv->rx_status_ring_dma_addr = pci_map_single(olympic_priv->pdev, olympic_priv->olympic_rx_status_ring, sizeof(struct olympic_rx_status) * OLYMPIC_RX_RING_SIZE, PCI_DMA_FROMDEVICE); writel(olympic_priv->rx_status_ring_dma_addr, olympic_mmio+RXSTATQ); writel(olympic_priv->rx_status_ring_dma_addr, olympic_mmio+RXCSA); olympic_priv->rx_ring_last_received = OLYMPIC_RX_RING_SIZE - 1; /* last processed rx status */ olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE - 1; writew(i, olympic_mmio+RXSTATQCNT);#if OLYMPIC_DEBUG printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ)); printk("RXCSA: %x, rx_status_ring[0]: %p\n",readl(olympic_mmio+RXCSA),&olympic_priv->olympic_rx_status_ring[0]); printk(" stat_ring[1]: %p, stat_ring[2]: %p, stat_ring[3]: %p\n", &(olympic_priv->olympic_rx_status_ring[1]), &(olympic_priv->olympic_rx_status_ring[2]), &(olympic_priv->olympic_rx_status_ring[3]) ); printk(" stat_ring[4]: %p, stat_ring[5]: %p, stat_ring[6]: %p\n", &(olympic_priv->olympic_rx_status_ring[4]), &(olympic_priv->olympic_rx_status_ring[5]), &(olympic_priv->olympic_rx_status_ring[6]) ); printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7]) ); printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]); printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr =%08x\n",olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; #endif writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ);#if OLYMPIC_DEBUG printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ)); printk("RXCSA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCSA),&olympic_priv->olympic_rx_status_ring[0]); printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]);#endif writel(SISR_RX_STATUS | SISR_RX_NOBUF,olympic_mmio+SISR_MASK_SUM); /* setup tx ring */ writel(BMCTL_TX1_DIS,olympic_mmio+BMCTL_RWM); /* Yes, this enables TX channel 1 */ for(i=0;i<OLYMPIC_TX_RING_SIZE;i++) olympic_priv->olympic_tx_ring[i].buffer=0xdeadbeef; olympic_priv->free_tx_ring_entries=OLYMPIC_TX_RING_SIZE; olympic_priv->tx_ring_dma_addr = pci_map_single(olympic_priv->pdev,olympic_priv->olympic_tx_ring, sizeof(struct olympic_tx_desc) * OLYMPIC_TX_RING_SIZE,PCI_DMA_TODEVICE) ; writel(olympic_priv->tx_ring_dma_addr, olympic_mmio+TXDESCQ_1); writel(olympic_priv->tx_ring_dma_addr, olympic_mmio+TXCDA_1); writew(OLYMPIC_TX_RING_SIZE, olympic_mmio+TXDESCQCNT_1); olympic_priv->tx_status_ring_dma_addr = pci_map_single(olympic_priv->pdev, olympic_priv->olympic_tx_status_ring, sizeof(struct olympic_tx_status) * OLYMPIC_TX_RING_SIZE, PCI_DMA_FROMDEVICE); writel(olympic_priv->tx_status_ring_dma_addr,olympic_mmio+TXSTATQ_1); writel(olympic_priv->tx_status_ring_dma_addr,olympic_mmio+TXCSA_1); writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXSTATQCNT_1); olympic_priv->tx_ring_free=0; /* next entry in tx ring to use */ olympic_priv->tx_ring_last_status=OLYMPIC_TX_RING_SIZE-1; /* last processed tx status */ writel(SISR_TX1_EOF | SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE,olympic_mmio+SISR_MASK_SUM);#if OLYMPIC_DEBUG printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM)); printk("SISR MASK: %x\n",readl(olympic_mmio+SISR_MASK));#endif if (olympic_priv->olympic_network_monitor) { u8 *oat ; u8 *opt ; oat = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; opt = (u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1), readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2), readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3), readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4), readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5)); printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name, readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1), readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2), readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3)); printk("%s: NAUN Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)), readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1), readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2), readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3), readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4), readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5)); } netif_start_queue(dev); return 0; } /* * When we enter the rx routine we do not know how many frames have been * queued on the rx channel. Therefore we start at the next rx status * position and travel around the receive ring until we have completed * all the frames. * * This means that we may process the frame before we receive the end * of frame interrupt. This is why we always test the status instead * of blindly processing the next frame. * * We also remove the last 4 bytes from the packet as well, these are * just token ring trailer info and upset protocols that don't check * their own length, i.e. SNA. * */static void olympic_rx(struct net_device *dev){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -