[syslinux:lwip] pxe: try to mimic the policy of iPXE with respect to interrupts

syslinux-bot for H. Peter Anvin hpa at zytor.com
Sun May 8 18:57:51 PDT 2011


Commit-ID:  96a59825a49f72f99ac92702d08bb4b91202bab7
Gitweb:     http://syslinux.zytor.com/commit/96a59825a49f72f99ac92702d08bb4b91202bab7
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Sun, 8 May 2011 18:29:18 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Sun, 8 May 2011 18:29:18 -0700

pxe: try to mimic the policy of iPXE with respect to interrupts

>From the iPXE checkin message:

[undi] Cope with devices that erroneously claim not to use
interrupts

Some PXE stacks advertise that interrupts are not supported, despite
requiring the use of interrupts.  Attempt to cope with such cards
without breaking others by always hooking the interrupt, and using the
"interrupts supported" flag only to decide whether or not to wait for
an interrupt before calling PXENV_UNDI_ISR_IN_PROCESS.

The possible combinations are therefore:

1. Card generates interrupts and claims to support interrupts

   iPXE will call PXENV_UNDI_ISR_IN_PROCESS only after an
   interrupt has been observed.  (This is required to avoid lockups in some
   PXE stacks, which spuriously sulk if called before an interrupt has
   been generated.)

   Such a card should work correctly.

2. Card does not generate interrupts and does not claim to support
   interrupts

   iPXE will call PXENV_UNDI_ISR_IN_PROCESS indiscriminately,
   matching the observed behaviour of at least one other PXE NBP
   (winBoot/i).

   Such a card should work correctly.

3. Card generates interrupts but claims not to support interrupts

   iPXE will call PXENV_UNDI_ISR_IN_PROCESS indiscriminately.  An
   interrupt will still result in a call to PXENV_UNDI_ISR_IN_START.

   Such a card may work correctly.

4. Card does not generate interrupts but claims to support
   interrupts

   Such a card will not work at all.

This attempts to match this policy.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 core/fs/pxe/isr.c            |   20 ++++++++++++++------
 core/fs/pxe/pxe.c            |   14 +++++++++++++-
 core/fs/pxe/pxe.h            |    3 +++
 core/lwip/src/netif/undiif.c |   24 +++++-------------------
 4 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/core/fs/pxe/isr.c b/core/fs/pxe/isr.c
index 1f79e78..bbad372 100644
--- a/core/fs/pxe/isr.c
+++ b/core/fs/pxe/isr.c
@@ -29,6 +29,10 @@ static bool install_irq_vector(uint8_t irq, void (*isr)(void), far_ptr_t *old)
     entry = (far_ptr_t *)(vec << 2);
     *old = *entry;
     entry->ptr = (uint32_t)isr;
+
+    printf("UNDI: IRQ %d(0x%02x): %04x:%04x -> %04x:%04x\n", irq, vec,
+	   old->seg, old->offs, entry->seg, entry->offs);
+
     return true;
 }
 
@@ -166,9 +170,13 @@ void pxe_init_isr(void)
  */
 void pxe_start_isr(void)
 {
-    if (pxe_irq_vector)
-	install_irq_vector(pxe_irq_vector, pxe_isr, &pxe_irq_chain);
-    else
+    pxe_irq_vector = pxe_undi_info.IntNumber; /* Used in 16-bit code */
+
+    if (pxe_undi_info.IntNumber)
+	install_irq_vector(pxe_undi_info.IntNumber, pxe_isr, &pxe_irq_chain);
+    
+    if (!pxe_undi_info.IntNumber ||
+	!(pxe_undi_iface.ServiceFlags & PXE_UNDI_IFACE_FLAG_IRQ))
 	poll_thread = start_thread("pxe poll", 4096, POLL_THREAD_PRIORITY,
 				   pxe_poll_thread, NULL);
 }
@@ -183,8 +191,8 @@ void pxe_cleanup_isr(void)
 
     memset(&undi_close, 0, sizeof(undi_close));
     pxe_call(PXENV_UNDI_CLOSE, &undi_close);
-    if (pxe_irq_vector)
-	uninstall_irq_vector(pxe_irq_vector, pxe_isr, &pxe_irq_chain);
-    else
+    if (pxe_undi_info.IntNumber)
+	uninstall_irq_vector(pxe_undi_info.IntNumber, pxe_isr, &pxe_irq_chain);
+    if (poll_thread)
 	kill_thread(poll_thread);
 }
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
index 267b32f..867404e 100644
--- a/core/fs/pxe/pxe.c
+++ b/core/fs/pxe/pxe.c
@@ -15,6 +15,9 @@
 #include "url.h"
 #include "tftp.h"
 
+__lowmem t_PXENV_UNDI_GET_INFORMATION pxe_undi_info;
+__lowmem t_PXENV_UNDI_GET_IFACE_INFO  pxe_undi_iface;
+
 static uint16_t real_base_mem;	   /* Amount of DOS memory after freeing */
 
 uint8_t MAC[MAC_MAX];		   /* Actual MAC address */
@@ -774,6 +777,15 @@ static int pxe_init(bool quiet)
 
     real_base_mem = max(code_seg, data_seg) >> 6; /* Convert to kilobytes */
 
+    /* Probe UNDI information */
+    pxe_call(PXENV_UNDI_GET_INFORMATION, &pxe_undi_info);
+    pxe_call(PXENV_UNDI_GET_IFACE_INFO,  &pxe_undi_iface);
+    
+    printf("UNDI: baseio %04x int %d MTU %d type %d \"%s\" flags 0x%x\n",
+	   pxe_undi_info.BaseIo, pxe_undi_info.IntNumber,
+	   pxe_undi_info.MaxTranUnit, pxe_undi_info.HwType,
+	   pxe_undi_iface.IfaceType, pxe_undi_iface.ServiceFlags);
+
     return 0;
 }
 
@@ -854,7 +866,7 @@ static void network_init(void)
     if (have_uuid)
 	sysappend_set_uuid(uuid);
     ip_init();
-    print_sysappend();
+    /* print_sysappend(); */
     http_bake_cookies();
 
     /*
diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h
index 47c233f..e07fc35 100644
--- a/core/fs/pxe/pxe.h
+++ b/core/fs/pxe/pxe.h
@@ -148,6 +148,9 @@ struct ip_info {
  */
 extern struct ip_info IPInfo;
 
+extern t_PXENV_UNDI_GET_INFORMATION pxe_undi_info;
+extern t_PXENV_UNDI_GET_IFACE_INFO  pxe_undi_iface;
+
 extern uint8_t MAC[];
 extern char BOOTIFStr[];
 extern uint8_t MAC_len;
diff --git a/core/lwip/src/netif/undiif.c b/core/lwip/src/netif/undiif.c
index 695abd6..6d75a58 100644
--- a/core/lwip/src/netif/undiif.c
+++ b/core/lwip/src/netif/undiif.c
@@ -223,22 +223,8 @@ static void print_arp_pbuf(struct netif *netif, struct pbuf *p)
 static void
 low_level_init(struct netif *netif)
 {
-  static __lowmem t_PXENV_UNDI_GET_INFORMATION undi_info;
-  static __lowmem t_PXENV_UNDI_GET_IFACE_INFO undi_iface;
   static __lowmem t_PXENV_UNDI_OPEN undi_open;
   int i;
-  /* struct undiif *undiif = netif->state; */
-
-  pxe_call(PXENV_UNDI_GET_INFORMATION, &undi_info);
-  pxe_call(PXENV_UNDI_GET_IFACE_INFO, &undi_iface);
-
-  printf("UNDI: baseio %04x int %d MTU %d type %d \"%s\" flags 0x%x\n",
-	 undi_info.BaseIo, undi_info.IntNumber, undi_info.MaxTranUnit,
-	 undi_info.HwType, undi_iface.IfaceType, undi_iface.ServiceFlags);
-
-  pxe_irq_vector = undi_info.IntNumber;
-  if (!(undi_iface.ServiceFlags & PXE_UNDI_IFACE_FLAG_IRQ))
-    pxe_irq_vector = 0;	/* Interrupts not supported */
 
   /* MAC_type and MAC_len should always match what is returned by
    * PXENV_UNDI_GET_INFORMATION.  At the moment the both seem to be
@@ -246,14 +232,14 @@ low_level_init(struct netif *netif)
    * somewhere so abort.
    */
   /* If we are in conflict abort */
-  if (MAC_type != undi_info.HwType) {
+  if (MAC_type != pxe_undi_info.HwType) {
     printf("HwType conflicit: %u != %u\n",
-	    MAC_type, undi_info.HwType);
+	    MAC_type, pxe_undi_info.HwType);
     kaboom();
   }
-  if (MAC_len != undi_info.HwAddrLen) {
+  if (MAC_len != pxe_undi_info.HwAddrLen) {
      printf("HwAddrLen conflict: %u != %u\n",
-	     MAC_len, undi_info.HwAddrLen);
+	     MAC_len, pxe_undi_info.HwAddrLen);
      kaboom();
   }
 
@@ -264,7 +250,7 @@ low_level_init(struct netif *netif)
   memcpy(netif->hwaddr, MAC, MAC_len);
 
   /* maximum transfer unit */
-  netif->mtu = undi_info.MaxTranUnit;
+  netif->mtu = pxe_undi_info.MaxTranUnit;
 
   dprintf("UNDI: hw address");
   for (i = 0; i < netif->hwaddr_len; i++)



More information about the Syslinux-commits mailing list