[librm] Use libflat to enable A20 line on each real-to-protected transition
[gpxe.git] / src / arch / i386 / drivers / net / undiload.c
index 1d4e88d..8271b50 100644 (file)
@@ -58,6 +58,12 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
        uint16_t exit;
        int rc;
 
+       /* Only one UNDI instance may be loaded at any given time */
+       if ( undi_loader_entry.segment ) {
+               DBG ( "UNDI %p cannot load multiple instances\n", undi );
+               return -EBUSY;
+       }
+
        /* Set up START_UNDI parameters */
        memset ( &undi_loader, 0, sizeof ( undi_loader ) );
        undi_loader.AX = undi->pci_busdevfn;
@@ -98,17 +104,10 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) {
                               : "a" ( __from_data16 ( &undi_loader ) )
                               : "ebx", "ecx", "edx", "esi", "edi", "ebp" );
 
-       /* UNDI API calls may rudely change the status of A20 and not
-        * bother to restore it afterwards.  Intel is known to be
-        * guilty of this.
-        *
-        * Note that we will return to this point even if A20 gets
-        * screwed up by the UNDI driver, because Etherboot always
-        * resides in an even megabyte of RAM.
-        */     
-       gateA20_set();
-
        if ( exit != PXENV_EXIT_SUCCESS ) {
+               /* Clear entry point */
+               memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) );
+
                rc = -undi_loader.Status;
                if ( rc == 0 ) /* Paranoia */
                        rc = -EIO;
@@ -151,6 +150,9 @@ int undi_unload ( struct undi_device *undi ) {
 
        DBGC ( undi, "UNDI %p unloading\n", undi );
 
+       /* Clear entry point */
+       memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) );
+
        /* Erase signatures */
        if ( undi->pxenv.segment )
                put_real ( dead, undi->pxenv.segment, undi->pxenv.offset );