⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ibmtr.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
		dhb=dhb_base & ~(ti->page_mask << 8);	}	dhb += ti->sram_virt;	/* 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);	memcpy_fromio(&xsrb, ti->srb, sizeof(xsrb));	SET_PAGE(ti->asb_page);	xmit_command = xsrb.command;	writeb(xmit_command, ti->asb + COMMAND_OFST);	writew(xsrb.station_id, ti->asb + STATION_ID_OFST);	writeb(llc_ssap, ti->asb + RSAP_VALUE_OFST);	writeb(xsrb.cmd_corr, ti->asb + CMD_CORRELATE_OFST);	writeb(0, ti->asb + RETCODE_OFST);	if ((xmit_command == XMIT_XID_CMD) || (xmit_command == XMIT_TEST_CMD)) {		writew(htons(0x11), ti->asb + FRAME_LENGTH_OFST);		writeb(0x0e, ti->asb + HEADER_LENGTH_OFST);		SET_PAGE(dhb_page);		writeb(AC, dhb);		writeb(LLC_FRAME, dhb + 1);		for (i = 0; i < TR_ALEN; i++)			writeb((int) 0x0FF, dhb + i + 2);		for (i = 0; i < TR_ALEN; i++)			writeb(0, dhb + i + TR_ALEN + 2);		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.	 */	writeb(hdr_len, ti->asb + HEADER_LENGTH_OFST);	writew(htons(ti->current_skb->len), ti->asb + FRAME_LENGTH_OFST);	src_len=ti->current_skb->len;	src_offset=0;	dhb=dhb_base;	while(1) {		if (ti->page_mask) {			dhb_page=(dhb >> 8) & ti->page_mask;			dhb=dhb & ~(ti->page_mask << 8);			dhb_len=0x4000-dhb; /* remaining size of this page */		}		dhb+=ti->sram_virt;		SET_PAGE(dhb_page);		if (src_len > dhb_len) {			memcpy_toio(dhb,&ti->current_skb->data[src_offset],					dhb_len);			src_len -= dhb_len;			src_offset += dhb_len;			dhb_base+=dhb_len;			dhb=dhb_base;			continue;		}		memcpy_toio(dhb, &ti->current_skb->data[src_offset], src_len);		break;	}	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);}				/*tr_tx *//*****************************************************************************/#define RECEIVE_BUFFER_OFST     6#define LAN_HDR_LENGTH_OFST     8#define DLC_HDR_LENGTH_OFST     9#define DSAP_OFST               0#define SSAP_OFST               1#define LLC_OFST                2#define PROTID_OFST             3#define ETHERTYPE_OFST          6static 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;	unsigned char dlc_hdr_len;	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);	memcpy_fromio(&rarb, ti->arb, sizeof(rarb));	rbuffer = ntohs(rarb.rec_buf_addr) ;	if (ti->page_mask) {		rbuffer_page = (rbuffer >> 8) & ti->page_mask;		rbuffer &= ~(ti->page_mask << 8);	}	rbuffer += ti->sram_virt;	SET_PAGE(ti->asb_page);	if (readb(ti->asb + RETCODE_OFST) !=0xFF) DPRINTK("ASB not free !!!\n");	writeb(REC_DATA, ti->asb + COMMAND_OFST);	writew(rarb.station_id, ti->asb + STATION_ID_OFST);	writew(rarb.rec_buf_addr, ti->asb + RECEIVE_BUFFER_OFST);	lan_hdr_len = rarb.lan_hdr_len;	if (lan_hdr_len > sizeof(struct trh_hdr)) {		DPRINTK("Linux cannot handle greater than 18 bytes RIF\n");		return;	}			/*BMS I added this above just to be very safe */	dlc_hdr_len = readb(ti->arb + DLC_HDR_LENGTH_OFST);	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",	(__u32) offsetof(struct rec_buf, data), (unsigned int) lan_hdr_len);	DPRINTK("llc: %08X rec_buf_addr: %04X dev->mem_start: %lX\n",		llc, ntohs(rarb.rec_buf_addr), dev->mem_start);	DPRINTK("dsap: %02X, ssap: %02X, llc: %02X, protid: %02X%02X%02X, "		"ethertype: %04X\n",		(int) readb(llc + DSAP_OFST), (int) readb(llc + SSAP_OFST),		(int) readb(llc + LLC_OFST), (int) readb(llc + PROTID_OFST),		(int) readb(llc+PROTID_OFST+1),(int)readb(llc+PROTID_OFST + 2),		(int) ntohs(readw(llc + ETHERTYPE_OFST)));#endif	if (readb(llc + offsetof(struct trllc, llc)) != UI_CMD) {		SET_PAGE(ti->asb_page);		writeb(DATA_LOST, ti->asb + RETCODE_OFST);		ti->tr_stats.rx_dropped++;		writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);		return;	}	length = ntohs(rarb.frame_len);	if (readb(llc + DSAP_OFST) == EXTENDED_SAP &&	   readb(llc + SSAP_OFST) == EXTENDED_SAP &&		length >= hdr_len)	IPv4_p = 1;#if TR_VERBOSE#define SADDR_OFST	8#define DADDR_OFST	2	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",			readb(llc + SSAP_OFST), readb(llc + DSAP_OFST),			readb(trhhdr+SADDR_OFST), readb(trhhdr+ SADDR_OFST+1),			readb(trhhdr+SADDR_OFST+2), readb(trhhdr+SADDR_OFST+3),			readb(trhhdr+SADDR_OFST+4), readb(trhhdr+SADDR_OFST+5),			readb(trhhdr+DADDR_OFST), readb(trhhdr+DADDR_OFST + 1),			readb(trhhdr+DADDR_OFST+2), readb(trhhdr+DADDR_OFST+3),			readb(trhhdr+DADDR_OFST+4), readb(trhhdr+DADDR_OFST+5));	}#endif	/*BMS handle the case she comes in with few hops but leaves with many */        skb_size=length-lan_hdr_len+sizeof(struct trh_hdr)+sizeof(struct trllc);	if (!(skb = dev_alloc_skb(skb_size))) {		DPRINTK("out of memory. frame dropped.\n");		ti->tr_stats.rx_dropped++;		SET_PAGE(ti->asb_page);		writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code));		writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);		return;	}	/*BMS again, if she comes in with few but leaves with many */	skb_reserve(skb, sizeof(struct trh_hdr) - lan_hdr_len);	skb_put(skb, length);	skb->dev = dev;	data = skb->data;	rbuffer_len = ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len)));	rbufdata = rbuffer + offsetof(struct rec_buf, data);	if (IPv4_p) {		/* Copy the headers without checksumming */		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... */#define BUFFER_POINTER_OFST	2#define BUFFER_LENGTH_OFST      6	for (;;) {		if (ibmtr_debug_trace&TRC_INITV && length < rbuffer_len)			DPRINTK("CURIOUS, length=%d < rbuffer_len=%d\n",						length,rbuffer_len);		if (IPv4_p)			chksum=csum_partial_copy_nocheck((void*)rbufdata,			    data,length<rbuffer_len?length:rbuffer_len,chksum);		else			memcpy_fromio(data, rbufdata, rbuffer_len);		rbuffer = ntohs(readw(rbuffer+BUFFER_POINTER_OFST)) ;		if (!rbuffer)			break;		rbuffer -= 2;		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_virt;		SET_PAGE(rbuffer_page);		rbuffer_len = ntohs(readw(rbuffer + BUFFER_LENGTH_OFST));		rbufdata = rbuffer + offsetof(struct rec_buf, data);	}	SET_PAGE(ti->asb_page);	writeb(0, ti->asb + offsetof(struct asb_rec, ret_code));	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->csum = chksum;		skb->ip_summed = 1;	}	netif_rx(skb);	dev->last_rx = jiffies;}				/*tr_rx *//*****************************************************************************/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_rerun;	init_timer(tmr);	add_timer(tmr);}/*****************************************************************************/void tok_rerun(unsigned long dev_addr){	struct net_device *dev = (struct net_device *)dev_addr;	struct tok_info *ti = (struct tok_info *) dev->priv;	if ( ti->open_action == RESTART){		ti->do_tok_int = FIRST_INT;		outb(0, dev->base_addr + ADAPTRESETREL);#ifdef ENABLE_PAGING		if (ti->page_mask)			writeb(SRPR_ENABLE_PAGING,				ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN);#endif		writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);	} else		tok_open_adapter(dev_addr);}/*****************************************************************************/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);	writeb(DIR_READ_LOG, ti->srb);	writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);	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;}/*****************************************************************************/#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_LICENSE("GPL");module_param_array(io, int, NULL, 0);module_param_array(irq, int, NULL, 0);module_param_array(mem, int, NULL, 0);static int __init ibmtr_init(void){	int i;	int count=0;	find_turbo_adapters(io);	for (i = 0; io[i] && (i < IBMTR_MAX_ADAPTERS); i++) {		struct net_device *dev;		irq[i] = 0;		mem[i] = 0;		dev = alloc_trdev(sizeof(struct tok_info));		if (dev == NULL) { 			if (i == 0)				return -ENOMEM;			break;		}		dev->base_addr = io[i];		dev->irq = irq[i];		dev->mem_start = mem[i];		if (ibmtr_probe_card(dev)) {			free_netdev(dev);			continue;		}		dev_ibmtr[i] = dev;		count++;	}	if (count) return 0;	printk("ibmtr: register_netdev() returned non-zero.\n");	return -EIO;}module_init(ibmtr_init);static void __exit ibmtr_cleanup(void){	int i;	for (i = 0; i < IBMTR_MAX_ADAPTERS; i++){		if (!dev_ibmtr[i])			continue;		unregister_netdev(dev_ibmtr[i]);		ibmtr_cleanup_card(dev_ibmtr[i]);		free_netdev(dev_ibmtr[i]);	}}module_exit(ibmtr_cleanup);#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -