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

📄 hp100.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static int hp100_build_rx_pdl(hp100_ring_t * ringptr,			      struct net_device *dev){#ifdef HP100_DEBUG_B	int ioaddr = dev->base_addr;#endif#ifdef HP100_DEBUG_BM	u_int *p;#endif#ifdef HP100_DEBUG_B	hp100_outw(0x4207, TRACE);	printk("hp100: %s: build rx pdl\n", dev->name);#endif	/* Allocate skb buffer of maximum size */	/* Note: This depends on the alloc_skb functions allocating more 	 * space than requested, i.e. aligning to 16bytes */	ringptr->skb = dev_alloc_skb(((MAX_ETHER_SIZE + 2 + 3) / 4) * 4);	if (NULL != ringptr->skb) {		/* 		 * Reserve 2 bytes at the head of the buffer to land the IP header		 * on a long word boundary (According to the Network Driver section		 * in the Linux KHG, this should help to increase performance.)		 */		skb_reserve(ringptr->skb, 2);		ringptr->skb->dev = dev;		ringptr->skb->data = (u_char *) skb_put(ringptr->skb, MAX_ETHER_SIZE);		/* ringptr->pdl points to the beginning of the PDL, i.e. the PDH */		/* Note: 1st Fragment is used for the 4 byte packet status		 * (receive header). Its PDL entries are set up by init_rxpdl. So 		 * here we only have to set up the PDL fragment entries for the data		 * part. Those 4 bytes will be stored in the DMA memory region 		 * directly before the PDL. 		 */#ifdef HP100_DEBUG_BM		printk("hp100: %s: build_rx_pdl: PDH@0x%x, skb->data (len %d) at 0x%x\n",				     dev->name, (u_int) ringptr->pdl,				     ((MAX_ETHER_SIZE + 2 + 3) / 4) * 4,				     (unsigned int) ringptr->skb->data);#endif		ringptr->pdl[0] = 0x00020000;	/* Write PDH */		ringptr->pdl[3] = ((u_int) virt_to_bus(ringptr->skb->data));		ringptr->pdl[4] = MAX_ETHER_SIZE;	/* Length of Data */#ifdef HP100_DEBUG_BM		for (p = (ringptr->pdl); p < (ringptr->pdl + 5); p++)			printk("hp100: %s: Adr 0x%.8x = 0x%.8x\n", dev->name, (u_int) p, (u_int) * p);#endif		return (1);	}	/* else: */	/* alloc_skb failed (no memory) -> still can receive the header	 * fragment into PDL memory. make PDL safe by clearing msgptr and	 * making the PDL only 1 fragment (i.e. the 4 byte packet status)	 */#ifdef HP100_DEBUG_BM	printk("hp100: %s: build_rx_pdl: PDH@0x%x, No space for skb.\n", dev->name, (u_int) ringptr->pdl);#endif	ringptr->pdl[0] = 0x00010000;	/* PDH: Count=1 Fragment */	return (0);}/* *  hp100_rxfill - attempt to fill the Rx Ring will empty skb's * * Makes assumption that skb's are always contiguous memory areas and * therefore PDLs contain only 2 physical fragments. * -  While the number of Rx PDLs with buffers is less than maximum *      a.  Get a maximum packet size skb *      b.  Put the physical address of the buffer into the PDL. *      c.  Output physical address of PDL to adapter. */static void hp100_rxfill(struct net_device *dev){	int ioaddr = dev->base_addr;	struct hp100_private *lp = (struct hp100_private *) dev->priv;	hp100_ring_t *ringptr;#ifdef HP100_DEBUG_B	hp100_outw(0x4208, TRACE);	printk("hp100: %s: rxfill\n", dev->name);#endif	hp100_page(PERFORMANCE);	while (lp->rxrcommit < MAX_RX_PDL) {		/*		   ** Attempt to get a buffer and build a Rx PDL.		 */		ringptr = lp->rxrtail;		if (0 == hp100_build_rx_pdl(ringptr, dev)) {			return;	/* None available, return */		}		/* Hand this PDL over to the card */		/* Note: This needs performance page selected! */#ifdef HP100_DEBUG_BM		printk("hp100: %s: rxfill: Hand to card: pdl #%d @0x%x phys:0x%x, buffer: 0x%x\n",				     dev->name, lp->rxrcommit, (u_int) ringptr->pdl,				     (u_int) ringptr->pdl_paddr, (u_int) ringptr->pdl[3]);#endif		hp100_outl((u32) ringptr->pdl_paddr, RX_PDA);		lp->rxrcommit += 1;		lp->rxrtail = ringptr->next;	}}/* * BM_shutdown - shutdown bus mastering and leave chip in reset state */static void hp100_BM_shutdown(struct net_device *dev){	int ioaddr = dev->base_addr;	struct hp100_private *lp = (struct hp100_private *) dev->priv;	unsigned long time;#ifdef HP100_DEBUG_B	hp100_outw(0x4209, TRACE);	printk("hp100: %s: bm shutdown\n", dev->name);#endif	hp100_page(PERFORMANCE);	hp100_outw(0xfefe, IRQ_MASK);	/* mask off all ints */	hp100_outw(0xffff, IRQ_STATUS);	/* Ack all ints */	/* Ensure Interrupts are off */	hp100_outw(HP100_INT_EN | HP100_RESET_LB, OPTION_LSW);	/* Disable all MAC activity */	hp100_page(MAC_CTRL);	hp100_andb(~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1);	/* stop rx/tx */	/* If cascade MMU is not already in reset */	if (0 != (hp100_inw(OPTION_LSW) & HP100_HW_RST)) {		/* Wait 1.3ms (10Mb max packet time) to ensure MAC is idle so		 * MMU pointers will not be reset out from underneath		 */		hp100_page(MAC_CTRL);		for (time = 0; time < 5000; time++) {			if ((hp100_inb(MAC_CFG_1) & (HP100_TX_IDLE | HP100_RX_IDLE)) == (HP100_TX_IDLE | HP100_RX_IDLE))				break;		}		/* Shutdown algorithm depends on the generation of Cascade */		if (lp->chip == HP100_CHIPID_LASSEN) {	/* ETR shutdown/reset */			/* Disable Busmaster mode and wait for bit to go to zero. */			hp100_page(HW_MAP);			hp100_andb(~HP100_BM_MASTER, BM);			/* 100 ms timeout */			for (time = 0; time < 32000; time++) {				if (0 == (hp100_inb(BM) & HP100_BM_MASTER))					break;			}		} else {	/* Shasta or Rainier Shutdown/Reset */			/* To ensure all bus master inloading activity has ceased,			 * wait for no Rx PDAs or no Rx packets on card. 			 */			hp100_page(PERFORMANCE);			/* 100 ms timeout */			for (time = 0; time < 10000; time++) {				/* RX_PDL: PDLs not executed. */				/* RX_PKT_CNT: RX'd packets on card. */				if ((hp100_inb(RX_PDL) == 0) && (hp100_inb(RX_PKT_CNT) == 0))					break;			}			if (time >= 10000)				printk("hp100: %s: BM shutdown error.\n", dev->name);			/* To ensure all bus master outloading activity has ceased,			 * wait until the Tx PDA count goes to zero or no more Tx space			 * available in the Tx region of the card. 			 */			/* 100 ms timeout */			for (time = 0; time < 10000; time++) {				if ((0 == hp100_inb(TX_PKT_CNT)) &&				    (0 != (hp100_inb(TX_MEM_FREE) & HP100_AUTO_COMPARE)))					break;			}			/* Disable Busmaster mode */			hp100_page(HW_MAP);			hp100_andb(~HP100_BM_MASTER, BM);		}	/* end of shutdown procedure for non-etr parts */		hp100_cascade_reset(dev, TRUE);	}	hp100_page(PERFORMANCE);	/* hp100_outw( HP100_BM_READ | HP100_BM_WRITE | HP100_RESET_HB, OPTION_LSW ); */	/* Busmaster mode should be shut down now. */}/*  *  transmit functions *//* tx function for busmaster mode */static int hp100_start_xmit_bm(struct sk_buff *skb, struct net_device *dev){	unsigned long flags;	int i, ok_flag;	int ioaddr = dev->base_addr;	struct hp100_private *lp = (struct hp100_private *) dev->priv;	hp100_ring_t *ringptr;#ifdef HP100_DEBUG_B	hp100_outw(0x4210, TRACE);	printk("hp100: %s: start_xmit_bm\n", dev->name);#endif	if (skb == NULL) {		return 0;	}	if (skb->len <= 0)		return 0;	/* Get Tx ring tail pointer */	if (lp->txrtail->next == lp->txrhead) {		/* No memory. */#ifdef HP100_DEBUG		printk("hp100: %s: start_xmit_bm: No TX PDL available.\n", dev->name);#endif		/* not waited long enough since last tx? */		if (jiffies - dev->trans_start < HZ)			return -EAGAIN;		if (lp->lan_type < 0) {	/* no LAN type detected yet? */			hp100_stop_interface(dev);			if ((lp->lan_type = hp100_sense_lan(dev)) < 0) {				printk("hp100: %s: no connection found - check wire\n", dev->name);				hp100_start_interface(dev);	/* 10Mb/s RX pkts maybe handled */				return -EIO;			}			if (lp->lan_type == HP100_LAN_100)				lp->hub_status = hp100_login_to_vg_hub(dev, FALSE);	/* relogin */			hp100_start_interface(dev);		}		if (lp->lan_type == HP100_LAN_100 && lp->hub_status < 0) {			/* we have a 100Mb/s adapter but it isn't connected to hub */			printk("hp100: %s: login to 100Mb/s hub retry\n", dev->name);			hp100_stop_interface(dev);			lp->hub_status = hp100_login_to_vg_hub(dev, FALSE);			hp100_start_interface(dev);		} else {			spin_lock_irqsave(&lp->lock, flags);			hp100_ints_off();	/* Useful ? Jean II */			i = hp100_sense_lan(dev);			hp100_ints_on();			spin_unlock_irqrestore(&lp->lock, flags);			if (i == HP100_LAN_ERR)				printk("hp100: %s: link down detected\n", dev->name);			else if (lp->lan_type != i) {	/* cable change! */				/* it's very hard - all network setting must be changed!!! */				printk("hp100: %s: cable change 10Mb/s <-> 100Mb/s detected\n", dev->name);				lp->lan_type = i;				hp100_stop_interface(dev);				if (lp->lan_type == HP100_LAN_100)					lp->hub_status = hp100_login_to_vg_hub(dev, FALSE);				hp100_start_interface(dev);			} else {				printk("hp100: %s: interface reset\n", dev->name);				hp100_stop_interface(dev);				if (lp->lan_type == HP100_LAN_100)					lp->hub_status = hp100_login_to_vg_hub(dev, FALSE);				hp100_start_interface(dev);			}		}		dev->trans_start = jiffies;		return -EAGAIN;	}	/*	 * we have to turn int's off before modifying this, otherwise	 * a tx_pdl_cleanup could occur at the same time	 */	spin_lock_irqsave(&lp->lock, flags);	ringptr = lp->txrtail;	lp->txrtail = ringptr->next;	/* Check whether packet has minimal packet size */	ok_flag = skb->len >= HP100_MIN_PACKET_SIZE;	i = ok_flag ? skb->len : HP100_MIN_PACKET_SIZE;	ringptr->skb = skb;	ringptr->pdl[0] = ((1 << 16) | i);	/* PDH: 1 Fragment & length */	ringptr->pdl[1] = (u32) virt_to_bus(skb->data);	/* 1st Frag: Adr. of data */	if (lp->chip == HP100_CHIPID_SHASTA) {		/* TODO:Could someone who has the EISA card please check if this works? */		ringptr->pdl[2] = i;	} else {		/* Lassen */		/* In the PDL, don't use the padded size but the real packet size: */		ringptr->pdl[2] = skb->len;	/* 1st Frag: Length of frag */	}	/* Hand this PDL to the card. */	hp100_outl(ringptr->pdl_paddr, TX_PDA_L);	/* Low Prio. Queue */	lp->txrcommit++;	spin_unlock_irqrestore(&lp->lock, flags);	/* Update statistics */	lp->stats.tx_packets++;	lp->stats.tx_bytes += skb->len;	dev->trans_start = jiffies;	return 0;}/* clean_txring checks if packets have been sent by the card by reading * the TX_PDL register from the performance page and comparing it to the * number of commited packets. It then frees the skb's of the packets that * obviously have been sent to the network. * * Needs the PERFORMANCE page selected.  */static void hp100_clean_txring(struct net_device *dev){	struct hp100_private *lp = (struct hp100_private *) dev->priv;	int ioaddr = dev->base_addr;	int donecount;#ifdef HP100_DEBUG_B	hp100_outw(0x4211, TRACE);	printk("hp100: %s: clean txring\n", dev->name);#endif	/* How many PDLs have been transmitted? */	donecount = (lp->txrcommit) - hp100_inb(TX_PDL);#ifdef HP100_DEBUG	if (donecount > MAX_TX_PDL)		printk("hp100: %s: Warning: More PDLs transmitted than commited to card???\n", dev->name);#endif	for (; 0 != donecount; donecount--) {#ifdef HP100_DEBUG_BM		printk("hp100: %s: Free skb: data @0x%.8x txrcommit=0x%x TXPDL=0x%x, done=0x%x\n",				dev->name, (u_int) lp->txrhead->skb->data,				lp->txrcommit, hp100_inb(TX_PDL), donecount);#endif		dev_kfree_skb_any(lp->txrhead->skb);		lp->txrhead->skb = (void *) NULL;		lp->txrhead = lp->txrhead->next;		lp->txrcommit--;	}}/* tx function for slave modes */static int hp100_start_xmit(struct sk_buff *skb, struct net_device *dev){	unsigned long flags;	int i, ok_flag;	int ioaddr = dev->base_addr;	u_short val;	struct hp100_private *lp = (struct hp100_private *) dev->priv;#ifdef HP100_DEBUG_B	hp100_outw(0x4212, TRACE);	printk("hp100: %s: start_xmit\n", dev->name);#endif	if (skb == NULL) {		return 0;	}	if (skb->len <= 0)		return 0;	if (lp->lan_type < 0) {	/* no LAN type detected yet? */		hp100_stop_interface(dev);		if ((lp->lan_type = hp100_sense_lan(dev)) < 0) {			printk("hp100: %s: no connection found - check wire\n", dev->name);			hp100_start_interface(dev);	/* 10Mb/s RX packets maybe handled */			return -EIO;		}		if (lp->lan_type == HP100_LAN_100)			lp->hub_status = hp100_login_to_vg_hub(dev, FALSE);	/* relogin */		hp100_start_interface(dev);	}	/* If there is not enough free memory on the card... */	i = hp100_inl(TX_MEM_FREE) & 0x7fffffff;	if (!(((i / 2) - 539) > (skb->len + 16) && (hp100_inb(TX_PKT_CNT) < 255))) {#ifdef HP100_DEBUG		printk("hp100: %s: start_xmit: tx free mem = 0x%x\n", dev->name, i);#endif		/* not waited long enough since last failed tx try? */		if (jiffies - dev->trans_start < HZ) {#ifdef HP100_DEBUG			printk("hp100: %s: trans_start timing problem\n",			       dev->name);#endif			return -EAGAIN;		}		if (lp->lan_type == HP100_LAN_100 && lp->hub_status < 0) {			/* we have a 100Mb/s adapter but it isn't connected to hub */			printk("hp100: %s: login to 100Mb/s hub retry\n", dev->name);			hp100_stop_interface(dev);			lp->hub_status = hp100_login_to_vg_hub(dev, FALSE);			hp100_start_interface(dev);		} else {			spin_lock_irqsave(&lp->lock, flags);			hp100_ints_off();	/* Useful ? Jean II */			i = hp100_sense_lan(dev);			hp100_ints_on();			spin_unlock_irqrestore(&lp->lock, flags);			if (i == HP100_LAN_ERR)				printk("hp100: %s: link down detected\n", dev->name);			else if (lp->lan_type != i) {	/* cable change! */				/* it's very hard - all network setting must be changed!!! */				printk("hp100: %s: cable change 10Mb/s <-> 100Mb/s detected\n", dev->name);

⌨️ 快捷键说明

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