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

📄 xircom_tulip_cb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 net_device *dev, int phy_id, int location){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	int i;	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;	int retval = 0;	long ioaddr = dev->base_addr;	long mdio_addr = ioaddr + CSR9;	if (tp->chip_id == LC82C168) {		int i = 1000;		outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);		inl(ioaddr + 0xA0);		inl(ioaddr + 0xA0);		while (--i > 0)			if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))				return retval & 0xffff;		return 0xffff;	}	if (tp->chip_id == COMET) {		if (phy_id == 1) {			if (location < 7)				return inl(ioaddr + 0xB4 + (location<<2));			else if (location == 17)				return inl(ioaddr + 0xD0);			else if (location >= 29 && location <= 31)				return inl(ioaddr + 0xD4 + ((location-29)<<2));		}		return 0xffff;	}	/* 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 net_device *dev, int phy_id, int location, int value){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	int i;	int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;	long ioaddr = dev->base_addr;	long mdio_addr = ioaddr + CSR9;	if (tp->chip_id == LC82C168) {		int i = 1000;		outl(cmd, ioaddr + 0xA0);		do			if ( ! (inl(ioaddr + 0xA0) & 0x80000000))				break;		while (--i > 0);		return;	}	if (tp->chip_id == COMET) {		if (phy_id != 1)			return;		if (location < 7)			outl(value, ioaddr + 0xB4 + (location<<2));		else if (location == 17)			outl(value, ioaddr + 0xD0);		else if (location >= 29 && location <= 31)			outl(value, ioaddr + 0xD4 + ((location-29)<<2));		return;	}	/* 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();	}	return;}static voidtulip_up(struct net_device *dev){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	long ioaddr = dev->base_addr;	int i;	/* On some chip revs we must set the MII/SYM port before the reset!? */	if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii))		outl_CSR6(0x00040000, ioaddr, tp->chip_id);	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */	outl(0x00000001, ioaddr + CSR0);	/* Deassert reset. */	outl(tp->csr0, ioaddr + CSR0);	udelay(2);	if (tulip_tbl[tp->chip_id].flags & HAS_ACPI)		pci_write_config_dword(tp->pdev, 0x40, 0x00000000);	/* Clear the tx ring */	for (i = 0; i < TX_RING_SIZE; i++) {		tp->tx_skbuff[i] = 0;		tp->tx_ring[i].status = 0x00000000;	}	if (tulip_debug > 1)		printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq);	if (tulip_tbl[tp->chip_id].flags & MC_HASH_ONLY) {		u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));		u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));		if (tp->chip_id == AX88140) {			outl(0, ioaddr + CSR13);			outl(addr_low,  ioaddr + CSR14);			outl(1, ioaddr + CSR13);			outl(addr_high, ioaddr + CSR14);		} else if (tp->chip_id == COMET) {			outl(addr_low,  ioaddr + 0xA4);			outl(addr_high, ioaddr + 0xA8);			outl(0, ioaddr + 0xAC);			outl(0, ioaddr + 0xB0);		}	} else if (tp->chip_id != X3201_3) {		/* This is set_rx_mode(), but without starting the transmitter. */		u16 *eaddrs = (u16 *)dev->dev_addr;		u16 *setup_frm = &tp->setup_frame[15*6];		/* 21140 bug: you must add the broadcast address. */		memset(tp->setup_frame, 0xff, 96*sizeof(u16));		/* Fill the final entry of the table with our physical address. */		*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];		*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];		*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];		/* Put the setup frame on the Tx list. */		tp->tx_ring[0].length = 0x08000000 | 192;		tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame);		tp->tx_ring[0].status = DescOwned;		tp->cur_tx++;	} else { /* X3201_3 */		u16 *eaddrs = (u16 *)dev->dev_addr;		u16 *setup_frm = &tp->setup_frame[0*6];				/* fill the table with the broadcast address */		memset(tp->setup_frame, 0xff, 96*sizeof(u16));		/* re-fill the first 14 table entries with our address */		for(i=0; i<14; i++) {			*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];			*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];			*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];		}		/* Put the setup frame on the Tx list. */		tp->tx_ring[0].length = 0x08000000 | 192;		/* Lie about the address of our setup frame to make the */		/* chip happy */		tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame);		tp->tx_ring[0].status = DescOwned;		tp->cur_tx++;	}	outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);	outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);	tp->saved_if_port = dev->if_port;	if (dev->if_port == 0)		dev->if_port = tp->default_port;	if (tp->chip_id == DC21041  &&  dev->if_port > 4)		/* Invalid: Select initial TP, autosense, autonegotiate.  */		dev->if_port = 4;	/* Allow selecting a default media. */	i = 0;	if (tp->mtable == NULL)		goto media_picked;	if (dev->if_port) {		int looking_for = media_cap[dev->if_port] & MediaIsMII ? 11 :			(dev->if_port == 12 ? 0 : dev->if_port);		for (i = 0; i < tp->mtable->leafcount; i++)			if (tp->mtable->mleaf[i].media == looking_for) {				printk(KERN_INFO "%s: Using user-specified media %s.\n",					   dev->name, medianame[dev->if_port]);				goto media_picked;			}	}	if ((tp->mtable->defaultmedia & 0x0800) == 0) {		int looking_for = tp->mtable->defaultmedia & 15;		for (i = 0; i < tp->mtable->leafcount; i++)			if (tp->mtable->mleaf[i].media == looking_for) {				printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",					   dev->name, medianame[looking_for]);				goto media_picked;			}	}	/* Start sensing first non-full-duplex media. */	for (i = tp->mtable->leafcount - 1;		 (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)		;media_picked:	tp->csr6 = 0;	tp->cur_index = i;	if (dev->if_port == 0  &&  tp->chip_id == DC21142) {		if (tp->mii_cnt) {			select_media(dev, 1);			if (tulip_debug > 1)				printk(KERN_INFO "%s: Using MII transceiver %d, status "					   "%4.4x.\n",					   dev->name, tp->phys[0], mdio_read(dev, tp->phys[0], 1));			outl_CSR6(0x82020000, ioaddr, tp->chip_id);			tp->csr6 = 0x820E0000;			dev->if_port = 11;			outl(0x0000, ioaddr + CSR13);			outl(0x0000, ioaddr + CSR14);		} else			t21142_start_nway(dev);	} else if ((tp->chip_id == LC82C168  || tp->chip_id == PNIC2)			   &&  tp->mii_cnt && ! tp->medialock) {		dev->if_port = 11;		tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);		outl(0x0001, ioaddr + CSR15);	} else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881)			   && ! tp->medialock) {		dev->if_port = 0;		tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);	} else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) {		/* Provided by BOLO, Macronix - 12/10/1998. */		dev->if_port = 0;		tp->csr6 = 0x01880200;		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);		outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);	} else if (tp->chip_id == DC21143  &&			   media_cap[dev->if_port] & MediaIsMII) {		/* We must reset the media CSRs when we force-select MII mode. */		outl(0x0000, ioaddr + CSR13);		outl(0x0000, ioaddr + CSR14);		outl(0x0008, ioaddr + CSR15);	} else if (tp->chip_id == X3201_3) {		outl(0x0008, ioaddr + CSR15);		udelay(5);		outl(0xa8050000, ioaddr + CSR15);		udelay(5);		outl(0xa00f0000, ioaddr + CSR15); 		udelay(5);		tp->csr6  = 0x32400000;	} else if (tp->chip_id == COMET) {		dev->if_port = 0;		tp->csr6 = 0x00040000;	} else		select_media(dev, 1);	/* Start the chip's Tx to process setup frame. */	outl_CSR6(tp->csr6, ioaddr, tp->chip_id);	outl_CSR6(tp->csr6 | 0x2000, ioaddr, tp->chip_id);	/* Enable interrupts by setting the interrupt mask. */	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);	outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);	outl(0, ioaddr + CSR2);		/* Rx poll demand */		netif_start_queue (dev);	if (tulip_debug > 2) {		printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",			   dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),			   inl(ioaddr + CSR6));	}	/* Set the timer to switch to check for link beat and perhaps switch	   to an alternate media type. */	init_timer(&tp->timer);	tp->timer.expires = RUN_AT(5*HZ);	tp->timer.data = (unsigned long)dev;	tp->timer.function = tulip_tbl[tp->chip_id].media_timer;	add_timer(&tp->timer);}static inttulip_open(struct net_device *dev){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))		return -EAGAIN;	tulip_init_ring(dev);	tulip_up(dev);	tp->open = 1;	MOD_INC_USE_COUNT;	return 0;}/* Set up the transceiver control registers for the selected media type. */static void select_media(struct net_device *dev, int startup){	long ioaddr = dev->base_addr;	struct tulip_private *tp = (struct tulip_private *)dev->priv;	struct mediatable *mtable = tp->mtable;	u32 new_csr6;	int i;	if (mtable) {		struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];		unsigned char *p = mleaf->leafdata;		switch (mleaf->type) {		case 0:					/* 21140 non-MII xcvr. */			if (tulip_debug > 1)				printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver"					   " with control setting %2.2x.\n",					   dev->name, p[1]);			dev->if_port = p[0];			if (startup)				outl(mtable->csr12dir | 0x100, ioaddr + CSR12);			outl(p[1], ioaddr + CSR12);			new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);			break;		case 2: case 4: {			u16 setup[5];			u32 csr13val, csr14val, csr15dir, csr15val;			for (i = 0; i < 5; i++)				setup[i] = get_u16(&p[i*2 + 1]);			dev->if_port = p[0] & 15;			if (media_cap[dev->if_port] & MediaAlwaysFD)				tp->full_duplex = 1;			if (startup && mtable->has_reset) {				struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];				unsigned char *rst = rleaf->leafdata;				if (tulip_debug > 1)					printk(KERN_DEBUG "%s: Resetting the transceiver.\n",						   dev->name);				for (i = 0; i < rst[0]; i++)					outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);			}			if (tulip_debug > 1)				printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control "					   "%4.4x/%4.4x.\n",					   dev->name, medianame[dev->if_port], setup[0], setup[1]);			if (p[0] & 0x40) {	/* SIA (CSR13-15) setup values are provided. */				csr13val = setup[0];

⌨️ 快捷键说明

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