Message-ID: <005f01bf1a10$4d4d6560$293f8589@gv015029.bgo.nera.no> From: "Gisle Vanem" To: Subject: Re: far call Date: Tue, 19 Oct 1999 10:59:26 +0200 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 4.72.3110.5 X-MIMEOLE: Produced By Microsoft MimeOLE V4.72.3110.3 Reply-To: djgpp AT delorie DOT com Eli Zaretskii said: >> bios32_api.offset32 = check.fields.entry; >> bios32_api.selector = selector; > >You have defined a special selector for the memory region, but didn't >adjust the offset accordingly. You need to subtract addr from >check.fields.entry, to make it a segment-relative offset suitable to >use with your selector. Otherwise, bios32_api.offset32 is way above >the 4K limit you've set up for bios32_api.selector. Thanks for the tips, but it's still crashing. Here the symify output and revised code: BIOS32: BIOS32 Service Directory structure at 000FDB60h BIOS32: BIOS32 Service Directory entry at 000FDB70h BIOS32: pmode entry at 01D7h:00000010h Exiting due to signal SIGSEGV General Protection Fault at eip=00001dcc, error=01d4 eax=49435024 ebx=00000000 ecx=00000000 edx=00000035 esi=00000054 edi=49435024 ebp=0008f6e4 esp=0008f6d4 program=D:\NET\TCPDUMP\PCAP\PM_DRVR\B32.EXE cs: sel=01b7 base=022a0000 limit=0009ffff ds: sel=01bf base=022a0000 limit=0009ffff es: sel=01bf base=022a0000 limit=0009ffff fs: sel=0187 base=0001c320 limit=0000ffff gs: sel=01c7 base=00000000 limit=0010ffff ss: sel=01bf base=022a0000 limit=0009ffff App stack: [0008f710..0000f710] Exceptn stack: [0000f5f8..0000d6b8] Call frame traceback EIPs: 0x00001dcc _bios32_service+16, line 44 of b32.c 0x00002046 _main+22, line 132 of b32.c 0x00002fde ___crt1_startup+174 ------------------------------- 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; #pragma pack(1) /* turn on packing, I'm sure this is equal to __attribute__((packed)) */ 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]; }; #pragma pack() /* 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 */ #if 0 __asm__ __volatile__ ( "lcall (%%edi)" : "=a" (return_code), "=b" (address), "=c" (length), "=d" (entry) : "0" (service), "1" (0), "D" (&bios32_api) ); #else __asm__ __volatile__ ( "lcall _bios32_api" /* line 44, crashes here */ : "=a" (return_code), "=b" (address), "=c" (length), "=d" (entry) : "0" (service), "1" (0) ); #endif 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 - addr; 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 --------------------------------------------- Generating asm-output, the "lcall" looks okay. Unless 'bios32_api' is wrongly aligned. I didn't see that packs '__dpmi_paddr' in any way. Maybe I need to modify the selector for 'execute' ? (don't think so) Gisle V.