📄 olympic.c
字号:
{ struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio; u8 __iomem *arb_block, *asb_block, *srb ; u8 header_len ; u16 frame_len, buffer_len ; struct sk_buff *mac_frame ; u8 __iomem *buf_ptr ; u8 __iomem *frame_data ; u16 buff_off ; u16 lan_status = 0, lan_status_diff ; /* Initialize to stop compiler warning */ u8 fdx_prot_error ; u16 next_ptr; arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; srb = (olympic_priv->olympic_lap + olympic_priv->srb) ; 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_mmio + 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 */ } writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */ writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */ writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */ writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); olympic_priv->asb_queued = 2 ; return ; } else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */ lan_status = swab16(readw(arb_block+6)); fdx_prot_error = readb(arb_block+8) ; /* Issue ARB Free */ writel(LISR_ARB_FREE,olympic_priv->olympic_mmio+LISR_SUM); lan_status_diff = olympic_priv->olympic_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 */ /* 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); netif_stop_queue(dev); olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; } /* If serious error */ if (olympic_priv->olympic_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 (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Counter Overflow \n", dev->name); /* Issue READ.LOG command */ writeb(SRB_READ_LOG, srb); writeb(0,srb+1); writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); writeb(0,srb+3); writeb(0,srb+4); writeb(0,srb+5); olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); } if (lan_status_diff & LSC_SR_CO) { if (olympic_priv->olympic_message_level) printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name); /* Issue a READ.SR.COUNTERS */ writeb(SRB_READ_SR_COUNTERS,srb); writeb(0,srb+1); writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); writeb(0,srb+3); olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */ writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); } olympic_priv->olympic_lan_status = lan_status ; } /* Lan.change.status */ else printk(KERN_WARNING "%s: Unknown arb command \n", dev->name);}static void olympic_asb_bh(struct net_device *dev) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; u8 __iomem *arb_block, *asb_block ; arb_block = (olympic_priv->olympic_lap + olympic_priv->arb) ; asb_block = (olympic_priv->olympic_lap + olympic_priv->asb) ; if (olympic_priv->asb_queued == 1) { /* Dropped through the first time */ writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */ writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */ writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */ writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */ writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); olympic_priv->asb_queued = 2 ; return ; } if (olympic_priv->asb_queued == 2) { switch (readb(asb_block+2)) { case 0x01: printk(KERN_WARNING "%s: Unrecognized command code \n", dev->name); break ; case 0x26: printk(KERN_WARNING "%s: Unrecognized buffer address \n", dev->name); break ; case 0xFF: /* Valid response, everything should be ok again */ break ; default: printk(KERN_WARNING "%s: Invalid return code in asb\n",dev->name); break ; } } olympic_priv->asb_queued = 0 ; } static int olympic_change_mtu(struct net_device *dev, int mtu) { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv; u16 max_mtu ; if (olympic_priv->olympic_ring_speed == 4) max_mtu = 4500 ; else max_mtu = 18000 ; if (mtu > max_mtu) return -EINVAL ; if (mtu < 100) return -EINVAL ; dev->mtu = mtu ; olympic_priv->pkt_buf_sz = mtu + TR_HLEN ; return 0 ; }static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data){ struct net_device *dev = (struct net_device *)data ; struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv; u8 __iomem *oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; u8 __iomem *opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; int size = 0 ; int len=0; off_t begin=0; off_t pos=0; size = sprintf(buffer, "IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapter %s\n",dev->name); size += sprintf(buffer+size, "\n%6s: Adapter Address : Node Address : Functional Addr\n", dev->name); size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x\n", dev->name, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], 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), 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)); size += sprintf(buffer+size, "\n%6s: Token Ring Parameters Table:\n", dev->name); size += sprintf(buffer+size, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n", dev->name) ; size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x :\n", dev->name, readb(opt+offsetof(struct olympic_parameters_table, phys_addr)), readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1), readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+2), readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+3), 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), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+1), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+2), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+3), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+4), readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+5), swab16(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))), swab16(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))), swab16(readw(opt+offsetof(struct olympic_parameters_table, att_code)))); size += sprintf(buffer+size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", dev->name) ; size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %04x : %04x : %04x : %04x : %04x : %04x : \n", dev->name, readb(opt+offsetof(struct olympic_parameters_table, source_addr)), readb(opt+offsetof(struct olympic_parameters_table, source_addr)+1), readb(opt+offsetof(struct olympic_parameters_table, source_addr)+2), readb(opt+offsetof(struct olympic_parameters_table, source_addr)+3), readb(opt+offsetof(struct olympic_parameters_table, source_addr)+4), readb(opt+offsetof(struct olympic_parameters_table, source_addr)+5), swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))), swab16(readw(opt+offsetof(struct olympic_parameters_table, major_vector))), swab16(readw(opt+offsetof(struct olympic_parameters_table, lan_status))), swab16(readw(opt+offsetof(struct olympic_parameters_table, local_ring))), swab16(readw(opt+offsetof(struct olympic_parameters_table, mon_error))), swab16(readw(opt+offsetof(struct olympic_parameters_table, frame_correl)))); size += sprintf(buffer+size, "%6s: Beacon Details : Tx : Rx : NAUN Node Address : NAUN Node Phys : \n", dev->name) ; size += sprintf(buffer+size, "%6s: : %02x : %02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x : \n", dev->name, swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))), swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+1), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+2), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+3), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+4), readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+5), readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)), readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+1), readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2), readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+3)); len=size; pos=begin+size; if (pos<o
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -