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

📄 ibmtr.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	writew(htons(MAX_I_FIELD),	       ti->srb + offsetof(struct dlc_open_sap, max_i_field));	writeb(SAP_OPEN_IND_SAP | SAP_OPEN_PRIORITY,	       ti->srb + offsetof(struct dlc_open_sap, sap_options));	writeb(SAP_OPEN_STATION_CNT,	       ti->srb + offsetof(struct dlc_open_sap, station_count));	writeb(type, ti->srb + offsetof(struct dlc_open_sap, sap_value));	writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);}void tok_open_adapter(unsigned long dev_addr){	struct device *dev=(struct 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	writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD);	writeb(~CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD);	for (i=0; i<sizeof(struct dir_open_adapter); i++)		writeb(0, ti->init_srb+i);	writeb(DIR_OPEN_ADAPTER,	       ti->init_srb + offsetof(struct dir_open_adapter, command));	writew(htons(OPEN_PASS_BCON_MAC),	       ti->init_srb + offsetof(struct dir_open_adapter, open_options));	if (ti->ring_speed == 16) {		writew(htons(ti->dhb_size16mb),		       ti->init_srb + offsetof(struct dir_open_adapter, dhb_length));		writew(htons(ti->rbuf_cnt16),		       ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf));		writew(htons(ti->rbuf_len16),		       ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len));	} else {		writew(htons(ti->dhb_size4mb),		       ti->init_srb + offsetof(struct dir_open_adapter, dhb_length));		writew(htons(ti->rbuf_cnt4),		       ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf));		writew(htons(ti->rbuf_len4),		       ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len));	}	writeb(NUM_DHB, /* always 2 */ 	       ti->init_srb + offsetof(struct dir_open_adapter, num_dhb));	writeb(DLC_MAX_SAP,	       ti->init_srb + offsetof(struct dir_open_adapter, dlc_max_sap));	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 */	writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);	writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);}static void tr_tx(struct 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;	if (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.*/	dhb=ti->sram		+ntohs(readw(ti->arb + offsetof(struct arb_xmit_req, dhb_address)));		/* 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);	xmit_command = readb(ti->srb + offsetof(struct srb_xmit, command));	writeb(xmit_command, ti->asb + offsetof(struct asb_xmit_resp, command));	writew(readb(ti->srb + offsetof(struct srb_xmit, station_id)),	       ti->asb + offsetof(struct asb_xmit_resp, station_id));	writeb(llc->ssap, ti->asb + offsetof(struct asb_xmit_resp, rsap_value));	writeb(readb(ti->srb + offsetof(struct srb_xmit, cmd_corr)),	       ti->asb + offsetof(struct asb_xmit_resp, cmd_corr));	writeb(0, ti->asb + offsetof(struct asb_xmit_resp, ret_code));	if ((xmit_command==XMIT_XID_CMD) || (xmit_command==XMIT_TEST_CMD)) {		writew(htons(0x11),		       ti->asb + offsetof(struct asb_xmit_resp, frame_length));		writeb(0x0e, ti->asb + offsetof(struct asb_xmit_resp, hdr_length));		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 + offsetof(struct asb_xmit_resp, hdr_length));	writew(htons(ti->current_skb->len),	       ti->asb + offsetof(struct asb_xmit_resp, frame_length));	memcpy_toio(dhb, ti->current_skb->data, ti->current_skb->len);	writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);	ti->tr_stats.tx_bytes+=ti->current_skb->len;	dev->tbusy=0;	dev_kfree_skb(ti->current_skb);	ti->current_skb=NULL;	mark_bh(NET_BH);	if (ti->readlog_pending) ibmtr_readlog(dev);}static void tr_rx(struct device *dev){	struct tok_info *ti=(struct tok_info *) dev->priv;	__u32 rbuffer, rbufdata;	__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;	rbuffer=(ti->sram		 +ntohs(readw(ti->arb + offsetof(struct arb_rec_req, rec_buf_addr))))+2; 	if(readb(ti->asb + offsetof(struct asb_rec, ret_code))!=0xFF)		DPRINTK("ASB not free !!!\n");	writeb(REC_DATA,	       ti->asb + offsetof(struct asb_rec, command));	writew(readw(ti->arb + offsetof(struct arb_rec_req, station_id)),	       ti->asb + offsetof(struct asb_rec, station_id));	writew(readw(ti->arb + offsetof(struct arb_rec_req, rec_buf_addr)),	       ti->asb + offsetof(struct asb_rec, rec_buf_addr));	lan_hdr_len=readb(ti->arb + offsetof(struct arb_rec_req, lan_hdr_len));		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: %p\n", llc,		ntohs(readw(ti->arb + offsetof(struct arb_rec_req, rec_buf_addr))),		ti->sram);	DPRINTK("dsap: %02X, ssap: %02X, llc: %02X, protid: %02X%02X%02X, "		"ethertype: %04X\n",		(int)readb(llc + offsetof(struct trllc, dsap)),		(int)readb(llc + offsetof(struct trllc, ssap)),		(int)readb(llc + offsetof(struct trllc, llc)),		(int)readb(llc + offsetof(struct trllc, protid)),		(int)readb(llc + offsetof(struct trllc, protid)+1),		(int)readb(llc + offsetof(struct trllc, protid)+2),		(int)readw(llc + offsetof(struct trllc, ethertype)));#endif	if (readb(llc + offsetof(struct trllc, llc))!=UI_CMD) {		writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code));		ti->tr_stats.rx_dropped++;		writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);		return;	}       	if ((readb(llc + offsetof(struct trllc, dsap))==EXTENDED_SAP) &&       	    (readb(llc + offsetof(struct trllc, ssap))==EXTENDED_SAP)) {       		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)readb(llc + offsetof(struct trllc, ssap)),       			(int)readb(llc + offsetof(struct trllc, dsap)),       			(int)readb(trhhdr + offsetof(struct trh_hdr, saddr)),       			(int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+1),       			(int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+2),       			(int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+3),       			(int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+4),       			(int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+5),       			(int)readb(trhhdr + offsetof(struct trh_hdr, daddr)),       			(int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+1),       			(int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+2),       			(int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+3),       			(int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+4),       			(int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+5));       	}#endif       	length = ntohs(readw(ti->arb+offsetof(struct arb_rec_req, frame_len)));       	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++;       		writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code));       		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(readw(rbuffer + offsetof(struct rec_buf, buf_len)));	rbufdata = rbuffer + offsetof(struct rec_buf,data);	if (IPv4_p) {                /* Copy the headers without checksumming */		hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr);		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(bus_to_virt(rbufdata), data,						   length < rbuffer_len ? length : rbuffer_len,						   chksum);		else			memcpy_fromio(data, rbufdata, rbuffer_len);		rbuffer = ntohs(readw(rbuffer));		if (!rbuffer)			break;		length -= rbuffer_len;		data += rbuffer_len;		rbuffer += ti->sram;		rbuffer_len = ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len)));		rbufdata = rbuffer + offsetof(struct rec_buf, data);	}       	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);}static int tok_send_packet(struct sk_buff *skb, struct device *dev){	struct tok_info *ti;	ti=(struct tok_info *) dev->priv;	if (dev->tbusy) {		int ticks_waited;		ticks_waited=jiffies - dev->trans_start;		if (ticks_waited<TR_BUSY_INTERVAL) return 1;		DPRINTK("Arrg. Transmitter busy.\n");		dev->trans_start+=5; /* we fake the transmission start time... */		return 1;	}	if (test_and_set_bit(0,(void *)&dev->tbusy)!=0)		DPRINTK("Transmitter access conflict\n");	else {		int flags;		/* 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;		writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command));		writew(ti->exsap_station_id, ti->srb		       +offsetof(struct srb_xmit, station_id));		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 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 device *dev) {	 struct tok_info *ti;	 ti=(struct tok_info *) dev->priv;	 ti->readlog_pending = 0;	 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);	 dev->tbusy=1; /* really srb busy... */}/* 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 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 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 device* dev_ibmtr[IBMTR_MAX_ADAPTERS];static int io[IBMTR_MAX_ADAPTERS] = {0xa20,0xa24};static int irq[IBMTR_MAX_ADAPTERS] = {0,0};static int mem[IBMTR_MAX_ADAPTERS] = {0,0};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_s(dev_ibmtr[i], sizeof(struct device));			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_s(dev_ibmtr[i]->priv, sizeof(struct tok_info));			 kfree_s(dev_ibmtr[i], sizeof(struct device));			 dev_ibmtr[i] = NULL;                }}#endif /* MODULE */

⌨️ 快捷键说明

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