NT4/private/ntos/nthals/halfire/ppc/pcibios.c
2020-09-30 17:12:29 +02:00

1085 lines
27 KiB
C

/*++
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