Date: Mon, 18 Oct 1999 23:10:34 +0100 (MET) From: Gisle Vanem To: djgpp AT delorie DOT com Subject: far call Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Reply-To: djgpp AT delorie DOT com I'm porting some BIOS32 detection routine from Linux. Now I've hit the wall trying to call the BIOS32 service. I've used the procedure described in the FAQ and used in Allegro (dpmi.c and vesa.c), but it crashes at the "lcall (%%edi)" line. Someone please tell whats wrong with the __asm__ statement. ---------------------------- cut ----------------------------------- #include #include #include #include /* signatures: "_32_" + "$PCI" */ #define BIOS32_SIGNATURE (('_'<<0) + ('3'<<8) + ('2'<<16) + ('_'<<24)) #define PCI_SERVICE (('$'<<0) + ('P'<<8) + ('C'<<16) + ('I'<<24)) static __dpmi_paddr bios32_api; union bios32 { struct { unsigned long signature; /* "_32_" */ unsigned long entry; /* 32 bit physical address */ unsigned char revision; /* Revision level, 0 */ unsigned char length; /* Length in paragraphs should be 01 */ unsigned char checksum; /* All bytes must add up to zero */ unsigned char reserved[5]; /* Must be zero */ } fields; char chars[16]; }; /* Returns the entry point for the given service, NULL on error */ unsigned long bios32_service (unsigned long service) { unsigned char return_code; /* %al */ unsigned long address; /* %ebx */ unsigned long length; /* %ecx */ unsigned long entry; /* %edx */ __asm__ __volatile__ ( "lcall (%%edi)" : "=a" (return_code), "=b" (address), "=c" (length), "=d" (entry) : "0" (service), "1" (0), "D" (&bios32_api) ); switch (return_code) { case 0: return (address + entry); case 0x80: printf ("bios32_service(%08lX): not present\n", service); return (0); default: printf ("bios32_service(%08lX): returned %X\n", service, return_code); return (0); } } int pcibios_init (void) { unsigned char sum; unsigned long addr; int i, length; for (addr = 0xe0000; addr <= 0xffff0; addr += 16) { union bios32 check; unsigned short selector; dosmemget (addr, sizeof(check), &check); if (check.fields.signature != BIOS32_SIGNATURE) continue; length = check.fields.length * 16; if (!length) continue; sum = 0; for (i = 0; i < length; ++i) sum += check.chars[i]; if (sum != 0) continue; if (check.fields.revision != 0) { printf ("BIOS32: unsupported revision %d at %08lX\n", check.fields.revision, addr); continue; } printf ("BIOS32: BIOS32 Service Directory structure at %08lXh\n", addr); if (check.fields.entry >= 0x100000) { printf ("BIOS32: entry in high memory!\n"); return (0); } selector = __dpmi_allocate_ldt_descriptors (1); printf ("BIOS32: BIOS32 Service Directory entry at %08lXh\n", check.fields.entry); if (selector <= 0) { printf ("BIOS32: failed to create selector\n"); return (0); } __dpmi_set_segment_base_address (selector, addr); __dpmi_set_segment_limit (selector, 4096-1); bios32_api.offset32 = check.fields.entry; bios32_api.selector = selector; printf ("BIOS32: pmode entry at %04Xh:%08lXh\n", bios32_api.selector, bios32_api.offset32); return (1); } return (0); } int main (void) { if (pcibios_init()) bios32_service (PCI_SERVICE); return (0); } ---------------------------- cut ----------------------------------- Gisle V.