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

📄 eepro100.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
	txfd.count   = 0x02208000;	txfd.tx_desc_addr = virt_to_bus(&txfd.tx_buf_addr0);	txfd.tx_buf_addr0 = virt_to_bus (&hdr);	txfd.tx_buf_size0 = sizeof (hdr);	txfd.tx_buf_addr1 = virt_to_bus (p);	txfd.tx_buf_size1 = s;#ifdef	DEBUG	printf ("txfd: \n");	hd (&txfd, sizeof (txfd));#endif	outl(virt_to_bus(&txfd), ioaddr + SCBPointer);	outw(INT_MASK | CU_START, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	s1 = inw (ioaddr + SCBStatus);	load_timer2(10*TICKS_PER_MS);		/* timeout 10 ms for transmit */	while (!txfd.status && timer2_running())		/* Wait */;	s2 = inw (ioaddr + SCBStatus);#ifdef	DEBUG	printf ("s1 = %hX, s2 = %hX.\n", s1, s2);#endif}/* * Sometimes the receiver stops making progress.  This routine knows how to * get it going again, without losing packets or being otherwise nasty like * a chip reset would be.  Previously the driver had a whole sequence * of if RxSuspended, if it's no buffers do one thing, if it's no resources, * do another, etc.  But those things don't really matter.  Separate logic * in the ISR provides for allocating buffers--the other half of operation * is just making sure the receiver is active.  speedo_rx_soft_reset does that. * This problem with the old, more involved algorithm is shown up under * ping floods on the order of 60K packets/second on a 100Mbps fdx network. */static voidspeedo_rx_soft_reset(void){  wait_for_cmd_done(ioaddr + SCBCmd);	/*	* Put the hardware into a known state.	*/	outb(RX_ABORT, ioaddr + SCBCmd);	ACCESS(rxfd)rx_buf_addr = 0xffffffff;  wait_for_cmd_done(ioaddr + SCBCmd);	outb(RX_START, ioaddr + SCBCmd);}/* function: eepro100_poll / eth_poll * This recieves a packet from the network. * * Arguments: none * * returns:   1 if a packet was recieved. *            0 if no pacet was recieved. * side effects: *            returns the packet in the array nic->packet. *            returns the length of the packet in nic->packetlen. */static int eepro100_poll(struct nic *nic){  unsigned int status;  status = inw(ioaddr + SCBStatus);	if (!ACCESS(rxfd)status)		return 0;  /*   * The chip may have suspended reception for various reasons.   * Check for that, and re-prime it should this be the case.   */  switch ((status >> 2) & 0xf) {  case 0: /* Idle */    break;  case 1:	/* Suspended */  case 2:	/* No resources (RxFDs) */  case 9:	/* Suspended with no more RBDs */  case 10: /* No resources due to no RBDs */  case 12: /* Ready with no RBDs */    speedo_rx_soft_reset();    break;  case 3:  case 5:  case 6:  case 7:  case 8:  case 11:  case 13:  case 14:  case 15:    /* these are all reserved values */    break;  }	/* Ok. We got a packet. Now restart the reciever.... */	ACCESS(rxfd)status = 0;	ACCESS(rxfd)command = 0xc000;	outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);	outw(INT_MASK | RX_START, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);#ifdef	DEBUG	printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff);#endif	nic->packetlen =  ACCESS(rxfd)count & 0x3fff;	memcpy (nic->packet, ACCESS(rxfd)packet, nic->packetlen);#ifdef	DEBUG	hd (nic->packet, 0x30);#endif	return 1;}/* function: eepro100_disable * resets the card. This is used to allow Etherboot or Linux * to probe the card again from a "virginal" state.... * Arguments: none * * returns:   void. */static void eepro100_disable(struct dev *dev __unused){/* from eepro100_reset */	outl(0, ioaddr + SCBPort);/* from eepro100_disable */	/* See if this PartialReset solves the problem with interfering with	   kernel operation after Etherboot hands over. - Ken 20001102 */	outl(2, ioaddr + SCBPort);	/* The following is from the Intel e100 driver.	 * This hopefully solves the problem with hanging hard DOS images. */	/* wait for the reset to take effect */	udelay(20);	/* Mask off our interrupt line -- it is unmasked after reset */	{		u16 intr_status;		/* Disable interrupts on our PCI board by setting the mask bit */		outw(INT_MASK, ioaddr + SCBCmd);		intr_status = inw(ioaddr + SCBStatus);		/* ack and clear intrs */		outw(intr_status, ioaddr + SCBStatus);		inw(ioaddr + SCBStatus);	}}/* exported function: eepro100_probe / eth_probe * initializes a card * * side effects: *            leaves the ioaddress of the 82557 chip in the variable ioaddr. *            leaves the 82557 initialized, and ready to recieve packets. */static int eepro100_probe(struct dev *dev, struct pci_device *p){	struct nic *nic = (struct nic *)dev;	unsigned short sum = 0;	int i;	int read_cmd, ee_size;	int options;	int rx_mode;	/* we cache only the first few words of the EEPROM data	   be careful not to access beyond this array */	unsigned short eeprom[16];	if (p->ioaddr == 0)		return 0;	ioaddr = p->ioaddr & ~3; /* Mask the bit that says "this is an io addr" */	adjust_pci_device(p);	if ((do_eeprom_cmd(EE_READ_CMD << 24, 27) & 0xffe0000)		== 0xffe0000) {		ee_size = 0x100;		read_cmd = EE_READ_CMD << 24;	} else {		ee_size = 0x40;		read_cmd = EE_READ_CMD << 22;	}	for (i = 0, sum = 0; i < ee_size; i++) {		unsigned short value = do_eeprom_cmd(read_cmd | (i << 16), 27);		if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0])))			eeprom[i] = value;		sum += value;	}	for (i=0;i<ETH_ALEN;i++) {		nic->node_addr[i] =  (eeprom[i/2] >> (8*(i&1))) & 0xff;	}	printf ("Ethernet addr: %!\n", nic->node_addr);	if (sum != 0xBABA)		printf("eepro100: Invalid EEPROM checksum %#hX, "		       "check settings before activating this device!\n", sum);	outl(0, ioaddr + SCBPort);	udelay (10000);	whereami ("Got eeprom.");	/* Base = 0 */	outl(0, ioaddr + SCBPointer);	outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	whereami ("set rx base addr.");	outl(virt_to_bus(&lstats), ioaddr + SCBPointer);	outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	whereami ("set stats addr.");	/* INIT RX stuff. */	ACCESS(rxfd)status  = 0x0001;	ACCESS(rxfd)command = 0x0000;	ACCESS(rxfd)link    = virt_to_bus(&(ACCESS(rxfd)status));	ACCESS(rxfd)rx_buf_addr = virt_to_bus(&nic->packet);	ACCESS(rxfd)count   = 0;	ACCESS(rxfd)size    = 1528;	outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);	outw(INT_MASK | RX_START, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	whereami ("started RX process.");	/* Start the reciever.... */	ACCESS(rxfd)status = 0;	ACCESS(rxfd)command = 0xc000;	outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);	outw(INT_MASK | RX_START, ioaddr + SCBCmd);	/* INIT TX stuff. */	/* Base = 0 */	outl(0, ioaddr + SCBPointer);	outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	whereami ("set TX base addr.");	txfd.command      = (CmdIASetup);	txfd.status       = 0x0000;	txfd.link         = virt_to_bus (&confcmd);	{		char *t = (char *)&txfd.tx_desc_addr;				for (i=0;i<ETH_ALEN;i++)			t[i] = nic->node_addr[i];	}#ifdef	DEBUG	printf ("Setup_eaddr:\n");	hd (&txfd, 0x20);#endif	/*      options = 0x40; */ /* 10mbps half duplex... */	options = 0x00;            /* Autosense */#ifdef PROMISC	rx_mode = 3;#elif ALLMULTI	rx_mode = 1;#else	rx_mode = 0;#endif	if (   ((eeprom[6]>>8) & 0x3f) == DP83840	       || ((eeprom[6]>>8) & 0x3f) == DP83840A) {		int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422;		if (congenb)			mdi_reg23 |= 0x0100;		printf("  DP83840 specific setup, setting register 23 to %hX.\n",		       mdi_reg23);		mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23);	}	whereami ("Done DP8340 special setup.");	if (options != 0) {		mdio_write(eeprom[6] & 0x1f, 0,			   ((options & 0x20) ? 0x2000 : 0) |    /* 100mbps? */			   ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */		whereami ("set mdio_register.");	}	confcmd.command  = CmdSuspend | CmdConfigure;	confcmd.status   = 0x0000;	confcmd.link     = virt_to_bus (&txfd);	confcmd.data[1]  = (txfifo << 4) | rxfifo;	confcmd.data[4]  = rxdmacount;	confcmd.data[5]  = txdmacount + 0x80;	confcmd.data[15] = (rx_mode & 2) ? 0x49: 0x48;	confcmd.data[19] = (options & 0x10) ? 0xC0 : 0x80;	confcmd.data[21] = (rx_mode & 1) ? 0x0D: 0x05;	outl(virt_to_bus(&txfd), ioaddr + SCBPointer);	outw(INT_MASK | CU_START, ioaddr + SCBCmd);	wait_for_cmd_done(ioaddr + SCBCmd);	whereami ("started TX thingy (config, iasetup).");	load_timer2(10*TICKS_PER_MS);	while (!txfd.status && timer2_running())		/* Wait */;	/* Read the status register once to disgard stale data */	mdio_read(eeprom[6] & 0x1f, 1);	/* Check to see if the network cable is plugged in.	 * This allows for faster failure if there is nothing	 * we can do.	 */	if (!(mdio_read(eeprom[6] & 0x1f, 1) & (1 << 2))) {		printf("Valid link not established\n");		eepro100_disable(dev);		return 0;	}	dev->disable  = eepro100_disable;	nic->poll     = eepro100_poll;	nic->transmit = eepro100_transmit;	return 1;}/*********************************************************************/#ifdef	DEBUG/* Hexdump a number of bytes from memory... */void hd (void *where, int n){	int i;	while (n > 0) {		printf ("%X ", where);		for (i=0;i < ( (n>16)?16:n);i++)			printf (" %hhX", ((char *)where)[i]);		printf ("\n");		n -= 16;		where += 16;	}}#endifstatic struct pci_id eepro100_nics[] = {PCI_ROM(0x8086, 0x1029, "id1029",        "Intel EtherExpressPro100 ID1029"),PCI_ROM(0x8086, 0x1030, "id1030",        "Intel EtherExpressPro100 ID1030"),PCI_ROM(0x8086, 0x1031, "82801cam",      "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection"),PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection"),PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection"),PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),PCI_ROM(0x8086, 0x1038, "id1038",        "Intel PRO/100 VM Network Connection"),PCI_ROM(0x8086, 0x1039, "82562et",       "Intel PRO100 VE 82562ET"),PCI_ROM(0x8086, 0x103a, "id103a",        "Intel Corporation 82559 InBusiness 10/100"),PCI_ROM(0x8086, 0x103b, "82562etb",      "Intel PRO100 VE 82562ETB"),PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection"),PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection"),PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection"),PCI_ROM(0x8086, 0x1059, "82551qm",       "Intel PRO/100 M Mobile Connection"),PCI_ROM(0x8086, 0x1209, "82559er",       "Intel EtherExpressPro100 82559ER"),PCI_ROM(0x8086, 0x1227, "82865",         "Intel 82865 EtherExpress PRO/100A"),PCI_ROM(0x8086, 0x1228, "82556",         "Intel 82556 EtherExpress PRO/100 Smart"),PCI_ROM(0x8086, 0x1229, "eepro100",      "Intel EtherExpressPro100"),PCI_ROM(0x8086, 0x2449, "82562em",       "Intel EtherExpressPro100 82562EM"),PCI_ROM(0x8086, 0x2459, "82562-1",       "Intel 82562 based Fast Ethernet Connection"),PCI_ROM(0x8086, 0x245d, "82562-2",       "Intel 82562 based Fast Ethernet Connection"),PCI_ROM(0x8086, 0x1050, "82562ez",       "Intel 82562EZ Network Connection"),PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server"),PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server"),};/* Cards with device ids 0x1030 to 0x103F, 0x2449, 0x2459 or 0x245D might need * a workaround for hardware bug on 10 mbit half duplex (see linux driver eepro100.c) * 2003/03/17 gbaum */static struct pci_driver eepro100_driver __pci_driver = {	.type      = NIC_DRIVER,	.name      = "EEPRO100",	.probe     = eepro100_probe,	.ids       = eepro100_nics,	.id_count  = sizeof(eepro100_nics)/sizeof(eepro100_nics[0]),	.class     = 0};

⌨️ 快捷键说明

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