/*++ Copyright (C) 1996 Motorola Inc. Module Name: pcibios.c Abstract: Emulate PCI BIOS functions. Note that the HAL bus functions (HalGetBusData, etc.) are not available at this phase of initialization, all of the work has to be done here. Author: Scott Geranen Environment: Kernel mode Revision History: --*/ #include "halp.h" #include "pci.h" #include "pcip.h" #include "pxmemctl.h" #include "pxpcisup.h" #include "emulate.h" #include "pcibios.h" UCHAR SBReadConfigByte( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register ); USHORT SBReadConfigWord( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register ); ULONG SBReadConfigDword( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register ); VOID SBWriteConfigByte( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register, IN UCHAR Data ); VOID SBWriteConfigWord( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register, IN USHORT Data ); VOID SBWriteConfigDword( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register, IN ULONG Data ); // // Last PCI bus in the system. // extern UCHAR HalpLastPciBus; // // Ports to be used to access config space. // #define CONFIG_ADDR_PORT (0x00000CF8) #define CONFIG_DATA_PORT (0x00000CFC) ULONG x86BiosReadIoSpace ( IN XM_OPERATION_DATATYPE DataType, IN USHORT PortNumber ); VOID x86BiosWriteIoSpace ( IN XM_OPERATION_DATATYPE DataType, IN USHORT PortNumber, IN ULONG Value ); BOOLEAN HalpEmulatePciBios( IN OUT PRXM_CONTEXT P ) /*++ Routine Description: This function emulates the PCI BIOS Specification, revision 2.1. The specification is available from the PCI Special Interest Group. This function assumes that it is being called during phase 0 initialization. The PCI bus functions are not available at this point, e.g. HalGetBusData. Arguments: P - Supplies a pointer to an emulator context structure. Return Value: TRUE (PCI BIOS was emulated) --*/ { #if DBG VOID TestPciBios(int flag); TestPciBios(0); #endif switch (P->Gpr[EAX].Xl) { case PCIBIOS_PCI_BIOS_PRESENT: // Installation Check KdPrint(("PCI_BIOS_PRESENT\n")); P->Gpr[EDX].Exx = 0x20494350; // "PCI " P->Gpr[EAX].Xh = 0x00; // 00 == BIOS present P->Gpr[EAX].Xl = 0x11; // PCI Hardware Characteristics (mech #1) P->Gpr[EBX].Xh = 0x02; // PCI Interface Level Major Version P->Gpr[EBX].Xl = 0x10; // PCI Interface Level (BCD) P->Gpr[ECX].Xl = HalpLastPciBus; // Last PCI bus number P->Eflags.CF = 0; // reset == PCI BIOS present break; case PCIBIOS_FIND_PCI_DEVICE: { USHORT DevID = P->Gpr[ECX].Xx; USHORT VenID = P->Gpr[EDX].Xx; USHORT DevIndex = P->Gpr[ESI].Xx; UCHAR Bus, Device, Function, Header, NumFunctions; BOOLEAN Found = FALSE; KdPrint(("Looking for instance %d of 0x%X, 0x%X\n", DevIndex, DevID, VenID)); if (VenID == 0xFFFF) { P->Gpr[EAX].Xh = PCIBIOS_BAD_VENDOR_ID; P->Eflags.CF = 1; // set == error } else { for (Bus = 0; Bus <= HalpLastPciBus; Bus++) { for (Device = 0; Device < PCI_MAX_DEVICES; Device++) { if (SBReadConfigWord(Bus, Device, 0, FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) { continue; // no device here } Header = SBReadConfigByte( Bus, Device, 0, FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType)); NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1; for (Function = 0; Function < NumFunctions; Function++) { if (SBReadConfigWord(Bus, Device, Function, FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == VenID) { if (SBReadConfigWord(Bus, Device, Function, FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceID)) == DevID) { Found = (DevIndex == 0); DevIndex--; } } if (Found) break; // function } if (Found) break; // device } if (Found) break; // bus } if (Found) { KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function)); P->Gpr[EBX].Xh = Bus; P->Gpr[EBX].Xl = (Device << 3) + Function; P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success } else { KdPrint(("Not found\n")); P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND; P->Eflags.CF = 1; // set == error } } } break; case PCIBIOS_FIND_PCI_CLASS_CODE: { ULONG ClassCode = (P->Gpr[ECX].Exx) << 8; // see comments below USHORT DevIndex = P->Gpr[ESI].Xx; UCHAR Bus, Device, Function, Header, NumFunctions; BOOLEAN Found = FALSE; KdPrint(("Looking for class instance %d of 0x%X\n", DevIndex, P->Gpr[ECX].Exx)); for (Bus = 0; Bus <= HalpLastPciBus; Bus++) { for (Device = 0; Device < PCI_MAX_DEVICES; Device++) { if (SBReadConfigWord(Bus, Device, 0, FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) { continue; // no device here } Header = SBReadConfigByte( Bus, Device, 0, FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType)); NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1; for (Function = 0; Function < NumFunctions; Function++) { // // The class code bytes are in the same Dword as // the revision id: // // Byte // 3 2 1 0 // +-------------------+--------+ // | class code | Rev id | // +-------------------+--------+ // // Read the Dword and mask off the revision id. // The class code we are looking for has been // shifted up already above. // if ((SBReadConfigDword(Bus, Device, Function, FIELD_OFFSET(PCI_COMMON_CONFIG, RevisionID)) & 0xFFFFFF00) == ClassCode) { Found = (DevIndex == 0); DevIndex--; } if (Found) break; // function } if (Found) break; // device } if (Found) break; // bus } if (Found) { KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function)); P->Gpr[EBX].Xh = Bus; P->Gpr[EBX].Xl = (Device << 3) + Function; P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success } else { KdPrint(("Not found\n")); P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND; P->Eflags.CF = 1; // set == error } } break; case PCIBIOS_READ_CONFIG_BYTE: KdPrint(("read byte %d, %d, %d, %d\n", P->Gpr[EBX].Xh, // Bus (P->Gpr[EBX].Xl >> 3), // Device (P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl)); // Register P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success P->Gpr[ECX].Xl = SBReadConfigByte( P->Gpr[EBX].Xh, // Bus (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl); // Register KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xl)); break; case PCIBIOS_READ_CONFIG_WORD: KdPrint(("read word %d, %d, %d, %d\n", P->Gpr[EBX].Xh, // Bus (P->Gpr[EBX].Xl >> 3), // Device (P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl)); // Register if ((P->Gpr[EDI].Xl & 1) == 0) { P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success P->Gpr[ECX].Xx = SBReadConfigWord( P->Gpr[EBX].Xh, // Bus (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl); // Register } else { P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER; P->Eflags.CF = 1; // set == error } KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xx)); break; case PCIBIOS_READ_CONFIG_DWORD: KdPrint(("read Dword %d, %d, %d, %d\n", P->Gpr[EBX].Xh, // Bus (P->Gpr[EBX].Xl >> 3), // Device (P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl)); // Register if ((P->Gpr[EDI].Xl & 3) == 0) { P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success P->Gpr[ECX].Exx = SBReadConfigDword( P->Gpr[EBX].Xh, // Bus (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl); // Register } else { P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER; P->Eflags.CF = 1; // set == error } KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Exx)); break; case PCIBIOS_WRITE_CONFIG_BYTE: KdPrint(("Write byte 0x%X to %d, %d, %d, %d\n", P->Gpr[ECX].Xl, // Value P->Gpr[EBX].Xh, // Bus (P->Gpr[EBX].Xl >> 3), // Device (P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl)); // Register P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success SBWriteConfigByte( P->Gpr[EBX].Xh, // Bus (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl, // Register P->Gpr[ECX].Xl); // Value break; case PCIBIOS_WRITE_CONFIG_WORD: KdPrint(("Write word 0x%X to %d, %d, %d, %d\n", P->Gpr[ECX].Xx, // Value P->Gpr[EBX].Xh, // Bus (P->Gpr[EBX].Xl >> 3), // Device (P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl)); // Register if ((P->Gpr[EDI].Xl & 1) == 0) { P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success SBWriteConfigWord( P->Gpr[EBX].Xh, // Bus (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl, // Register P->Gpr[ECX].Xx); // Value } else { P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER; P->Eflags.CF = 1; // set == error } break; case PCIBIOS_WRITE_CONFIG_DWORD: KdPrint(("Write Dword 0x%X to %d, %d, %d, %d\n", P->Gpr[ECX].Exx, // Value P->Gpr[EBX].Xh, // Bus (P->Gpr[EBX].Xl >> 3), // Device (P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl)); // Register if ((P->Gpr[EDI].Xl & 3) == 0) { P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success SBWriteConfigDword( P->Gpr[EBX].Xh, // Bus (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function P->Gpr[EDI].Xl, // Register P->Gpr[ECX].Exx); // Value } else { P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER; P->Eflags.CF = 1; // set == error } break; case PCIBIOS_GENERATE_SPECIAL_CYCLE: { PCI_TYPE1_CFG_BITS Addr; KdPrint(("Generate Special cycle %d, 0x%X\n", P->Gpr[EBX].Xh, // Bus P->Gpr[ECX].Exx)); // Value Addr.u.AsULONG = 0; // initialize reserved bits Addr.u.bits.Enable = TRUE; Addr.u.bits.BusNumber = P->Gpr[EBX].Xh; Addr.u.bits.DeviceNumber = 0x1f; Addr.u.bits.FunctionNumber = 7; x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG); x86BiosWriteIoSpace (LONG_DATA, CONFIG_DATA_PORT, P->Gpr[EDX].Exx); P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL; P->Eflags.CF = 0; // clear == success } break; case PCIBIOS_GET_IRQ_ROUTING_OPTIONS: // not supported case PCIBIOS_SET_IRQ_ROUTING_OPTIONS: // not supported default: KdPrint(("PCI BIOS: function %x not supported\n", P->Gpr[EAX].Xl)); P->Gpr[EAX].Xh = PCIBIOS_FUNC_NOT_SUPPORTED; P->Eflags.CF = 1; // set == error break; } return TRUE; } UCHAR SBReadConfigByte( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register ) { ULONG ByteInRegister; PCI_TYPE1_CFG_BITS Addr; Addr.u.AsULONG = 0; // initialize reserved bits Addr.u.bits.Enable = TRUE; Addr.u.bits.BusNumber = Bus; Addr.u.bits.DeviceNumber = Device; Addr.u.bits.FunctionNumber = Function; ByteInRegister = Register % sizeof(ULONG); Addr.u.bits.RegisterNumber = Register / sizeof(ULONG); x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG); return((UCHAR)x86BiosReadIoSpace (BYTE_DATA, (USHORT)(CONFIG_DATA_PORT + ByteInRegister))); } USHORT SBReadConfigWord( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register ) { ULONG WordInRegister; PCI_TYPE1_CFG_BITS Addr; Addr.u.AsULONG = 0; // initialize reserved bits Addr.u.bits.Enable = TRUE; Addr.u.bits.BusNumber = Bus; Addr.u.bits.DeviceNumber = Device; Addr.u.bits.FunctionNumber = Function; WordInRegister = Register % sizeof(ULONG); Addr.u.bits.RegisterNumber = Register / sizeof(ULONG); x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG); return((USHORT)x86BiosReadIoSpace (WORD_DATA, (USHORT)(CONFIG_DATA_PORT + WordInRegister))); } ULONG SBReadConfigDword( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register ) { PCI_TYPE1_CFG_BITS Addr; Addr.u.AsULONG = 0; // initialize reserved bits Addr.u.bits.Enable = TRUE; Addr.u.bits.BusNumber = Bus; Addr.u.bits.DeviceNumber = Device; Addr.u.bits.FunctionNumber = Function; Addr.u.bits.RegisterNumber = Register / sizeof(ULONG); x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG); return(x86BiosReadIoSpace (LONG_DATA, (USHORT)CONFIG_DATA_PORT)); } VOID SBWriteConfigByte( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register, IN UCHAR Data ) { ULONG ByteInRegister; PCI_TYPE1_CFG_BITS Addr; Addr.u.AsULONG = 0; // initialize reserved bits Addr.u.bits.Enable = TRUE; Addr.u.bits.BusNumber = Bus; Addr.u.bits.DeviceNumber = Device; Addr.u.bits.FunctionNumber = Function; ByteInRegister = Register % sizeof(ULONG); Addr.u.bits.RegisterNumber = Register / sizeof(ULONG); x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG); x86BiosWriteIoSpace ( BYTE_DATA, (USHORT)(CONFIG_DATA_PORT + ByteInRegister), Data ); } VOID SBWriteConfigWord( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register, IN USHORT Data ) { ULONG WordInRegister; PCI_TYPE1_CFG_BITS Addr; Addr.u.AsULONG = 0; // initialize reserved bits Addr.u.bits.Enable = TRUE; Addr.u.bits.BusNumber = Bus; Addr.u.bits.DeviceNumber = Device; Addr.u.bits.FunctionNumber = Function; WordInRegister = Register % sizeof(ULONG); Addr.u.bits.RegisterNumber = Register / sizeof(ULONG); x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG); x86BiosWriteIoSpace ( WORD_DATA, (USHORT)(CONFIG_DATA_PORT + WordInRegister), Data ); } VOID SBWriteConfigDword( IN UCHAR Bus, IN UCHAR Device, IN UCHAR Function, IN UCHAR Register, IN ULONG Data ) { PCI_TYPE1_CFG_BITS Addr; Addr.u.AsULONG = 0; // initialize reserved bits Addr.u.bits.Enable = TRUE; Addr.u.bits.BusNumber = Bus; Addr.u.bits.DeviceNumber = Device; Addr.u.bits.FunctionNumber = Function; Addr.u.bits.RegisterNumber = Register / sizeof(ULONG); x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG); x86BiosWriteIoSpace ( LONG_DATA, CONFIG_DATA_PORT, Data ); } #if DBG // Modify this code to match your particular HW configuration // // Use the debugger to force flag to 1. VOID initregs(PRXM_CONTEXT P) { P->Gpr[EAX].Exx = 0x1234B100; P->Gpr[EBX].Exx = 0x23456789; P->Gpr[ECX].Exx = 0x3456789A; P->Gpr[EDX].Exx = 0x456789AB; P->Gpr[ESP].Exx = 0x87654321; P->Gpr[EBP].Exx = 0x98765432; P->Gpr[ESI].Exx = 0xA9876543; P->Gpr[EDI].Exx = 0xBA987654; P->Eflags.CF = 1; } VOID dumpregs(PRXM_CONTEXT P) { DbgPrint("Carry = %d\n", P->Eflags.CF); DbgPrint("EAX = %X, EBX = %X, ECX = %X, EDX = %X\n", P->Gpr[EAX], P->Gpr[EBX], P->Gpr[ECX], P->Gpr[EDX]); DbgPrint("ESP = %X, EBP = %X, ESI = %X, EDI = %X\n", P->Gpr[ESP], P->Gpr[EBP], P->Gpr[ESI], P->Gpr[EDI]); } VOID TestPciBios(int flag) { int i; XM_CONTEXT Context; PRXM_CONTEXT P = &Context; if (flag == 0) return; DbgBreakPoint(); initregs(P); dumpregs(P); DbgBreakPoint(); P->Gpr[EAX].Xl = 1; // bios present HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 2; // find device P->Gpr[ECX].Xx = 0xffff; P->Gpr[EDX].Xx = 0xffff; P->Gpr[ESI].Xx = 0; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++) { initregs(P); P->Gpr[EAX].Xl = 2; // find device P->Gpr[ECX].Xx = 0x0453; P->Gpr[EDX].Xx = 0x8086; P->Gpr[ESI].Xx = i; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); } for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++) { initregs(P); P->Gpr[EAX].Xl = 2; // find device P->Gpr[ECX].Xx = 0x0002; P->Gpr[EDX].Xx = 0x1011; // DEC ethernet P->Gpr[ESI].Xx = i; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); } for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++) { initregs(P); P->Gpr[EAX].Xl = 2; // find device P->Gpr[ECX].Xx = 0x7278; P->Gpr[EDX].Xx = 0x9004; // adaptec P->Gpr[ESI].Xx = i; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); } initregs(P); P->Gpr[EAX].Xl = 2; // find device P->Gpr[ECX].Xx = 0x1234; P->Gpr[EDX].Xx = 0x5678; P->Gpr[ESI].Xx = 0; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++) { initregs(P); P->Gpr[EAX].Xl = 3; // find class code P->Gpr[ECX].Exx = 0x030000; // vga P->Gpr[ESI].Xx = i; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); } for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++) { initregs(P); P->Gpr[EAX].Xl = 3; // find class code P->Gpr[ECX].Exx = 0x020000; // ethernet P->Gpr[ESI].Xx = i; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); } for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++) { initregs(P); P->Gpr[EAX].Xl = 3; // find class code P->Gpr[ECX].Exx = 0x010000; // scsi P->Gpr[ESI].Xx = i; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); } initregs(P); P->Gpr[EAX].Xl = 3; // find class code P->Gpr[ECX].Exx = 0xABCDEF; // not found P->Gpr[ESI].Xx = 0; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 6; // generate special cycle P->Gpr[EBX].Xh = 0; P->Gpr[EDX].Exx = 0x00000002; // x86 specific HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xE; // get irq routing HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xF; // set irq routing HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 8; // read byte P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent P->Gpr[EDI].Xx = 1; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 8; // read byte P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 0; P->Gpr[EDI].Xx = 1; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 8; // read byte P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function P->Gpr[EDI].Xx = 1; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 8; // read byte P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function P->Gpr[EDI].Xx = 1; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 9; // read word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 0; P->Gpr[EDI].Xx = 1; // bad register number HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 9; // read word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent P->Gpr[EDI].Xx = 2; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 9; // read word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 0; P->Gpr[EDI].Xx = 2; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 9; // read word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function P->Gpr[EDI].Xx = 2; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 9; // read word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function P->Gpr[EDI].Xx = 2; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 0; P->Gpr[EDI].Xx = 2; // bad register number HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent P->Gpr[EDI].Xx = 4; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 0; P->Gpr[EDI].Xx = 4; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function P->Gpr[EDI].Xx = 4; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function P->Gpr[EDI].Xx = 4; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (17 << 3) + 0; P->Gpr[EDI].Xx = 2; // bad register number HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x3C; HalpEmulatePciBios(P); dumpregs(P); initregs(P); P->Gpr[EAX].Xl = 0xB; // write byte P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x3C; P->Gpr[ECX].Xl = 0xAB; HalpEmulatePciBios(P); dumpregs(P); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x3C; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xC; // write word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x3F; // bad register P->Gpr[ECX].Xl = 0xAB; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x30; HalpEmulatePciBios(P); dumpregs(P); initregs(P); P->Gpr[EAX].Xl = 0xC; // write word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x30; P->Gpr[ECX].Xx = 0xFFFF; HalpEmulatePciBios(P); dumpregs(P); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x30; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xD; // write Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x3F; // bad register P->Gpr[ECX].Xl = 0xAB; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x30; HalpEmulatePciBios(P); dumpregs(P); initregs(P); P->Gpr[EAX].Xl = 0xD; // write word P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x30; P->Gpr[ECX].Exx = 0xFFFFFFFF; HalpEmulatePciBios(P); dumpregs(P); initregs(P); P->Gpr[EAX].Xl = 0xA; // read Dword P->Gpr[EBX].Xh = 0; P->Gpr[EBX].Xl = (16 << 3) + 0; P->Gpr[EDI].Xx = 0x30; HalpEmulatePciBios(P); dumpregs(P); DbgBreakPoint(); DbgPrint("All done!\n"); DbgBreakPoint(); } #endif