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

📄 tulip.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 inttulip_open(struct device *dev){	struct tulip_private *tp = (struct tulip_private *)dev->priv;	long ioaddr = dev->base_addr;	int i = 0;	/* 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(0x00040000, ioaddr + CSR6);	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */	outl(0x00000001, ioaddr + CSR0);#ifdef _LINUX_DELAY_H	udelay(2);#else	SLOW_DOWN_IO;#endif	/* Deassert reset.	   486: Set 8 longword cache alignment, 8 longword burst.	   586: Set 16 longword cache alignment, no burst limit.	   Cache alignment bits 15:14	     Burst length 13:8		0000	No alignment  0x00000000 unlimited		0800 8 longwords		4000	8  longwords		0100 1 longword		1000 16 longwords		8000	16 longwords		0200 2 longwords	2000 32 longwords		C000	32  longwords		0400 4 longwords	   Wait the specified 50 PCI cycles after a reset by initializing	   Tx and Rx queues and the address filter list. */#if defined(__alpha__)	/* ToDo: Alpha setting could be better. */	outl(0x01A00000 | 0xE000, ioaddr + CSR0);#elif defined(__powerpc__)	outl(0x01A00080 | 0x8000, ioaddr + CSR0);#elif defined(__i386__)#if defined(MODULE)	/* When a module we don't have 'x86' to check. */	outl(0x01A00000 | 0x4800, ioaddr + CSR0);#else#if (LINUX_VERSION_CODE > 0x2014c)#define x86 boot_cpu_data.x86#endif	outl(0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0);	if (x86 <= 4)	  printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache "			 "alignment to %x.\n", dev->name,			 0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000));#endif#else	outl(0x01A00000 | 0x4800, ioaddr + CSR0);#warning Processor architecture undefined!#endif#ifdef SA_SHIRQ	if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)) {		return -EAGAIN;	}#else	if (irq2dev_map[dev->irq] != NULL		|| (irq2dev_map[dev->irq] = dev) == NULL		|| dev->irq == 0		|| request_irq(dev->irq, &tulip_interrupt, 0,					   tulip_tbl[tp->chip_id].chip_name)) {		return -EAGAIN;	}#endif	if (tulip_debug > 1)		printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq);	MOD_INC_USE_COUNT;	tulip_init_ring(dev);	/* This is set_rx_mode(), but without starting the transmitter. */	/* Fill the whole address filter table with our physical address. */	{		u16 *eaddrs = (u16 *)dev->dev_addr;		u32 *setup_frm = tp->setup_frame, i;		/* You must add the broadcast address when doing perfect filtering! */		*setup_frm++ = 0xffff;		*setup_frm++ = 0xffff;		*setup_frm++ = 0xffff;		/* Fill the rest of the accept table with our physical address. */		for (i = 1; i < 16; i++) {			*setup_frm++ = eaddrs[0];			*setup_frm++ = eaddrs[1];			*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 = 0x80000000;		tp->cur_tx++;	}	outl(virt_to_bus(tp->rx_ring), ioaddr + CSR3);	outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);	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. */	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)		for (i = 0; i < tp->mtable->leafcount; i++)		  if (tp->mtable->mleaf[i].media == (tp->mtable->defaultmedia & 15)) {			printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",				   dev->name, medianame[tp->mtable->mleaf[i].media]);			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) {		tp->csr6 = 0x82420200;		outl(0x0003FFFF, ioaddr + CSR14);		outl(0x0008, ioaddr + CSR15);		outl(0x0001, ioaddr + CSR13);		outl(0x1301, ioaddr + CSR12);	} else if (tp->chip_id == LC82C168  &&  tp->mii_cnt && ! tp->medialock) {		dev->if_port = 11;		tp->csr6 = 0x816C0000 | (tp->full_duplex ? 0x0200 : 0);		outl(0x0001, ioaddr + CSR15);	} else		select_media(dev, 1);	/* Start the chip's Tx to process setup frame. */	outl(tp->csr6, ioaddr + CSR6);	outl(tp->csr6 | 0x2000, ioaddr + CSR6);	dev->tbusy = 0;	tp->interrupt = 0;	dev->start = 1;	/* 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(tp->csr6 | 0x2002, ioaddr + CSR6);	outl(0, ioaddr + CSR2);		/* Rx poll demand */	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);	return 0;}/* Set up the transceiver control registers for the selected media type. */static void select_media(struct 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 check_mii =0, 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[3];			for (i = 0; i < 3; i++)				setup[i] = get_u16(&p[i*2 + 1]);			dev->if_port = p[0] & 15;			if (tulip_debug > 1)				printk(KERN_DEBUG "%s: 21142 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. */				outl(0, ioaddr + CSR13);				outl(setup[1], ioaddr + CSR14);				outl(setup[2], ioaddr + CSR15);				outl(setup[0], ioaddr + CSR13);				for (i = 0; i < 3; i++)			/* Re-fill setup[]  */					setup[i] = get_u16(&p[i*2 + 7]);			} else if (dev->if_port <= 4) {				outl(0, ioaddr + CSR13);				outl(t21142_csr14[dev->if_port], ioaddr + CSR14);				outl(t21142_csr15[dev->if_port], ioaddr + CSR15);				outl(t21142_csr13[dev->if_port], ioaddr + CSR13);			} else {				outl(0, ioaddr + CSR14);				outl(8, ioaddr + CSR15);				outl(0, ioaddr + CSR13);			}			outl(setup[0]<<16, ioaddr + CSR15);	/* Direction */			outl(setup[1]<<16, ioaddr + CSR15);	/* Data */			if (mleaf->type == 4)				new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);			else				new_csr6 = 0x82420000;			break;		}		case 1: case 3: {			int phy_num = p[0];			int init_length = p[1];			u16 *misc_info;			u16 to_advertise;			dev->if_port = 11;			check_mii = 1;			new_csr6 = 0x020E0000;			if (mleaf->type == 3) {	/* 21142 */				u16 *init_sequence = (u16*)(p+2);				u16 *reset_sequence = &((u16*)(p+3))[init_length];				int reset_length = p[2 + init_length*2];				misc_info = reset_sequence + reset_length;				if (startup)					for (i = 0; i < reset_length; i++)						outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);				for (i = 0; i < init_length; i++)					outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);			} else {				u8 *init_sequence = p + 2;				u8 *reset_sequence = p + 3 + init_length;				int reset_length = p[2 + init_length];				misc_info = (u16*)(reset_sequence + reset_length);				if (startup) {					outl(mtable->csr12dir | 0x100, ioaddr + CSR12);					for (i = 0; i < reset_length; i++)						outl(reset_sequence[i], ioaddr + CSR12);				}				for (i = 0; i < init_length; i++)					outl(init_sequence[i], ioaddr + CSR12);			}			to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1;			tp->advertising[phy_num] = to_advertise;			if (tulip_debug > 1 || 1)				printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d (%d).\n",					   dev->name, to_advertise, phy_num, tp->phys[phy_num]);			/* Bogus: put in by a committee?  */			mdio_write(dev, tp->phys[phy_num], 4, to_advertise);			break;		}		default:		  new_csr6 = 0x020E0000;		}		if (tulip_debug > 1)			printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n",				   dev->name, medianame[dev->if_port],				   inl(ioaddr + CSR12) & 0xff);	} else if (tp->chip_id == DC21041) {		if (tulip_debug > 1)			printk(KERN_DEBUG "%s: 21041 using media %s, CSR12 is %4.4x.\n",				   dev->name, medianame[dev->if_port & 15],				   inl(ioaddr + CSR12) & 0xffff);		outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */		outl(t21041_csr14[dev->if_port], ioaddr + CSR14);		outl(t21041_csr15[dev->if_port], ioaddr + CSR15);		outl(t21041_csr13[dev->if_port], ioaddr + CSR13);		new_csr6 = 0x80020000;	} else if (tp->chip_id == LC82C168) {		if (startup && ! tp->medialock)			dev->if_port = tp->mii_cnt ? 11 : 0;		if (tulip_debug > 1)			printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, CSR12 %4.4x,"				   " media %s.\n",				   dev->name, inl(ioaddr + 0xB8), inl(ioaddr + CSR12),				   medianame[dev->if_port]);		if (tp->mii_cnt) {			new_csr6 = 0x812C0000;			outl(0x0001, ioaddr + CSR15);			outl(0x0201B07A, ioaddr + 0xB8);		} else if (startup) {			/* Start with 10mbps to do autonegotiation. */			outl(0x32, ioaddr + CSR12);			new_csr6 = 0x00420000;			outl(0x0001B078, ioaddr + 0xB8);			outl(0x0201B078, ioaddr + 0xB8);		} else if (dev->if_port == 3  ||  dev->if_port == 5) {			outl(0x33, ioaddr + CSR12);			new_csr6 = 0x01860000;			if (startup)				outl(0x0201F868, ioaddr + 0xB8); /* Trigger autonegotiation. */			else				outl(0x1F868, ioaddr + 0xB8);		} else {			outl(0x32, ioaddr + CSR12);			new_csr6 = 0x00420000;			outl(0x1F078, ioaddr + 0xB8);		}	} else if (tp->chip_id == DC21040) {					/* 21040 */		/* Turn on the xcvr interface. */		int csr12 = inl(ioaddr + CSR12);		if (tulip_debug > 1)			printk(KERN_DEBUG "%s: 21040 media type is %s, CSR12 is %2.2x.\n",				   dev->name, dev->if_port ? "AUI" : "10baseT", csr12);		new_csr6 = (dev->if_port ? 0x01860000 : 0x00420000);		/* Set the full duplux match frame. */		outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);		outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */		outl(dev->if_port ? 0x0000000C : 0x00000004, ioaddr + CSR13);	} else {					/* Unknown chip type with no media table. */		if (tp->default_port == 0)			if (tp->mii_cnt) {				dev->if_port = 11;			} else				dev->if_port = 3;		if (media_cap[dev->if_port] & MediaIsMII) {			new_csr6 = 0x020E0000;		} else if (media_cap[dev->if_port] & MediaIsFx) {			new_csr6 = 0x028600000;		} else			new_csr6 = 0x038600000;		if (tulip_debug > 1)			printk(KERN_DEBUG "%s: No media description table, assuming "				   "%s transceiver, CSR12 %2.2x.\n",				   dev->name, medianame[dev->if_port],				   inl(ioaddr + CSR12));	}	tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);	return;}static void tulip_timer(unsigned long data){	struct device *dev = (struct device *)data;	struct tulip_private *tp = (struct tulip_private *)dev->priv;	long ioaddr = dev->base_addr;	u32 csr12 = inl(ioaddr + CSR12);	int next_tick = 0;	if (tulip_debug > 3) {		printk(KERN_DEBUG "%s: Media selection tick, status %8.8x mode %8.8x "			   "SIA %8.8x %8.8x %8.8x %8.8x.\n",			   dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR6),			   csr12, inl(ioaddr + CSR13),			   inl(ioaddr + CSR14), inl(ioaddr + CSR15));	}	switch (tp->chip_id) {	case DC21040:		if (csr12 & 0x0002) { /* Network error */			printk(KERN_INFO "%s: No 10baseT link beat found, switching to %s media.\n",				   dev->name, dev->if_port ? "10baseT" : "AUI");			dev->if_port ^= 1;			outl(dev->if_port ? 0x0000000C : 0x00000004, ioaddr + CSR13);			dev->trans_start = jiffies;		}		break;

⌨️ 快捷键说明

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