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

📄 xircom_tulip_cb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				}				/* Enable autonegotiation: some boards default to off. */				mdio_write(dev, phy, 0, mii_reg0 |						   (tp->full_duplex ? 0x1100 : 0x1000) |						   (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));			}		}		tp->mii_cnt = phy_idx;		if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {			printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",				   dev->name);			tp->phys[0] = 1;		}	}	/* The Tulip-specific entries in the device structure. */	dev->open = &tulip_open;	dev->hard_start_xmit = &tulip_start_xmit;	dev->stop = &tulip_close;	dev->get_stats = &tulip_get_stats;#ifdef HAVE_PRIVATE_IOCTL	dev->do_ioctl = &private_ioctl;#endif#ifdef HAVE_MULTICAST	dev->set_multicast_list = &set_rx_mode;#endif	dev->tx_timeout = tulip_tx_timeout;	dev->watchdog_timeo = TX_TIMEOUT;	/* Reset the xcvr interface and turn on heartbeat. */	switch (chip_idx) {	case DC21041:		outl(0x00000000, ioaddr + CSR13);		outl(0xFFFFFFFF, ioaddr + CSR14);		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */		outl_CSR6(inl(ioaddr + CSR6) | 0x0200, ioaddr, chip_idx);		outl(0x0000EF05, ioaddr + CSR13);		break;	case DC21040:		outl(0x00000000, ioaddr + CSR13);		outl(0x00000004, ioaddr + CSR13);		break;	case DC21140: default:		if (tp->mtable)			outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);		break;	case DC21142:	case PNIC2:		if (tp->mii_cnt  ||  media_cap[dev->if_port] & MediaIsMII) {			outl_CSR6(0x82020000, ioaddr, chip_idx);			outl(0x0000, ioaddr + CSR13);			outl(0x0000, ioaddr + CSR14);			outl_CSR6(0x820E0000, ioaddr, chip_idx);		} else {			outl_CSR6(0x82420200, ioaddr, chip_idx);			outl(0x0001, ioaddr + CSR13);			outl(0x0003FFFF, ioaddr + CSR14);			outl(0x0008, ioaddr + CSR15);			outl(0x0001, ioaddr + CSR13);			outl(0x1301, ioaddr + CSR12); /* Start NWay. */		}		break;	case X3201_3:		outl(0x0008, ioaddr + CSR15);		udelay(5);  /* The delays are Xircom recommended to give the					 * chipset time to reset the actual hardware					 * on the PCMCIA card					 */		outl(0xa8050000, ioaddr + CSR15);		udelay(5);		outl(0xa00f0000, ioaddr + CSR15);		udelay(5);		outl_CSR6(0x32000200, ioaddr, chip_idx);		break;	case LC82C168:		if ( ! tp->mii_cnt) {			outl_CSR6(0x00420000, ioaddr, chip_idx);			outl(0x30, ioaddr + CSR12);			outl(0x0001F078, ioaddr + 0xB8);			outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */		}		break;	case MX98713: case COMPEX9881:		outl_CSR6(0x00000000, ioaddr, chip_idx);		outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */		outl(0x00000001, ioaddr + CSR13);		break;	case MX98715: case MX98725:		outl_CSR6(0x01a80000, ioaddr, chip_idx);		outl(0xFFFFFFFF, ioaddr + CSR14);		outl(0x00001000, ioaddr + CSR12);		break;	case COMET:		/* No initialization necessary. */		break;	}	return dev;}/* Serial EEPROM section. *//* The main routine to parse the very complicated SROM structure.   Search www.digital.com for "21X4 SROM" to get details.   This code is very complex, and will require changes to support   additional cards, so I'll be verbose about what is going on.   *//* Known cards that have old-style EEPROMs. */static struct fixups {  char *name;  unsigned char addr0, addr1, addr2;  u16 newtable[32];				/* Max length below. */} eeprom_fixups[] = {  {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,						  0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},  {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x021f,							   0x0000, 0x009E, /* 10baseT */							   0x0903, 0x006D, /* 100baseTx */ }},  {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x033f,								 0x0107, 0x8021, /* 100baseFx */								 0x0108, 0x8021, /* 100baseFx-FD */								 0x0103, 0x006D, /* 100baseTx */ }},  {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0313,							   0x1001, 0x009E, /* 10base2, CSR12 0x10*/							   0x0000, 0x009E, /* 10baseT */							   0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ }},  {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x031F,							0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */							0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */							0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */   }},  {0, 0, 0, 0, {}}};static const char * block_name[] = {"21140 non-MII", "21140 MII PHY", "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};#if defined(__i386__)			/* AKA get_unaligned() */#define get_u16(ptr) (*(u16 *)(ptr))#else#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))#endifstatic void parse_eeprom(struct net_device *dev){	/* The last media info list parsed, for multiport boards.  */	static struct mediatable *last_mediatable;	static unsigned char *last_ee_data;	static int controller_index;	struct tulip_private *tp = (struct tulip_private *)dev->priv;	long ioaddr = dev->base_addr;	unsigned char *ee_data = tp->eeprom;	int i;#ifdef CARDBUS	int chip_rev = tp->revision;#endif	tp->mtable = 0;	for (i = 0; i < EEPROM_SIZE/2; i++)		((u16 *)ee_data)[i] =			le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));	/* Detect an old-style (SA only) EEPROM layout:	   memcmp(eedata, eedata+16, 8). */	for (i = 0; i < 8; i ++)		if (ee_data[i] != ee_data[16+i])			break;	if (i >= 8) {		if (ee_data[0] == 0xff) {			if (last_mediatable) {				controller_index++;				printk(KERN_INFO "%s:  Controller %d of multiport board.\n",					   dev->name, controller_index);				tp->mtable = last_mediatable;				ee_data = last_ee_data;				goto subsequent_board;			} else				printk(KERN_INFO "%s:  Missing EEPROM, this interface may "					   "not work correctly!\n",			   dev->name);			return;		}	  /* Do a fix-up based on the vendor half of the station address prefix. */	  for (i = 0; eeprom_fixups[i].name; i++) {		if (dev->dev_addr[0] == eeprom_fixups[i].addr0			&&  dev->dev_addr[1] == eeprom_fixups[i].addr1			&&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {		  if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)			  i++;			/* An Accton EN1207, not an outlaw Maxtech. */		  memcpy(ee_data + 26, eeprom_fixups[i].newtable,				 sizeof(eeprom_fixups[i].newtable));		  printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"				 " substitute media control info.\n",				 dev->name, eeprom_fixups[i].name);		  break;		}	  }	  if (eeprom_fixups[i].name == NULL) { /* No fixup found. */		  printk(KERN_INFO "%s: Old style EEPROM with no media selection "				 "information.\n",			   dev->name);		return;	  }	}	controller_index = 0;	if (ee_data[19] > 1) {		/* Multiport board. */		last_ee_data = ee_data;	}subsequent_board:	if (ee_data[27] == 0) {		/* No valid media table. */	} else if (tp->chip_id == DC21041) {		unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3];		short media;		int count;		media = get_u16(p);		p += 2;		count = *p++;		printk(KERN_INFO "%s:21041 Media information at %d, default media "			   "%4.4x (%s).\n", dev->name, ee_data[27], media,			   media & 0x0800 ? "Autosense" : medianame[media & 15]);		for (i = 0; i < count; i++) {			unsigned char media_code = *p++;			u16 csrvals[3];			int idx;			for (idx = 0; idx < 3; idx++) {				csrvals[idx] = get_u16(p);				p += 2;			}			if (media_code & 0x40) {				printk(KERN_INFO "%s:  21041 media %2.2x (%s),"					   " csr13 %4.4x csr14 %4.4x csr15 %4.4x.\n",					   dev->name, media_code & 15, medianame[media_code & 15],					   csrvals[0], csrvals[1], csrvals[2]);			} else				printk(KERN_INFO "%s:  21041 media #%d, %s.\n",					   dev->name, media_code & 15, medianame[media_code & 15]);		}	} else {		unsigned char *p = (void *)ee_data + ee_data[27];		unsigned char csr12dir = 0;		int count;		struct mediatable *mtable;		u16 media = get_u16(p);		p += 2;		if (tulip_tbl[tp->chip_id].flags & CSR12_IN_SROM)			csr12dir = *p++;		count = *p++;		mtable = (struct mediatable *)			kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),					GFP_KERNEL);		if (mtable == NULL)			return;				/* Horrible, impossible failure. */		last_mediatable = tp->mtable = mtable;		mtable->defaultmedia = media;		mtable->leafcount = count;		mtable->csr12dir = csr12dir;		mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;		mtable->csr15dir = mtable->csr15val = 0;		printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,			   media & 0x0800 ? "Autosense" : medianame[media & 15]);		for (i = 0; i < count; i++) {			struct medialeaf *leaf = &mtable->mleaf[i];			if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */				leaf->type = 0;				leaf->media = p[0] & 0x3f;				leaf->leafdata = p;				if ((p[2] & 0x61) == 0x01)	/* Bogus, but Znyx boards do it. */					mtable->has_mii = 1;				p += 4;			} else {				leaf->type = p[1];				if (p[1] == 0x05) {					mtable->has_reset = i;					leaf->media = p[2] & 0x0f;				} else if (p[1] & 1) {					mtable->has_mii = 1;					leaf->media = 11;				} else {					mtable->has_nonmii = 1;					leaf->media = p[2] & 0x0f;					if (p[1] == 2) {						if (leaf->media == 0) {							mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;							mtable->csr15val = get_unaligned((u16*)&p[5])<<16;						} else if (leaf->media == 0x40) {							u32 base15 = get_unaligned((u16*)&p[7]);							mtable->csr15dir =								(get_unaligned((u16*)&p[9])<<16) + base15;							mtable->csr15val =								(get_unaligned((u16*)&p[11])<<16) + base15;						}					}				}				leaf->leafdata = p + 2;				p += (p[0] & 0x3f) + 1;			}			if (tulip_debug > 1  &&  leaf->media == 11) {				unsigned char *bp = leaf->leafdata;				printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "					   "sequences %d/%d long, capabilities %2.2x %2.2x.\n",					   dev->name, bp[0], bp[1], bp[1 + bp[1]*2],					   bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);			}			printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "				   "by a %s (%d) block.\n",				   dev->name, i, medianame[leaf->media], leaf->media,				   block_name[leaf->type], leaf->type);		}	}}/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*//*  EEPROM_Ctrl bits. */#define EE_SHIFT_CLK	0x02	/* EEPROM shift clock. */#define EE_CS			0x01	/* EEPROM chip select. */#define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */#define EE_WRITE_0		0x01#define EE_WRITE_1		0x05#define EE_DATA_READ	0x08	/* EEPROM chip data out. */#define EE_ENB			(0x4800 | EE_CS)/* Delay between EEPROM clock transitions.   Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.   We add a bus turn-around to insure that this remains true. */#define eeprom_delay()	inl(ee_addr)/* The EEPROM commands include the alway-set leading bit. */#define EE_WRITE_CMD	(5 << addr_len)#define EE_READ_CMD		(6 << addr_len)#define EE_ERASE_CMD	(7 << addr_len)static int read_eeprom(long ioaddr, int location, int addr_len){	int i;	unsigned short retval = 0;	long ee_addr = ioaddr + CSR9;	int read_cmd = location | EE_READ_CMD;	outl(EE_ENB & ~EE_CS, ee_addr);	outl(EE_ENB, ee_addr);	/* Shift the read command bits out. */	for (i = 4 + addr_len; i >= 0; i--) {		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;		outl(EE_ENB | dataval, ee_addr);		eeprom_delay();		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);		eeprom_delay();	}	outl(EE_ENB, ee_addr);	for (i = 16; i > 0; i--) {		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);		eeprom_delay();		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);		outl(EE_ENB, ee_addr);		eeprom_delay();	}	/* Terminate the EEPROM access. */	outl(EE_ENB & ~EE_CS, ee_addr);	return retval;}/* 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

⌨️ 快捷键说明

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