📄 ibmtr.c
字号:
#if !TR_NEWFORMAT DPRINTK("card reset\n");#endif ti->open_status=IN_PROGRESS; isa_writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); return 0;}static void open_sap(unsigned char type,struct net_device *dev){ int i; struct tok_info *ti=(struct tok_info *) dev->priv; SET_PAGE(ti->srb_page); for (i=0; i<sizeof(struct dlc_open_sap); i++) isa_writeb(0, ti->srb+i); isa_writeb(DLC_OPEN_SAP, ti->srb + offsetof(struct dlc_open_sap, command)); isa_writew(htons(MAX_I_FIELD), ti->srb + offsetof(struct dlc_open_sap, max_i_field)); isa_writeb(SAP_OPEN_IND_SAP | SAP_OPEN_PRIORITY, ti->srb + offsetof(struct dlc_open_sap, sap_options)); isa_writeb(SAP_OPEN_STATION_CNT, ti->srb + offsetof(struct dlc_open_sap, station_count)); isa_writeb(type, ti->srb + offsetof(struct dlc_open_sap, sap_value)); isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);}void tok_open_adapter(unsigned long dev_addr){ struct net_device *dev=(struct net_device *)dev_addr; struct tok_info *ti; int i; ti=(struct tok_info *) dev->priv;#if !TR_NEWFORMAT DPRINTK("now opening the board...\n");#endif isa_writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); isa_writeb(~CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); for (i=0; i<sizeof(struct dir_open_adapter); i++) isa_writeb(0, ti->init_srb+i); isa_writeb(DIR_OPEN_ADAPTER, ti->init_srb + offsetof(struct dir_open_adapter, command)); isa_writew(htons(OPEN_PASS_BCON_MAC), ti->init_srb + offsetof(struct dir_open_adapter, open_options)); if (ti->ring_speed == 16) { isa_writew(htons(ti->dhb_size16mb), ti->init_srb + offsetof(struct dir_open_adapter, dhb_length)); isa_writew(htons(ti->rbuf_cnt16), ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf)); isa_writew(htons(ti->rbuf_len16), ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len)); } else { isa_writew(htons(ti->dhb_size4mb), ti->init_srb + offsetof(struct dir_open_adapter, dhb_length)); isa_writew(htons(ti->rbuf_cnt4), ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf)); isa_writew(htons(ti->rbuf_len4), ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len)); } isa_writeb(NUM_DHB, /* always 2 */ ti->init_srb + offsetof(struct dir_open_adapter, num_dhb)); isa_writeb(DLC_MAX_SAP, ti->init_srb + offsetof(struct dir_open_adapter, dlc_max_sap)); isa_writeb(DLC_MAX_STA, ti->init_srb + offsetof(struct dir_open_adapter, dlc_max_sta)); ti->srb=ti->init_srb; /* We use this one in the interrupt handler */ ti->srb_page=ti->init_srb_page; DPRINTK("Opend adapter: Xmit bfrs: %d X %d, Rcv bfrs: %d X %d\n", isa_readb(ti->init_srb+offsetof(struct dir_open_adapter,num_dhb)), ntohs(isa_readw(ti->init_srb+offsetof(struct dir_open_adapter,dhb_length))), ntohs(isa_readw(ti->init_srb+offsetof(struct dir_open_adapter,num_rcv_buf))), ntohs(isa_readw(ti->init_srb+offsetof(struct dir_open_adapter,rcv_buf_len))) ); isa_writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);}static void tr_tx(struct net_device *dev){ struct tok_info *ti=(struct tok_info *) dev->priv; struct trh_hdr *trhdr=(struct trh_hdr *)ti->current_skb->data; unsigned int hdr_len; __u32 dhb; unsigned char xmit_command; int i; struct trllc *llc; struct srb_xmit xsrb; __u8 dhb_page=0; __u8 llc_ssap; SET_PAGE(ti->asb_page); if (isa_readb(ti->asb + offsetof(struct asb_xmit_resp, ret_code))!=0xFF) DPRINTK("ASB not free !!!\n"); /* in providing the transmit interrupts, is telling us it is ready for data and providing a shared memory address for us to stuff with data. Here we compute the effective address where we will place data.*/ SET_PAGE(ti->arb_page); dhb=ntohs(isa_readw(ti->arb + offsetof(struct arb_xmit_req, dhb_address))); if (ti->page_mask) { dhb_page=(dhb >> 8) & ti->page_mask; dhb &= ~(ti->page_mask << 8); } dhb+=ti->sram; /* Figure out the size of the 802.5 header */ if (!(trhdr->saddr[0] & 0x80)) /* RIF present? */ hdr_len=sizeof(struct trh_hdr)-TR_MAXRIFLEN; else hdr_len=((ntohs(trhdr->rcf) & TR_RCF_LEN_MASK)>>8) +sizeof(struct trh_hdr)-TR_MAXRIFLEN; llc = (struct trllc *)(ti->current_skb->data + hdr_len); llc_ssap=llc->ssap; SET_PAGE(ti->srb_page); isa_memcpy_fromio(&xsrb, ti->srb, sizeof(xsrb)); SET_PAGE(ti->asb_page); xmit_command=xsrb.command; isa_writeb(xmit_command, ti->asb + offsetof(struct asb_xmit_resp, command)); isa_writew(xsrb.station_id, ti->asb + offsetof(struct asb_xmit_resp, station_id)); isa_writeb(llc_ssap, ti->asb + offsetof(struct asb_xmit_resp, rsap_value)); isa_writeb(xsrb.cmd_corr, ti->asb + offsetof(struct asb_xmit_resp, cmd_corr)); isa_writeb(0, ti->asb + offsetof(struct asb_xmit_resp, ret_code)); if ((xmit_command==XMIT_XID_CMD) || (xmit_command==XMIT_TEST_CMD)) { isa_writew(htons(0x11), ti->asb + offsetof(struct asb_xmit_resp, frame_length)); isa_writeb(0x0e, ti->asb + offsetof(struct asb_xmit_resp, hdr_length)); SET_PAGE(dhb_page); isa_writeb(AC, dhb); isa_writeb(LLC_FRAME, dhb+1); for (i=0; i<TR_ALEN; i++) isa_writeb((int)0x0FF, dhb+i+2); for (i=0; i<TR_ALEN; i++) isa_writeb(0, dhb+i+TR_ALEN+2); isa_writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); return; } /* * the token ring packet is copied from sk_buff to the adapter * buffer identified in the command data received with the interrupt. */ isa_writeb(hdr_len, ti->asb + offsetof(struct asb_xmit_resp, hdr_length)); isa_writew(htons(ti->current_skb->len), ti->asb + offsetof(struct asb_xmit_resp, frame_length)); SET_PAGE(dhb_page); isa_memcpy_toio(dhb, ti->current_skb->data, ti->current_skb->len); isa_writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); ti->tr_stats.tx_bytes+=ti->current_skb->len; dev_kfree_skb_irq(ti->current_skb); ti->current_skb=NULL; netif_wake_queue(dev); if (ti->readlog_pending) ibmtr_readlog(dev);}static void tr_rx(struct net_device *dev){ struct tok_info *ti=(struct tok_info *) dev->priv; __u32 rbuffer, rbufdata; __u8 rbuffer_page=0; __u32 llc; unsigned char *data; unsigned int rbuffer_len, lan_hdr_len, hdr_len, ip_len, length; struct sk_buff *skb; unsigned int skb_size = 0; int IPv4_p = 0; unsigned int chksum = 0; struct iphdr *iph; struct arb_rec_req rarb; SET_PAGE(ti->arb_page); isa_memcpy_fromio(&rarb, ti->arb, sizeof(rarb)); rbuffer=ntohs(rarb.rec_buf_addr)+2; if (ti->page_mask) { rbuffer_page=(rbuffer >> 8) & ti->page_mask; rbuffer &= ~(ti->page_mask<<8); } rbuffer += ti->sram; SET_PAGE(ti->asb_page); if(isa_readb(ti->asb + offsetof(struct asb_rec, ret_code))!=0xFF) DPRINTK("ASB not free !!!\n"); isa_writeb(REC_DATA, ti->asb + offsetof(struct asb_rec, command)); isa_writew(rarb.station_id, ti->asb + offsetof(struct asb_rec, station_id)); isa_writew(rarb.rec_buf_addr, ti->asb + offsetof(struct asb_rec, rec_buf_addr)); lan_hdr_len=rarb.lan_hdr_len; hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr); SET_PAGE(rbuffer_page); llc=(rbuffer + offsetof(struct rec_buf, data) + lan_hdr_len);#if TR_VERBOSE DPRINTK("offsetof data: %02X lan_hdr_len: %02X\n", (unsigned int)offsetof(struct rec_buf,data), (unsigned int)lan_hdr_len); DPRINTK("llc: %08X rec_buf_addr: %04X ti->sram: %lx\n", llc, ntohs(rarb.rec_buf_addr), (long)ti->sram); DPRINTK("dsap: %02X, ssap: %02X, llc: %02X, protid: %02X%02X%02X, " "ethertype: %04X\n", (int)isa_readb(llc + offsetof(struct trllc, dsap)), (int)isa_readb(llc + offsetof(struct trllc, ssap)), (int)isa_readb(llc + offsetof(struct trllc, llc)), (int)isa_readb(llc + offsetof(struct trllc, protid)), (int)isa_readb(llc + offsetof(struct trllc, protid)+1), (int)isa_readb(llc + offsetof(struct trllc, protid)+2), (int)isa_readw(llc + offsetof(struct trllc, ethertype)));#endif if (isa_readb(llc + offsetof(struct trllc, llc))!=UI_CMD) { SET_PAGE(ti->asb_page); isa_writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code)); ti->tr_stats.rx_dropped++; isa_writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); return; } length = ntohs(rarb.frame_len); if ((isa_readb(llc + offsetof(struct trllc, dsap))==EXTENDED_SAP) && (isa_readb(llc + offsetof(struct trllc, ssap))==EXTENDED_SAP) && (length>=hdr_len)) { IPv4_p = 1; }#if TR_VERBOSE if (!IPv4_p){ __u32 trhhdr; trhhdr=(rbuffer+offsetof(struct rec_buf,data)); DPRINTK("Probably non-IP frame received.\n"); DPRINTK("ssap: %02X dsap: %02X saddr: %02X:%02X:%02X:%02X:%02X:%02X " "daddr: %02X:%02X:%02X:%02X:%02X:%02X\n", (int)isa_readb(llc + offsetof(struct trllc, ssap)), (int)isa_readb(llc + offsetof(struct trllc, dsap)), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, saddr)), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, saddr)+1), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, saddr)+2), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, saddr)+3), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, saddr)+4), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, saddr)+5), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, daddr)), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, daddr)+1), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, daddr)+2), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, daddr)+3), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, daddr)+4), (int)isa_readb(trhhdr + offsetof(struct trh_hdr, daddr)+5)); }#endif skb_size = length; if (!(skb=dev_alloc_skb(skb_size))) { DPRINTK("out of memory. frame dropped.\n"); ti->tr_stats.rx_dropped++; SET_PAGE(ti->asb_page); isa_writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code)); isa_writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); return; } skb_put(skb, length); skb_reserve(skb, sizeof(struct trh_hdr)-lan_hdr_len+sizeof(struct trllc)); skb->dev=dev; data=skb->data; rbuffer_len=ntohs(isa_readw(rbuffer + offsetof(struct rec_buf, buf_len))); rbufdata = rbuffer + offsetof(struct rec_buf,data); if (IPv4_p) { /* Copy the headers without checksumming */ isa_memcpy_fromio(data, rbufdata, hdr_len); /* Watch for padded packets and bogons */ iph=(struct iphdr*)(data + lan_hdr_len + sizeof(struct trllc)); ip_len = ntohs(iph->tot_len) - sizeof(struct iphdr); length -= hdr_len; if ((ip_len <= length) && (ip_len > 7)) length = ip_len; data += hdr_len; rbuffer_len -= hdr_len; rbufdata += hdr_len; } /* Copy the payload... */ for (;;) { if (IPv4_p) chksum = csum_partial_copy_nocheck(bus_to_virt(rbufdata), data, length < rbuffer_len ? length : rbuffer_len, chksum); else isa_memcpy_fromio(data, rbufdata, rbuffer_len); rbuffer = ntohs(isa_readw(rbuffer)); if (!rbuffer) break; length -= rbuffer_len; data += rbuffer_len; if (ti->page_mask) { rbuffer_page=(rbuffer>>8) & ti->page_mask; rbuffer &= ~(ti->page_mask << 8); } rbuffer += ti->sram; SET_PAGE(rbuffer_page); rbuffer_len = ntohs(isa_readw(rbuffer + offsetof(struct rec_buf, buf_len))); rbufdata = rbuffer + offsetof(struct rec_buf, data); } SET_PAGE(ti->asb_page); isa_writeb(0, ti->asb + offsetof(struct asb_rec, ret_code)); isa_writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); ti->tr_stats.rx_bytes += skb->len; ti->tr_stats.rx_packets++; skb->protocol = tr_type_trans(skb,dev); if (IPv4_p && (skb->protocol == ETH_P_IP)) { skb->csum = chksum; skb->ip_summed = 1; } netif_rx(skb);}static int tok_send_packet(struct sk_buff *skb, struct net_device *dev){ struct tok_info *ti; unsigned long flags; ti=(struct tok_info *) dev->priv; netif_stop_queue(dev); /* lock against other CPUs */ spin_lock_irqsave(&(ti->lock), flags); /* Save skb; we'll need it when the adapter asks for the data */ ti->current_skb=skb; SET_PAGE(ti->srb_page); isa_writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command)); isa_writew(ti->exsap_station_id, ti->srb +offsetof(struct srb_xmit, station_id)); isa_writeb(CMD_IN_SRB, (ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)); spin_unlock_irqrestore(&(ti->lock), flags); dev->trans_start=jiffies; return 0;}void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev) { tmr->expires = jiffies + TR_RETRY_INTERVAL; tmr->data = (unsigned long) dev; tmr->function = tok_open_adapter; init_timer(tmr); add_timer(tmr);}void ibmtr_readlog(struct net_device *dev) { struct tok_info *ti; ti=(struct tok_info *) dev->priv; ti->readlog_pending = 0; SET_PAGE(ti->srb_page); isa_writeb(DIR_READ_LOG, ti->srb); isa_writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); isa_writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); netif_stop_queue(dev);}/* tok_get_stats(): Basically a scaffold routine which will return the address of the tr_statistics structure associated with this device -- the tr.... structure is an ethnet look-alike so at least for this iteration may suffice. */static struct net_device_stats * tok_get_stats(struct net_device *dev) { struct tok_info *toki; toki=(struct tok_info *) dev->priv; return (struct net_device_stats *) &toki->tr_stats;}int ibmtr_change_mtu(struct net_device *dev, int mtu) { struct tok_info *ti = (struct tok_info *) dev->priv; if (ti->ring_speed == 16 && mtu > ti->maxmtu16) return -EINVAL; if (ti->ring_speed == 4 && mtu > ti->maxmtu4) return -EINVAL; dev->mtu = mtu; return 0;}#ifndef PCMCIA#ifdef MODULE/* 3COM 3C619C supports 8 interrupts, 32 I/O ports */static struct net_device* dev_ibmtr[IBMTR_MAX_ADAPTERS];static int io[IBMTR_MAX_ADAPTERS] = {0xa20,0xa24};static int irq[IBMTR_MAX_ADAPTERS];static int mem[IBMTR_MAX_ADAPTERS];MODULE_PARM(io, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i");MODULE_PARM(irq, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i");MODULE_PARM(mem, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i");int init_module(void){ int i; for (i = 0; io[i] && (i<IBMTR_MAX_ADAPTERS); i++) { irq[i] = 0; mem[i] = 0; dev_ibmtr[i] = NULL; dev_ibmtr[i] = init_trdev(dev_ibmtr[i], 0); if (dev_ibmtr[i] == NULL) return -ENOMEM; dev_ibmtr[i]->base_addr = io[i]; dev_ibmtr[i]->irq = irq[i]; dev_ibmtr[i]->mem_start = mem[i]; dev_ibmtr[i]->init = &ibmtr_probe; if (register_trdev(dev_ibmtr[i]) != 0) { kfree(dev_ibmtr[i]); dev_ibmtr[i] = NULL; if (i == 0) { printk("ibmtr: register_trdev() returned non-zero.\n"); return -EIO; } else { return 0; } } } return 0;}void cleanup_module(void){ int i; for (i = 0; i < IBMTR_MAX_ADAPTERS; i++) if (dev_ibmtr[i]) { unregister_trdev(dev_ibmtr[i]); free_irq(dev_ibmtr[i]->irq, dev_ibmtr[i]); release_region(dev_ibmtr[i]->base_addr, IBMTR_IO_EXTENT); kfree(dev_ibmtr[i]->priv); kfree(dev_ibmtr[i]); dev_ibmtr[i] = NULL; }}#endif /* MODULE */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -