Home |
RTTarget-32 Programming Manual Running Win32 Programs without Win32 Running a Program on the Target Running with or without Paging Installing Hardware Interrupt Handlers Catching NULL Pointer Assignments Running without Run-Time System Configuration for Debug and Release Builds Loading DLLs through a File System Using the MetaWINDOW Graphics Library Custom MP Floating Pointer Structure Compiling and Linking with On Time RTOS-32 |
Custom MP Floating Pointer StructureSome BIOSes do not supply a usable MP Floating Pointer Structure (see section APIC Mode for details), preventing the use of APIC Mode. On such targets, function RTMPACPITableCreate may be able to create the table through the ACPI BIOS. If this fails too, a custom MP Floating Pointer Structure must be built using functions RTMPTableCreate, RTMPTableCPUEx, RTMPTableIOAPIC, RTMPTableBus, RTMPTableInterrupt, and RTMPTablePCIInterrupt. The custom table must contain data about all installed CPUs, I/O APICs, buses, and the APIC mode interrupt routing. Example (from demo program MPDiag, file CustomMPTable.cpp):// PCI bus numbers start at 0 #define PCI_BUS_0 0 #define PCI_BUS_1 1 #define PCI_BUS_2 2 #define PCI_BUS_3 3 #define PCI_BUS_4 4 #define PCI_BUS_5 5 #define PCI_BUS_6 6 #define PCI_BUS_7 7 #define PCI_BUS_8 8 // etc. // there is only one ISA bus, and it must have an ID larger than any PCI bus #define ISA_BUS 100 #define FIRST_IOAPIC 32 // must be larger than number of logical CPUs #define SECOND_IOAPIC 33 // ditto // etc. // PCI Interrupt Pins #define INT_A 0 #define INT_B 1 #define INT_C 2 #define INT_D 3 /*-----------------------------------*/ void CreateCustomMPTable(void) { static BYTE MPTableBuffer[1024]; // some space for the table RTSMBIOS_BIOS_Info * BIOSInfo = (RTSMBIOS_BIOS_Info *) RTSMBIOSGetStructure(0, 1); // we only have a custom table for one specific BIOS which contains a // broken MP Floating Pointer Structure, which we replace here. if (BIOSInfo && strcmp("BX97520J.86A.2431.2007.0110.1629", RTSMBIOSGetString(BIOSInfo, &BIOSInfo->Version)) == 0) { RTMPTableCreate(MPTableBuffer, sizeof(MPTableBuffer), 0, 0); // Create one CPU entry with local APIC ID 0 RTMPTableCPUEx(0, 1); // Create an I/O APIC at default address RTMPTableIOAPIC(FIRST_IOAPIC, 0); // Create all present buses with unique IDs RTMPTableBus(PCI_BUS_0, "PCI"); RTMPTableBus(PCI_BUS_1, "PCI"); RTMPTableBus(PCI_BUS_4, "PCI"); RTMPTableBus(PCI_BUS_5, "PCI"); RTMPTableBus(ISA_BUS , "ISA"); // IoApicID Int BusID IRQ RTMPTableInterrupt(FIRST_IOAPIC, 1, ISA_BUS, 1, 0); // keyboard RTMPTableInterrupt(FIRST_IOAPIC, 2, ISA_BUS, 0, 0); // timer RTMPTableInterrupt(FIRST_IOAPIC, 3, ISA_BUS, 3, 0); // COM2 RTMPTableInterrupt(FIRST_IOAPIC, 4, ISA_BUS, 4, 0); // COM1 RTMPTableInterrupt(FIRST_IOAPIC, 6, ISA_BUS, 6, 0); // Floppy RTMPTableInterrupt(FIRST_IOAPIC, 7, ISA_BUS, 7, 0); // LPT1 RTMPTableInterrupt(FIRST_IOAPIC, 8, ISA_BUS, 8, 0); // CLOCK RTMPTableInterrupt(FIRST_IOAPIC, 12, ISA_BUS, 12, 0); // Mouse RTMPTableInterrupt(FIRST_IOAPIC, 14, ISA_BUS, 14, 0); // IDE 0 RTMPTableInterrupt(FIRST_IOAPIC, 15, ISA_BUS, 15, 0); // IDE 1 // IoApicID Int BusID Dev Int-Pin RTMPTablePCIInterrupt(FIRST_IOAPIC, 22, PCI_BUS_0, 1, INT_A, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 23, PCI_BUS_0, 29, INT_A, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 19, PCI_BUS_0, 29, INT_B, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 18, PCI_BUS_0, 29, INT_C, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 16, PCI_BUS_0, 29, INT_D, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 19, PCI_BUS_0, 31, INT_B, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 16, PCI_BUS_1, 0, INT_A, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 17, PCI_BUS_4, 0, INT_A, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 18, PCI_BUS_5, 2, INT_A, 0); RTMPTablePCIInterrupt(FIRST_IOAPIC, 18, PCI_BUS_5, 4, INT_A, 0); } } The order of table entries in important. It is recommended to use the same order as in the example above (CPUs, I/O APICs, PCI buses, ISA bus, interrupt routing). Details about each function are given in the RTTarget-32 Reference Manual. Below are a few tips on how to retrieve the required information for a custom MP Floating Pointer Structure. The first CPU will usually have APIC ID 0, but if the system has more than one physical CPU, the IDs of all subsequent CPUs depend on the number of logical CPUs in each physical CPU, which is possibly not known. This problem can be solved in this way: Example (for a 4 CPU socket board):// create the first physical CPU RTMPTableCPUEx(0, 1); // determine how many logical CPUs it contains int L = RTMPCPUs(0); // do not use RT_APIC_NO_HYPERTHREAD here! // now create the other 3 physical CPUs for (int i=1; i<4; i++) RTMPTableCPUEx(i*L, 1); To determine what PCI buses are present, run demo program MPDiag under the debugger. It will list (and write to file Rttarget.log on the host) all present PCI devices and for each the respective PCI bus number, device number, and interrupt pin. Only the PCI bus numbers listed here need to be added to the table using RTMPTableBus. The interrupt routing for ISA devices is straight forward. It is recommended to always use the routing as given in the example above. If you have more ISA devices which can generate interrupts, please add them. The most difficult part is the PCI interrupt routing as it is usually different in APIC mode and in PIC mode. The PIC mode routing is displayed by demo program MPDiag's PCI device list, but the APIC mode routing is required in the custom MP Floating Pointer Structure. One way to find the correct IRQ values is to look them up when the target is running a different OS in APIC mode (Windows 2000 or higher, for example). For each PCI device which shall be operated in interrupt driven mode, determine the device's PCI bus number, PCI device number, and IRQ in the Windows device manager. The respective PCI interrupt pin (A..D) is displayed by MPDiag's PCI device list. An MP Floating Pointer Structure depends heavily on the target's chipset, hardware, and BIOS. Applications should be careful not to install a custom MP Floating Pointer Structure on a target it was not designed for. The example above uses information from the System Management BIOS (SMBIOS) to identify a specific BIOS version. Applications should use a similar mechanism to identify the target system.
|