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

📄 pcnet32.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		lp->a.write_bcr(ioaddr, 9, val);	}	/* set/reset GPSI bit in test register */	val = lp->a.read_csr(ioaddr, 124) & ~0x10;	if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)		val |= 0x10;	lp->a.write_csr(ioaddr, 124, val);	if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {		val = lp->a.read_bcr(ioaddr, 32) & ~0x38;	/* disable Auto Negotiation, set 10Mpbs, HD */		if (lp->options & PCNET32_PORT_FD)			val |= 0x10;		if (lp->options & PCNET32_PORT_100)			val |= 0x08;		lp->a.write_bcr(ioaddr, 32, val);	} else {		if (lp->options & PCNET32_PORT_ASEL) {	/* enable auto negotiate, setup, disable fd */			val = lp->a.read_bcr(ioaddr, 32) & ~0x98;			val |= 0x20;			lp->a.write_bcr(ioaddr, 32, val);		}	}#ifdef DO_DXSUFLO	if (lp->dxsuflo) {	/* Disable transmit stop on underflow */		val = lp->a.read_csr(ioaddr, 3);		val |= 0x40;		lp->a.write_csr(ioaddr, 3, val);	}#endif	if (lp->ltint) {	/* Enable TxDone-intr inhibitor */		val = lp->a.read_csr(ioaddr, 5);		val |= (1 << 14);		lp->a.write_csr(ioaddr, 5, val);	}	lp->init_block.mode =	    le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);	lp->init_block.filter[0] = 0xffffffff;	lp->init_block.filter[1] = 0xffffffff;	pcnet32_init_ring(nic);	/* Re-initialize the PCNET32, and start it when done. */	lp->a.write_csr(ioaddr, 1,			(virt_to_bus(&lp->init_block)) & 0xffff);	lp->a.write_csr(ioaddr, 2, (virt_to_bus(&lp->init_block)) >> 16);	lp->a.write_csr(ioaddr, 4, 0x0915);	lp->a.write_csr(ioaddr, 0, 0x0001);	i = 0;	while (i++ < 100)		if (lp->a.read_csr(ioaddr, 0) & 0x0100)			break;	/* 	 * We used to clear the InitDone bit, 0x0100, here but Mark Stockton	 * reports that doing so triggers a bug in the '974.	 */	lp->a.write_csr(ioaddr, 0, 0x0042);	printf("pcnet32 open, csr0 %hX.\n", lp->a.read_csr(ioaddr, 0));}/**************************************************************************POLL - Wait for a frame***************************************************************************/static int pcnet32_poll(struct nic *nic __unused){	/* return true if there's an ethernet packet ready to read */	/* nic->packet should contain data on return */	/* nic->packetlen should contain length of data */	int status;	int entry;	entry = lp->cur_rx & RX_RING_MOD_MASK;	status = ((short) le16_to_cpu(rx_ring[entry].status) >> 8);	if (status < 0)		return 0;	if (status == 0x03) {		nic->packetlen =		    (le32_to_cpu(rx_ring[entry].msg_length) & 0xfff) - 4;		memcpy(nic->packet, &rxb[entry], nic->packetlen);		/* Andrew Boyd of QNX reports that some revs of the 79C765		 * clear the buffer length */		rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ);		rx_ring[entry].status |= le16_to_cpu(0x8000);	/* prime for next receive */		/* Switch to the next Rx ring buffer */		lp->cur_rx++;	} else {		return 0;	}	return 1;}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void pcnet32_transmit(struct nic *nic __unused, const char *d,	/* Destination */			     unsigned int t,	/* Type */			     unsigned int s,	/* size */			     const char *p){				/* Packet */	/* send the packet to destination */	unsigned long time;	u8 *ptxb;	u16 nstype;	u16 status;	int entry = 0;		/*lp->cur_tx & TX_RING_MOD_MASK; */	status = 0x8300;	/* point to the current txb incase multiple tx_rings are used */	ptxb = txb + (lp->cur_tx * PKT_BUF_SZ);	/* copy the packet to ring buffer */	memcpy(ptxb, d, ETH_ALEN);	/* dst */	memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);	/* src */	nstype = htons((u16) t);	/* type */	memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);	/* type */	memcpy(ptxb + ETH_HLEN, p, s);	s += ETH_HLEN;	while (s < ETH_ZLEN)	/* pad to min length */		ptxb[s++] = '\0';	tx_ring[entry].length = le16_to_cpu(-s);	tx_ring[entry].misc = 0x00000000;	tx_ring[entry].base = (u32) virt_to_le32desc(ptxb);	/* we set the top byte as the very last thing */	tx_ring[entry].status = le16_to_cpu(status);	/* Trigger an immediate send poll */	lp->a.write_csr(ioaddr, 0, 0x0048);	/* wait for transmit complete */	lp->cur_tx = 0;		/* (lp->cur_tx + 1); */	time = currticks() + TICKS_PER_SEC;	/* wait one second */	while (currticks() < time &&	       ((short) le16_to_cpu(tx_ring[entry].status) < 0));	if ((short) le16_to_cpu(tx_ring[entry].status) < 0)		printf("PCNET32 timed out on transmit\n");	/* Stop pointing at the current txb	 * otherwise the card continues to send the packet */	tx_ring[entry].base = 0;}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/#ifdef EB50static void pcnet32_disable(struct nic *nic __unused)#elsestatic void pcnet32_disable(struct dev *dev __unused)#endif{	/* Stop the PCNET32 here -- it ocassionally polls memory if we don't */	lp->a.write_csr(ioaddr, 0, 0x0004);	/*	 * Switch back to 16-bit mode to avoid problesm with dumb 	 * DOS packet driver after a warm reboot	 */	lp->a.write_bcr(ioaddr, 20, 4);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outsideYou should omit the last argument struct pci_device * for a non-PCI NIC***************************************************************************/#ifdef EB50struct nic *pcnet32_probe(struct nic *nic, unsigned short *io_addr, struct pci_device *pci){#elsestatic int pcnet32_probe(struct dev *dev, struct pci_device *pci){	struct nic *nic = (struct nic *) dev;#endif	int i, media;	int fdx, mii, fset, dxsuflo, ltint;	int chip_version;	char *chipname;	/* struct net_device *dev; */	struct pcnet32_access *a = NULL;	u8 promaddr[6];	int shared = 1;	if (pci->ioaddr == 0)		return 0;	/* BASE is used throughout to address the card */	ioaddr = pci->ioaddr;	printf("\n");		printf("pcnet32.c: %s, %s\n", drv_version, drv_date);	printf("%s: Probing for Vendor=%hX   Device=%hX\n",	       pci->name, pci->vendor, pci->dev_id);	/* reset the chip */	pcnet32_wio_reset(ioaddr);	/* NOTE: 16-bit check is first, otherwise some older PCnet chips fail */	if (pcnet32_wio_read_csr(ioaddr, 0) == 4	    && pcnet32_wio_check(ioaddr)) {		a = &pcnet32_wio;	} else {		pcnet32_dwio_reset(ioaddr);		if (pcnet32_dwio_read_csr(ioaddr, 0) == 4		    && pcnet32_dwio_check(ioaddr)) {			a = &pcnet32_dwio;		} else			/* return -ENODEV; */			return 0;	}	chip_version =	    a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr, 89) << 16);	printf("PCnet chip version is %#x.\n", chip_version);	if ((chip_version & 0xfff) != 0x003)		/*return -ENODEV; */		return 0;	/* initialize variables */	fdx = mii = fset = dxsuflo = ltint = 0;	chip_version = (chip_version >> 12) & 0xffff;	switch (chip_version) {	case 0x2420:		chipname = "PCnet/PCI 79C970";	/* PCI */		break;	case 0x2430:		if (shared)			chipname = "PCnet/PCI 79C970";	/* 970 gives the wrong chip id back */		else			chipname = "PCnet/32 79C965";	/* 486/VL bus */		break;	case 0x2621:		chipname = "PCnet/PCI II 79C970A";	/* PCI */		fdx = 1;		break;	case 0x2623:		chipname = "PCnet/FAST 79C971";	/* PCI */		fdx = 1;		mii = 1;		fset = 1;		ltint = 1;		break;	case 0x2624:		chipname = "PCnet/FAST+ 79C972";	/* PCI */		fdx = 1;		mii = 1;		fset = 1;		break;	case 0x2625:		chipname = "PCnet/FAST III 79C973";	/* PCI */		fdx = 1;		mii = 1;		break;	case 0x2626:		chipname = "PCnet/Home 79C978";	/* PCI */		fdx = 1;		/* 		 * This is based on specs published at www.amd.com.  This section		 * assumes that a card with a 79C978 wants to go into 1Mb HomePNA		 * mode.  The 79C978 can also go into standard ethernet, and there		 * probably should be some sort of module option to select the		 * mode by which the card should operate		 */		/* switch to home wiring mode */		media = a->read_bcr(ioaddr, 49);		printf("media reset to %#x.\n", media);		a->write_bcr(ioaddr, 49, media);		break;	case 0x2627:		chipname = "PCnet/FAST III 79C975";	/* PCI */		fdx = 1;		mii = 1;		break;	default:		printf("PCnet version %#x, no PCnet32 chip.\n",		       chip_version);		/* return -ENODEV; */		return 0;	}	/*	 *  On selected chips turn on the BCR18:NOUFLO bit. This stops transmit	 *  starting until the packet is loaded. Strike one for reliability, lose	 *  one for latency - although on PCI this isnt a big loss. Older chips 	 *  have FIFO's smaller than a packet, so you can't do this.	 */	if (fset) {		a->write_bcr(ioaddr, 18,			     (a->read_bcr(ioaddr, 18) | 0x0800));		a->write_csr(ioaddr, 80,			     (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00);		dxsuflo = 1;		ltint = 1;	}	printf("%s at %hX,", chipname, ioaddr);	/* read PROM address */	for (i = 0; i < 6; i++)		promaddr[i] = inb(ioaddr + i);	/* Update the nic structure with the MAC Address */	for (i = 0; i < ETH_ALEN; i++) {		nic->node_addr[i] = promaddr[i];	}	/* Print out some hardware info */	printf("%s: %! at ioaddr %hX\n", pci->name, nic->node_addr,	       ioaddr);	/* I really must find out what this does */	adjust_pci_device(pci);	/* point to private storage */	lp = &lpx;	if (((chip_version + 1) & 0xfffe) == 0x2624) {	/* Version 0x2623 or 0x2624 */		i = a->read_csr(ioaddr, 80) & 0x0C00;	/* Check tx_start_pt */		printf("    tx_start_pt(0x%hX):", i);		switch (i >> 10) {		case 0:			printf("  20 bytes,");			break;		case 1:			printf("  64 bytes,");			break;		case 2:			printf(" 128 bytes,");			break;		case 3:			printf("~220 bytes,");			break;		}		i = a->read_bcr(ioaddr, 18);	/* Check Burst/Bus control */		printf(" BCR18(%hX):", i & 0xffff);		if (i & (1 << 5))			printf("BurstWrEn ");		if (i & (1 << 6))			printf("BurstRdEn ");		if (i & (1 << 7))			printf("DWordIO ");		if (i & (1 << 11))			printf("NoUFlow ");		i = a->read_bcr(ioaddr, 25);		printf("    SRAMSIZE=0x%hX,", i << 8);		i = a->read_bcr(ioaddr, 26);		printf(" SRAM_BND=0x%hX,", i << 8);		i = a->read_bcr(ioaddr, 27);		if (i & (1 << 14))			printf("LowLatRx");	}	lp = &lpx;	lp->name = chipname;	lp->shared_irq = shared;	lp->full_duplex = fdx;	lp->dxsuflo = dxsuflo;	lp->ltint = ltint;	lp->mii = mii;	if ((cards_found >= MAX_UNITS)	    || (options[cards_found] > sizeof(options_mapping)))		lp->options = PCNET32_PORT_ASEL;	else		lp->options = options_mapping[options[cards_found]];	if (fdx && !(lp->options & PCNET32_PORT_ASEL) &&	    ((cards_found >= MAX_UNITS) || full_duplex[cards_found]))		lp->options |= PCNET32_PORT_FD;	if (!a) {		printf("No access methods\n");		return 0;	}	lp->a = *a;	/* detect special T1/E1 WAN card by checking for MAC address */	if (nic->node_addr[0] == 0x00 && nic->node_addr[1] == 0xe0	    && nic->node_addr[2] == 0x75)		lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;	lp->init_block.mode = le16_to_cpu(0x0003); 	/* Disable Rx and Tx. */	lp->init_block.tlen_rlen =	    le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);	for (i = 0; i < 6; i++)		lp->init_block.phys_addr[i] = nic->node_addr[i];	lp->init_block.filter[0] = 0xffffffff;	lp->init_block.filter[1] = 0xffffffff;	lp->init_block.rx_ring = virt_to_bus(&rx_ring);	lp->init_block.tx_ring = virt_to_bus(&tx_ring);	/* switch pcnet32 to 32bit mode */	a->write_bcr(ioaddr, 20, 2);	a->write_csr(ioaddr, 1, (virt_to_bus(&lp->init_block)) & 0xffff);	a->write_csr(ioaddr, 2, (virt_to_bus(&lp->init_block)) >> 16);	/* 	 * To auto-IRQ we enable the initialization-done and DMA error	 * interrupts. For ISA boards we get a DMA error, but VLB and PCI	 * boards will work.	 */	/* Trigger an initialization just for the interrupt. */	a->write_csr(ioaddr, 0, 0x41);	mdelay(1);	cards_found++;		/* point to NIC specific routines */	pcnet32_reset(nic);#ifdef EB50	nic->poll = pcnet32_poll;	nic->transmit = pcnet32_transmit;	nic->disable = pcnet32_disable;	return nic;#else	nic->poll = pcnet32_poll;	nic->transmit = pcnet32_transmit;	dev->disable = pcnet32_disable;	return 1;#endif}#ifndef EB50static struct pci_id pcnet32_nics[] = {	PCI_ROM(0x1022, 0x2000, "lancepci", "AMD Lance/PCI"),	PCI_ROM(0x1022, 0x2625, "pcnetfastiii", "AMD Lance/PCI PCNet/32"),	PCI_ROM(0x1022, 0x2001, "amdhomepna", "AMD Lance/HomePNA"),};static struct pci_driver pcnet32_driver __pci_driver = {	.type = NIC_DRIVER,	.name = "PCNET32/PCI",	.probe = pcnet32_probe,	.ids = pcnet32_nics,	.id_count = sizeof(pcnet32_nics) / sizeof(pcnet32_nics[0]),	.class = 0,};#endif

⌨️ 快捷键说明

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