Hello GRUB people, now I have done the patch for the eepro100 stuff. Two points changed: (1) Added support for i82559ER (not tested here @home, as I have no 559ER card, but I tested the modified chip ID in the company on a real 559ER (2) Changed access to EEPROM to avoid failures on modern 82559 cards. This feature is tested on a moder i82559 card (Compaq/Intel NIC). Now the eepro100 driver is in sync with etherboot (release 4.7.18), but I used the "old" method of TIMEOUT (it is a tested merge of the two versions). Again, I think we should speek about the future strategy to be able to really copy in the current etherboot-drivers only. Here is the patch ... Cheers Christoph P. Christoph Plattner wrote: > > Ok, I did the patch already using the old TIMEOUT method (used before in > etherboot and GRUB) but the new routines handling the EEPROM access, > etc. > > At the moment my time is limited to do that in a "releasable" way, but I > will try in the next few days. > > Cheers > Christoph Plattner > > OKUJI Yoshinori wrote: > > > > From: OKUJI Yoshinori <[EMAIL PROTECTED]> > > Subject: Re: Patch for EtherExpressPro100 > > Date: Wed, 28 Feb 2001 18:44:00 +0900 > > > > > Ok, then I'll update only the eepro100 driver, as I have too little > > > time to update all the drivers. > > > > Ah, I reminded myself of that the most difficult part to update a > > newer version of Etherboot was eepro100, because it used the > > low-overhead timer routine. Because it is obvious that I cannot have > > time to investigate the solution for porting the routine to GRUB for > > now, I'd like to leave the work to one who is willing to do > > that. Sorry. > > > > (I guess that I won't have spare time to work on really new things, at > > least in two weeks.) > > > > Okuji > > > > _______________________________________________ > > Bug-grub mailing list > > [EMAIL PROTECTED] > > http://mail.gnu.org/mailman/listinfo/bug-grub > > -- > ------------------------------------------------------------------------- > private: [EMAIL PROTECTED] > company: [EMAIL PROTECTED] > > _______________________________________________ > Bug-grub mailing list > [EMAIL PROTECTED] > http://mail.gnu.org/mailman/listinfo/bug-grub -- ------------------------------------------------------------------------- private: [EMAIL PROTECTED] company: [EMAIL PROTECTED]
Index: ChangeLog =================================================================== RCS file: /cvs/grub/ChangeLog,v retrieving revision 1.405 diff -u -r1.405 ChangeLog --- ChangeLog 2001/02/28 11:19:39 1.405 +++ ChangeLog 2001/02/28 23:46:48 @@ -1,3 +1,19 @@ +2001-03-01 <[EMAIL PROTECTED]> + + * netboot/eepro100.c: merged all changes on base of etherboot- + 4.7.18 but with restrictions: + (1) changes in newlines and comments in untouched parts + are not changes (I want only change a minimum) + (2) I used the "olt" TIMEOUT method without timer control. + +2001-02-28 <[EMAIL PROTECTED]> + + * netboot/config.c (PCI_NIC): added 82559ER with eepro100_probe + added 82559ER to PCI network device list + + * netboot/pci.h (PCI_DEVICE_ID_INTEL_82559ER): added chip ID + for i82559ER version (subset chip of i82559). + 2001-02-28 OKUJI Yoshinori <[EMAIL PROTECTED]> From HASEGAWA Tomoki <[EMAIL PROTECTED]>: Index: netboot/config.c =================================================================== RCS file: /cvs/grub/netboot/config.c,v retrieving revision 1.10 diff -u -r1.10 config.c --- netboot/config.c 2001/02/02 12:21:18 1.10 +++ netboot/config.c 2001/02/28 23:46:49 @@ -91,6 +91,8 @@ #ifdef INCLUDE_EEPRO100 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557, "Intel EtherExpressPro100", 0, 0, 0}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER, + "Intel EtherExpressPro100", 0, 0, 0}, #endif #ifdef INCLUDE_EPIC100 { PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_EPIC100, @@ -190,6 +192,7 @@ # endif /* INCLUDE_3C595 */ # ifdef INCLUDE_EEPRO100 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557, eepro100_probe }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER, eepro100_probe }, # endif /* INCLUDE_EEPRO100 */ # ifdef INCLUDE_EPIC100 { PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_EPIC100, epic100_probe }, Index: netboot/eepro100.c =================================================================== RCS file: /cvs/grub/netboot/eepro100.c,v retrieving revision 1.3 diff -u -r1.3 eepro100.c --- netboot/eepro100.c 2000/04/22 01:17:09 1.3 +++ netboot/eepro100.c 2001/02/28 23:46:49 @@ -125,8 +125,7 @@ }; -static int read_eeprom(int location); -static void udelay (int val); +static int do_eeprom_cmd(int cmd, int cmd_len); void hd (void *where, int n); @@ -140,22 +139,20 @@ #define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ #define EE_CS 0x02 /* 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_WRITE_0 0x4802 +#define EE_WRITE_1 0x4806 #define EE_ENB (0x4800 | EE_CS) /* Delay between EEPROM clock transitions. This is a "nasty" timing loop, but PC compatible machines are defined to delay an ISA compatible period for the SLOW_DOWN_IO macro. */ -#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) \ +#define udelay(nanosec) do { int _i = 3; while (--_i > 0) \ { __SLOW_DOWN_IO; }} while (0) /* The EEPROM commands include the alway-set leading bit. */ -#define EE_WRITE_CMD (5 << 6) -#define EE_READ_CMD (6 << 6) -#define EE_ERASE_CMD (7 << 6) +#define EE_READ_CMD 6 /* The SCB accepts the following controls for the Tx and Rx units: */ #define CU_START 0x0010 @@ -291,9 +288,7 @@ #define TIME_OUT 1000000 -static unsigned short eeprom [0x40]; - /***********************************************************************/ /* Locally used functions */ /***********************************************************************/ @@ -343,46 +338,34 @@ } while (! (val & 0x10000000)); return val & 0xffff; } - -/* Support function: read_eeprom - * reads a value from the eeprom at a specified location. - * Arguments: location: address of the location to read from the eeprom. - * returns: value read from eeprom at location. - */ -static int read_eeprom(int location) -{ - int i; - unsigned short retval = 0; - int ee_addr = ioaddr + SCBeeprom; - int read_cmd = location | EE_READ_CMD; - - outw(EE_ENB & ~EE_CS, ee_addr); - outw(EE_ENB, ee_addr); - - /* Shift the read command bits out. */ - for (i = 10; i >= 0; i--) { - short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; - outw(EE_ENB | dataval, ee_addr); - eeprom_delay(100); - outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); - eeprom_delay(150); - outw(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */ - eeprom_delay(250); - } - outw(EE_ENB, ee_addr); - - for (i = 15; i >= 0; i--) { - outw(EE_ENB | EE_SHIFT_CLK, ee_addr); - eeprom_delay(100); - retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0); - outw(EE_ENB, ee_addr); - eeprom_delay(100); - } - - /* Terminate the EEPROM access. */ - outw(EE_ENB & ~EE_CS, ee_addr); - return retval; +/* The fixes for the code were kindly provided by Dragan Stancevic + <[EMAIL PROTECTED]> to strictly follow Intel specifications of EEPROM + access timing. + The publicly available sheet 64486302 (sec. 3.1) specifies 1us access + interval for serial EEPROM. However, it looks like that there is an + additional requirement dictating larger udelay's in the code below. + 2000/05/24 SAW */ +static int do_eeprom_cmd(int cmd, int cmd_len) +{ + unsigned retval = 0; + long ee_addr = ioaddr + SCBeeprom; + + outw(EE_ENB, ee_addr); udelay(2); + outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2); + + /* Shift the command bits out. */ + do { + short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; + outw(dataval, ee_addr); udelay(2); + outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2); + retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0); + } while (--cmd_len >= 0); + outw(EE_ENB, ee_addr); udelay(2); + + /* Terminate the EEPROM access. */ + outw(EE_ENB & ~EE_CS, ee_addr); + return retval; } @@ -500,11 +483,8 @@ static int eepro100_poll(struct nic *nic) { - int to; - - to = TIME_OUT; - while (!ACCESS(rxfd)status && --to) - /* Wait */; + if (!ACCESS(rxfd)status) + return 0; /* Ok. We got a packet. Now restart the reciever.... */ ACCESS(rxfd)status = 0; @@ -513,7 +493,6 @@ outw(INT_MASK | RX_START, ioaddr + SCBCmd); wait_for_cmd_done(ioaddr + SCBCmd); - if (to) { #ifdef DEBUG printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff); #endif @@ -522,13 +501,14 @@ #ifdef DEBUG hd (nic->packet, 0x30); #endif - return 1; - } else - return 0; + return 1; } static void eepro100_disable(struct nic *nic) { + /* See if this PartialReset solves the problem with interfering with + kernel operation after Etherboot hands over. - Ken 20001102 */ + outl(2, ioaddr + SCBPort); } /* exported function: eepro100_probe / eth_probe @@ -542,7 +522,8 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *p) { u16 sum = 0; - int i, j, to; + int i, to; + int read_cmd, ee_size; unsigned short value; int options; int promisc; @@ -551,21 +532,19 @@ unsigned short pci_command; unsigned short new_command; unsigned char pci_latency; + /* we cache only the first few words of the EEPROM data + be careful not to access beyond this array */ + unsigned short eeprom[16]; if (probeaddrs == 0 || probeaddrs[0] == 0) return 0; ioaddr = probeaddrs[0] & ~3; /* Mask the bit that says "this is an io addr" */ - /* Ok. Got one. Read the eeprom. */ - for (j = 0, i = 0; i < 0x40; i++) { - value = read_eeprom(i); - eeprom[i] = value; - sum += value; - } /* From Matt Hortman <[EMAIL PROTECTED]> */ - if (p->dev_id == PCI_DEVICE_ID_INTEL_82557 ){ + if ((p->dev_id == PCI_DEVICE_ID_INTEL_82557 ) || + (p->dev_id == PCI_DEVICE_ID_INTEL_82559ER) ) { /* * check to make sure the bios properly set the * 82557 (or 82558) to be bus master @@ -587,7 +566,23 @@ printf("\nPCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n", pci_latency); pcibios_write_config_byte(pci_bus, p->devfn, PCI_LATENCY_TIMER, 32); } - } + } + + 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; + } printf ("Ethernet addr: "); for (i=0;i<6;i++) { @@ -597,7 +592,7 @@ printf ("\n"); if (sum != 0xBABA) - printf("eepro100: Invalid EEPROM checksum %#4.4x, " + printf("eepro100: Invalid EEPROM checksum %#x, " "check settings before activating this device!\n", sum); outl(0, ioaddr + SCBPort); udelay (10); @@ -667,7 +662,6 @@ promisc = 0; - printf ("eeprom[6] = %x \n", eeprom[6]); if ( ((eeprom[6]>>8) & 0x3f) == DP83840 || ((eeprom[6]>>8) & 0x3f) == DP83840A) { int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422; @@ -713,17 +707,6 @@ nic->transmit = eepro100_transmit; nic->disable = eepro100_disable; return nic; -} - -static int loops_per_usec = 300; /* totally bogus value */ - -static void udelay (int val) -{ - int c; - - for(c=0; c<val*loops_per_usec; c++) { - /* Nothing */; - } } /*********************************************************************/ Index: netboot/pci.h =================================================================== RCS file: /cvs/grub/netboot/pci.h,v retrieving revision 1.7 diff -u -r1.7 pci.h --- netboot/pci.h 2000/07/29 19:22:54 1.7 +++ netboot/pci.h 2001/02/28 23:46:49 @@ -120,6 +120,7 @@ #define PCI_DEVICE_ID_3COM_3C905C_TXM 0x9200 #define PCI_VENDOR_ID_INTEL 0x8086 #define PCI_DEVICE_ID_INTEL_82557 0x1229 +#define PCI_DEVICE_ID_INTEL_82559ER 0x1209 #define PCI_VENDOR_ID_AMD 0x1022 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_VENDOR_ID_SMC_1211 0x1113