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

📄 xircom_cb.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
must be called with the lock held and interrupts disabled.*/static void enable_receive_interrupt(struct xircom_private *card){	unsigned int val;	enter();	val = inl(card->io_port + CSR7);	/* Interrupt enable register */	val = val | (1 << 6);			/* enable the receive interrupt */	outl(val, card->io_port + CSR7);	leave();}/*enable_link_interrupt enables the link status change interruptmust be called with the lock held and interrupts disabled.*/static void enable_link_interrupt(struct xircom_private *card){	unsigned int val;	enter();	val = inl(card->io_port + CSR7);	/* Interrupt enable register */	val = val | LinkStatusBit;			/* enable the link status chage interrupt */	outl(val, card->io_port + CSR7);	leave();}/*disable_all_interrupts disables all interruptsmust be called with the lock held and interrupts disabled.*/static void disable_all_interrupts(struct xircom_private *card){	unsigned int val;	enter();		val = 0;				/* disable all interrupts */	outl(val, card->io_port + CSR7);	leave();}/*enable_common_interrupts enables several weird interruptsmust be called with the lock held and interrupts disabled.*/static void enable_common_interrupts(struct xircom_private *card){	unsigned int val;	enter();	val = inl(card->io_port + CSR7);	/* Interrupt enable register */	val |= (1<<16); /* Normal Interrupt Summary */	val |= (1<<15); /* Abnormal Interrupt Summary */	val |= (1<<13); /* Fatal bus error */	val |= (1<<8);  /* Receive Process Stopped */	val |= (1<<7);  /* Receive Buffer Unavailable */	val |= (1<<5);  /* Transmit Underflow */	val |= (1<<2);  /* Transmit Buffer Unavailable */	val |= (1<<1);  /* Transmit Process Stopped */	outl(val, card->io_port + CSR7);	leave();}/*enable_promisc starts promisc modemust be called with the lock held and interrupts disabled.*/static inline void enable_promisc(struct xircom_private *card){	unsigned int val;	enter();	val = inl(card->io_port + CSR6);		val = val | PromiscBit;	 /* Bit 6 */	outl(val, card->io_port + CSR6);	printk(KERN_INFO "xircom_cb: enabling promiscuous mode \n");	leave();}/* link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what.Must be called in locked state with interrupts disabled*/static inline unsigned int link_status(struct xircom_private *card){	unsigned int val;	enter();		val = inb(card->io_port + CSR12);		if (!(val&(1<<2)))  /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */		return 10;	if (!(val&(1<<1)))  /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */		return 100;			/* If we get here -> no link at all */		leave();	return 0;}/* set_half_duplex() sets the card to half duplex mode. In order to do this,set_half_duplex() has to deactivate the transmitter and receiver first. Itwill re-enable the transmitter and receiver if those were active from thebeginning.Update: the above is not enough. It doesn't touch the MII, in fact it ensuresthe main chipset and the MII are never in sync if a full-duplex connectionis negotiated. The proper fix is to tell the MII to force a half-duplexconnection. -IonMust be called in locked state*/static void set_half_duplex(struct xircom_private *card){	unsigned int val;	int rx,tx,tmp;	enter();		rx=receive_active(card);	tx=transmit_active(card);		deactivate_transmitter(card);	deactivate_receiver(card);		val = inb(card->io_port + CSR6);	val &= ~(1<<9);	outb(val,card->io_port + CSR6);	/* tell the MII not to advertise 10/100FDX */	tmp = mdio_read(card, 0, 4);	printk("xircom_cb: capabilities changed from %#x to %#x\n",	       tmp, tmp & ~0x140);	tmp &= ~0x140;	mdio_write(card, 0, 4, tmp);	/* restart autonegotiation */	tmp = mdio_read(card, 0, 0);	mdio_write(card, 0, 0, tmp | 0x1200);	if (rx)		activate_receiver(card);	if (tx)		activate_transmitter(card);		leave();}/*  read_mac_address() reads the MAC address from the NIC and stores it in the "dev" structure.   This function will take the spinlock itself and can, as a result, not be called with the lock helt. */static void read_mac_address(struct xircom_private *card){	unsigned char j, tuple, link, data_id, data_count;	unsigned long flags;	int i;	enter();			spin_lock_irqsave(&card->lock, flags);	outl(1 << 12, card->io_port + CSR9);	/* enable boot rom access */	for (i = 0x100; i < 0x1f7; i += link + 2) {		outl(i, card->io_port + CSR10);		tuple = inl(card->io_port + CSR9) & 0xff;		outl(i + 1, card->io_port + CSR10);		link = inl(card->io_port + CSR9) & 0xff;		outl(i + 2, card->io_port + CSR10);		data_id = inl(card->io_port + CSR9) & 0xff;		outl(i + 3, card->io_port + CSR10);		data_count = inl(card->io_port + CSR9) & 0xff;		if ((tuple == 0x22) && (data_id == 0x04) && (data_count == 0x06)) {			/* 			 * This is it.  We have the data we want.			 */			for (j = 0; j < 6; j++) {				outl(i + j + 4, card->io_port + CSR10);				card->dev->dev_addr[j] = inl(card->io_port + CSR9) & 0xff;			}			break;		} else if (link == 0) {			break;		}	}	spin_unlock_irqrestore(&card->lock, flags);#ifdef DEBUG	for (i = 0; i < 6; i++)		printk("%c%2.2X", i ? ':' : ' ', card->dev->dev_addr[i]);	printk("\n");#endif	leave();}/* MII transceiver control section.   Read and write the MII registers using software-generated serial   MDIO protocol.  See the MII specifications or DP83840A data sheet   for details. *//* The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually   met by back-to-back PCI I/O cycles, but we insert a delay to avoid   "overclocking" issues or future 66Mhz PCI. */#define mdio_delay() inl(mdio_addr)/* Read and write the MII registers using software-generated serial   MDIO protocol.  It is just different enough from the EEPROM protocol   to not share code.  The maxium data clock rate is 2.5 Mhz. */#define MDIO_SHIFT_CLK	0x10000#define MDIO_DATA_WRITE0 0x00000#define MDIO_DATA_WRITE1 0x20000#define MDIO_ENB	0x00000		/* Ignore the 0x02000 databook setting. */#define MDIO_ENB_IN	0x40000#define MDIO_DATA_READ	0x80000static int mdio_read(struct xircom_private *card, int phy_id, int location){	int i;	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;	int retval = 0;	long mdio_addr = card->io_port + CSR9;	/* Establish sync by sending at least 32 logic ones. */	for (i = 32; i >= 0; i--) {		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);		mdio_delay();		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Shift the read command bits out. */	for (i = 15; i >= 0; i--) {		int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;		outl(MDIO_ENB | dataval, mdio_addr);		mdio_delay();		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Read the two transition, 16 data, and wire-idle bits. */	for (i = 19; i > 0; i--) {		outl(MDIO_ENB_IN, mdio_addr);		mdio_delay();		retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	return (retval>>1) & 0xffff;}static void mdio_write(struct xircom_private *card, int phy_id, int location, int value){	int i;	int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;	long mdio_addr = card->io_port + CSR9;	/* Establish sync by sending 32 logic ones. */	for (i = 32; i >= 0; i--) {		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);		mdio_delay();		outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Shift the command bits out. */	for (i = 31; i >= 0; i--) {		int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;		outl(MDIO_ENB | dataval, mdio_addr);		mdio_delay();		outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}	/* Clear out extra bits. */	for (i = 2; i > 0; i--) {		outl(MDIO_ENB_IN, mdio_addr);		mdio_delay();		outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);		mdio_delay();	}}/* tranceiver_voodoo() enables the external UTP plug thingy. it's called voodoo as I stole this code and cannot cross-reference it with the specification. */static void tranceiver_voodoo(struct xircom_private *card){	unsigned long flags;	u32 tmp32;	enter();	/* disable all powermanagement */	pci_read_config_dword(card->pdev, PCI_POWERMGMT,&tmp32);	tmp32 &= ~PowerMgmtBits; 	pci_write_config_dword(card->pdev, PCI_POWERMGMT, tmp32);	setup_descriptors(card);	spin_lock_irqsave(&card->lock, flags);	outl(0x0008, card->io_port + CSR15);        udelay(25);          outl(0xa8050000, card->io_port + CSR15);        udelay(25);        outl(0xa00f0000, card->io_port + CSR15);        udelay(25);                spin_unlock_irqrestore(&card->lock, flags);	netif_start_queue(card->dev);	leave();}static void xircom_up(struct xircom_private *card){	unsigned long flags;	int i;	u32 tmp32;	enter();	/* disable all powermanagement */	pci_read_config_dword(card->pdev, PCI_POWERMGMT,&tmp32);	tmp32 &= ~PowerMgmtBits; 	pci_write_config_dword(card->pdev, PCI_POWERMGMT, tmp32);	setup_descriptors(card);	spin_lock_irqsave(&card->lock, flags);		enable_link_interrupt(card);	enable_transmit_interrupt(card);	enable_receive_interrupt(card);	enable_common_interrupts(card);	enable_promisc(card);		/* The card can have received packets already, read them away now */	for (i=0;i<NUMDESCRIPTORS;i++) 		investigate_rx_descriptor(card->dev,card,i,bufferoffsets[i]);	set_half_duplex(card);	spin_unlock_irqrestore(&card->lock, flags);	trigger_receive(card);	trigger_transmit(card);	netif_start_queue(card->dev);	leave();}static void investigate_rx_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset){		int status;						enter();		status = card->rx_desc[descnr].status;				if ((status > 0)) {	/* packet received */					/* TODO: discard error packets */						short pkt_len = ((status >> 16) & 0x7ff) - 4;	/* minus 4, we don't want the CRC */			struct sk_buff *skb;			if (pkt_len > 1518) {				printk(KERN_ERR "xircom_cb: Packet length %i is bogus \n",pkt_len);				pkt_len = 1518;			}			skb = dev_alloc_skb(pkt_len + 2);			if (skb == NULL) {				card->stats.rx_dropped++;				goto out;			}			skb->dev = dev;			skb_reserve(skb, 2);			eth_copy_and_sum(skb, &card->rx_buffer[bufferoffset], pkt_len, 0);			skb_put(skb, pkt_len);			skb->protocol = eth_type_trans(skb, dev);			netif_rx(skb);			dev->last_rx = jiffies;			card->stats.rx_packets++;			card->stats.rx_bytes += pkt_len;					      out:			/* give the buffer back to the card */			card->rx_desc[descnr].status = DescOwnedCard;			trigger_receive(card);		}		leave();}/* Returns 1 if the descriptor is free or became free */static unsigned int investigate_tx_descriptor(struct net_device *dev, struct xircom_private *card, unsigned int descnr, unsigned int bufferoffset){		int status,retval = 0;		enter();				status = card->tx_desc[descnr].status;				if (status == DescOwnedDriver)			return 1;#if 0				if (status & 0x8000) {	/* Major error */			printk(KERN_ERR "Major transmit error status %x \n", status);			card->tx_desc[descnr].status = 0;			netif_wake_queue (dev);		}#endif		if (status > 0) {	/* bit 31 is 0 when done */			card->stats.tx_packets++;			if (card->tx_skb[descnr]!=NULL) {				card->stats.tx_bytes += card->tx_skb[descnr]->len;				dev_kfree_skb_irq(card->tx_skb[descnr]);			}			card->tx_skb[descnr] = NULL;			/* Bit 8 in the status field is 1 if there was a collision */			if (status & CollisionBit)				card->stats.collisions++;			card->tx_desc[descnr].status = DescOwnedDriver; /* descriptor is free again */			retval = 1;		}		leave();		return retval;		}static int __init xircom_init(void){	pci_register_driver(&xircom_ops);	return 0;}static void __exit xircom_exit(void){	pci_unregister_driver(&xircom_ops);} module_init(xircom_init) module_exit(xircom_exit)

⌨️ 快捷键说明

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