[syslinux] ethersel.c32 issues

Jesse Sipprell jesses at sportsline.com
Wed Apr 20 23:14:20 PDT 2005


My apologies if this is no longer an issue or has been resolved in some other
manner.  It was quicker for me to simply do some quick hacking than to
research more fully.

Regarding this message from Feb 2005:

>>> Did you make progress with ethersel.c32?
>>> Is there anything I can do to help?
>>>
>> 
>> I've been out of town.  If you could sprinkle some printf's and see why 
>> it doesn't detect the device that would be interesting.
>
>I have added several printf's to ethersel.c including one after the line
>did = pci_readl(a);
>
>I have added
>printf("found: DID %08x\n", did);
>
>and I get a lot of lines like
>found: DID ffffffff
>
>My conclusion is that it does not detect any PCI devices because 
>something is wrong with the pciscan function. Maybe ethersel is not 
>scanning the right addresses.
>
>> Worst case, the BIOS doesn't initialize a bridge that the NIC is behind. 
>>  That would be very messy to fix.
>
>I am sure there is a way to detect the PCI IDs because etherboot is able 
>to do it. Maybe we could use some of its code?

Procedurally, the bios must be "asked" before it is acceptable to probe
for configuration data.  Obviously, this is not a technical requirement
in many cases, however ...

The following patch will allow ethersel to correctly probe in cases where
the bios is not activating a bridge or some other issue (strict-adherence)
prevents the pci configuration information from being available.  This will
also allow ethersel to work under vmware.  YMMV.

--- ethersel.c	2005-04-21 01:55:22.903371800 -0400
+++ ethersel.c.biosfix	2005-04-21 01:55:59.905746584 -0400
@@ -43,6 +43,8 @@
 # define dprintf(...) ((void)0)
 #endif
 
+extern enum pci_config_type __pci_cfg_type;
+
 struct match {
   struct match *next;
   uint32_t did;
@@ -64,6 +66,35 @@
   return MK_PTR(r.es, r.ebx.w[0]);
 }
 
+static int
+get_bios(void)
+{
+  static com32sys_t r;
+  int lastbus = -1;
+  uint8_t bioscfg;
+
+  r.eax.w[0] = 0xb101;
+  __intcall(0x1a, &r, &r);
+
+  if (r.eax.b[1] == 0x00) {
+    lastbus = r.ecx.b[0];
+
+    if(__pci_cfg_type == PCI_CFG_AUTO) {
+      bioscfg = r.eax.b[0] & 0x03;
+      if (bioscfg & 0x01) {
+        dprintf("detected PCI bios cfg mechanism 1\n");
+        __pci_cfg_type = PCI_CFG_TYPE1;
+      } else if (bioscfg & 0x02) {
+        dprintf("detected PCI bios cfg mechanism 2\n");
+        __pci_cfg_type = PCI_CFG_TYPE2;
+      } else
+        dprintf("unable to determine PCI bios cfg mechanism.\n");
+    }
+  }
+
+  return lastbus;
+}
+
 static char *
 skipspace(char *p)
 {
@@ -205,13 +236,23 @@
 static struct match *
 pciscan(struct match *list)
 {
-  unsigned int bus, dev, func, maxfunc;
+  unsigned int bus, dev, func, maxfunc, maxbus;
   uint32_t did, sid;
   uint8_t hdrtype, rid;
   pciaddr_t a;
   struct match *m;
+  int bios_maxbus;
+
+
+  if ((bios_maxbus = get_bios()) < 0) {
+    dprintf("PCI bios not detected.\n");
+    maxbus = 0xff;
+  } else {
+    maxbus = bios_maxbus + 1;
+    dprintf("PCI bios reports %u buses, scanning...\n", maxbus);
+  }
 
-  for ( bus = 0 ; bus <= 0xff ; bus++ ) {
+  for ( bus = 0 ; bus < maxbus; bus++ ) {
     for ( dev = 0 ; dev <= 0x1f ; dev++ ) {
       maxfunc = 0;
       for ( func = 0 ; func <= maxfunc ; func++ ) {




More information about the Syslinux mailing list