Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/smp/acpi.c need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "arch/i386.h"
0019 #include "kernel.h"
0020 #include "mem/mem.h"
0021 #include "smp/smp.h"
0022 #include "smp/apic.h"
0023 #include "smp/spinlock.h"
0024 #include "drivers/pci/pci.h"
0025 #include "drivers/acpi/acpi.h"
0026 #include "drivers/acpi/acmacros.h"
0027 #include "drivers/acpi/acexcep.h"
0028 #include "util/printf.h"
0029 #include "util/cpuid.h"
0030 
0031 static int process_acpi_tables (void);
0032 static int acpi_add_processor (ACPI_MADT_LOCAL_APIC *);
0033 static void acpi_parse_srat (ACPI_TABLE_SRAT *);
0034 
0035 /*******************************************************************
0036  * Support for ACPI via ACPICA, the Intel Reference Implementation *
0037  *******************************************************************/
0038 
0039 /* ACPICA supports the notion of "Early Initialization" the very
0040  * purpose of which is to obtain the ACPI tables and begin the process
0041  * of booting Application Processors when the rest of the operating
0042  * system is not ready for normal operation.  This is intended to
0043  * supersede the usage of the Intel Multiprocessing Specification. */
0044 
0045 /* ACPICA early initialization requires some static space be set aside
0046  * for ACPI tables -- and there is no dynamic memory allocation
0047  * available at this stage, so here it is: */
0048 #define ACPI_MAX_INIT_TABLES 24
0049 static ACPI_TABLE_DESC TableArray[ACPI_MAX_INIT_TABLES];
0050 
0051 uint32
0052 acpi_early_init(void)
0053 {
0054   return process_acpi_tables ();
0055 }
0056 
0057 void
0058 acpi_enable_IOAPIC (void)
0059 {
0060   ACPI_STATUS Status;
0061   ACPI_OBJECT arg = { ACPI_TYPE_INTEGER };
0062   ACPI_OBJECT_LIST arg_list = { 1, &arg };
0063   arg.Integer.Value = 1;        /* IOAPIC */
0064   Status = AcpiEvaluateObject (NULL, "\\_PIC", &arg_list, NULL);
0065   if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) {
0066     com1_printf ("unable to evaluate _PIC(1): %d\n", Status);
0067   } else
0068     com1_printf ("ACPI: IOAPIC mode enabled.\n");
0069 }
0070 
0071 static u8 acpi_sci_irq = 9, acpi_sci_flags = 0;
0072 static u32
0073 acpi_irq_handler (u8 vec)
0074 {
0075   extern ACPI_OSD_HANDLER acpi_service_routine;
0076   extern void *acpi_service_routine_context;
0077 
0078   //logger_printf ("ACPI: IRQ (vec=0x%X) acpi_service_routine=0x%p\n", vec, acpi_service_routine);
0079   if (acpi_service_routine) {
0080     acpi_service_routine (acpi_service_routine_context);
0081   }
0082   return 0;
0083 }
0084 
0085 void
0086 acpi_reboot (void)
0087 {
0088   ACPI_STATUS AcpiHwWrite (UINT32 Value, ACPI_GENERIC_ADDRESS *Reg);
0089   AcpiHwWrite (AcpiGbl_FADT.ResetValue, &AcpiGbl_FADT.ResetRegister);
0090 }
0091 
0092 static UINT32
0093 acpi_power_button (void *ctxt)
0094 {
0095   logger_printf ("ACPI: acpi_power_button\n");
0096   printf ("REBOOTING...\n");
0097   com1_printf ("REBOOTING...\n");
0098   tsc_delay_usec (100000);      /* avoid race between COM1 and Reboot */
0099   acpi_reboot ();
0100   asm volatile ("hlt");
0101   return 0;
0102 }
0103 
0104 static void
0105 acpi_notify_handler (ACPI_HANDLE Device,
0106                      UINT32 Value,
0107                      void *Context)
0108 {
0109   ACPI_BUFFER Path;
0110   ACPI_STATUS Status;
0111   logger_printf ("ACPI: acpi_notify_handler (0x%p, 0x%X)\n", Device, Value);
0112   Status = AcpiGetName (Device, ACPI_FULL_PATHNAME, &Path);
0113   if (ACPI_SUCCESS (Status)) {
0114     logger_printf ("    DeviceName=%s\n", Path.Pointer);
0115   }
0116 }
0117 
0118 void
0119 acpi_secondary_init(void)
0120 {
0121   ACPI_STATUS Status;
0122   //ACPI_HANDLE SysBusHandle;
0123   ACPI_STATUS DisplayOneDevice (ACPI_HANDLE, UINT32, void *, void **);
0124   /* Complete the ACPICA initialization sequence */
0125 
0126   Status = AcpiInitializeSubsystem ();
0127   if (ACPI_FAILURE (Status)) {
0128     com1_printf ("Failed to initialize ACPI.\n");
0129   }
0130   Status = AcpiReallocateRootTable ();
0131   if (ACPI_FAILURE (Status)) {
0132     com1_printf ("Failed: AcpiReallocateRootTable %d.\n", Status);
0133   }
0134   Status = AcpiLoadTables ();
0135   if (ACPI_FAILURE (Status)) {
0136     com1_printf ("Failed: AcpiLoadTables.\n");
0137   }
0138   Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION);
0139   if (ACPI_FAILURE (Status)) {
0140     com1_printf ("Failed: AcpiEnableSubsystem.\n");
0141   }
0142   Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION);
0143   if (ACPI_FAILURE (Status)) {
0144     com1_printf ("Failed: AcpiInitializeObjects.\n");
0145   }
0146 
0147   /* Must enable IOAPIC before checking any PCI routing tables. */
0148   acpi_enable_IOAPIC ();
0149 
0150   /* Install System Control Interrupt */
0151   u8 vector = find_unused_vector (MINIMUM_VECTOR_PRIORITY);
0152   if (vector) {
0153     u64 flags = IOAPIC_DELIVERY_FIXED | IOAPIC_DESTINATION_LOGICAL;
0154     u8 gsi = acpi_sci_irq;
0155     /* SCI defaults to LEVEL/LOW in IO-APIC mode. */
0156     if ((acpi_sci_flags & ACPI_MADT_POLARITY_MASK) == ACPI_MADT_POLARITY_ACTIVE_HIGH)
0157       flags |= IOAPIC_POLARITY_HIGH;
0158     else
0159       flags |= IOAPIC_POLARITY_LOW;
0160     if ((acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) == ACPI_MADT_TRIGGER_EDGE)
0161       flags |= IOAPIC_TRIGGER_EDGE;
0162     else
0163       flags |= IOAPIC_TRIGGER_LEVEL;
0164     if (IOAPIC_map_GSI (gsi, vector, 0x0100000000000000ULL | flags) != -1) {
0165       set_vector_handler (vector, acpi_irq_handler);
0166       logger_printf ("ACPI: mapped GSI 0x%X to vector 0x%X (%s, %s)\n",
0167                      gsi, vector,
0168                      flags & IOAPIC_TRIGGER_LEVEL ? "level" : "edge",
0169                      flags & IOAPIC_POLARITY_LOW ? "low" : "high");
0170     } else
0171       logger_printf ("ACPI: failed to map GSI\n");
0172   } else
0173     logger_printf ("ACPI: failed to find unused vector\n");
0174 
0175   logger_printf ("AcpiEnableEvent returned %d\n",
0176                  AcpiEnableEvent (ACPI_EVENT_POWER_BUTTON, 0));
0177   logger_printf ("AcpiInstallFixedEventHandler returned %d\n",
0178                  AcpiInstallFixedEventHandler (ACPI_EVENT_POWER_BUTTON, acpi_power_button, NULL));
0179   logger_printf ("AcpiInstallNotifyHandler returned %d\n",
0180                  AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, acpi_notify_handler, NULL));
0181   logger_printf ("AcpiInstallNotifyHandler returned %d\n",
0182                  AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY, acpi_notify_handler, NULL));
0183 
0184   extern u8 AcpiGbl_OsiData;
0185   AcpiGbl_OsiData=0;
0186 
0187   /* Walk the System Bus "\_SB_" and output info about each object
0188    * found. */
0189 
0190 #if 0
0191   AcpiGetHandle (ACPI_ROOT_OBJECT, ACPI_NS_SYSTEM_BUS, &SysBusHandle);
0192   AcpiWalkNamespace (ACPI_TYPE_ANY, SysBusHandle, INT_MAX,
0193                      DisplayOneDevice, NULL, NULL);
0194 #else
0195   AcpiGetDevices (NULL, DisplayOneDevice, NULL, NULL);
0196 #endif
0197 }
0198 
0199 #define printf com1_printf
0200 static int
0201 process_acpi_tables (void)
0202 {
0203   extern uint32 mp_LAPIC_addr;
0204   extern uint32 mp_num_IOAPICs;
0205   extern uint32 mp_IOAPIC_addr;
0206   extern mp_IOAPIC_info mp_IOAPICs[];
0207   extern uint32 mp_num_overrides;
0208   extern mp_int_override mp_overrides[];
0209 
0210   ACPI_STATUS status;
0211 
0212   status = AcpiInitializeTables (TableArray, ACPI_MAX_INIT_TABLES, FALSE);
0213 
0214   if (status == AE_OK) {
0215     ACPI_TABLE_MADT *madt;
0216     ACPI_TABLE_FADT *fadt;
0217     ACPI_TABLE_BOOT *boot;
0218     ACPI_TABLE_ASF *asf;
0219     ACPI_TABLE_MCFG *mcfg;
0220     ACPI_TABLE_HPET *hpet;
0221     ACPI_TABLE_TCPA *tcpa;
0222     ACPI_TABLE_SRAT *srat;
0223     ACPI_TABLE_DMAR *dmar;
0224 
0225     if (AcpiGetTable (ACPI_SIG_FADT, 0, (ACPI_TABLE_HEADER **) & fadt) ==
0226         AE_OK) {
0227       /* Fixed ACPI Description Table */
0228       printf ("Bootflags: %s %s %s\n",
0229               (fadt->BootFlags & ACPI_FADT_LEGACY_DEVICES) ?
0230               "HAS_LEGACY_DEVICES" : "NO_LEGACY_DEVICES",
0231               (fadt->BootFlags & ACPI_FADT_8042) ?
0232               "HAS_KBD_8042" : "NO_KBD_8042",
0233               (fadt->BootFlags & ACPI_FADT_NO_VGA) ?
0234               "NO_VGA_PROBING" : "VGA_PROBING_OK");
0235       printf ("Flags=0x%X SCI_IRQ=0x%X Pm1aEvt=0x%p Pm1aCtl=0x%p\n",
0236               fadt->Flags,
0237               fadt->SciInterrupt,
0238               fadt->Pm1aEventBlock,
0239               fadt->Pm1aControlBlock);
0240       printf ("ResetReg=0x%llX ResetSpace=%d ResetVal=0x%X\n",
0241               fadt->ResetRegister.Address, fadt->ResetRegister.SpaceId, fadt->ResetValue);
0242       acpi_sci_irq = fadt->SciInterrupt;
0243     } else {
0244       printf ("AcpiGetTable FADT: FAILED\n");
0245     }
0246 
0247     mp_ISA_bus_id = 0;
0248     if (AcpiGetTable (ACPI_SIG_MADT, 0, (ACPI_TABLE_HEADER **) & madt) ==
0249         AE_OK) {
0250       /* Multiple APIC Description Table */
0251       uint8 *ptr, *lim = (uint8 *) madt + madt->Header.Length;
0252       printf ("ACPI OEM: %.6s Compiler: %.4s LAPIC: %p Flags:%s\n",
0253               madt->Header.OemId,
0254               madt->Header.AslCompilerId,
0255               madt->Address,
0256               (madt->Flags & ACPI_MADT_PCAT_COMPAT) ? " PCAT_COMPAT" : "");
0257       mp_LAPIC_addr = madt->Address;
0258       ptr = (uint8 *) madt + sizeof (ACPI_TABLE_MADT);
0259       while (ptr < lim) {
0260         switch (((ACPI_SUBTABLE_HEADER *) ptr)->Type) {
0261         case ACPI_MADT_TYPE_LOCAL_APIC:{
0262           /* Processor entry */
0263           ACPI_MADT_LOCAL_APIC *sub = (ACPI_MADT_LOCAL_APIC *) ptr;
0264           printf ("Processor: 0x%X APIC-ID: 0x%X %s",
0265                   sub->ProcessorId,
0266                   sub->Id,
0267                   sub->LapicFlags & 1 ? "(enabled)" : "(disabled)");
0268           if (acpi_add_processor (sub)) {
0269             printf (" (booted)");
0270           }
0271           printf ("\n");
0272           break;
0273         }
0274         case ACPI_MADT_TYPE_IO_APIC:{
0275           /* IO-APIC entry */
0276           ACPI_MADT_IO_APIC *sub = (ACPI_MADT_IO_APIC *) ptr;
0277           printf ("IO-APIC ID: %X Address: %X IRQBase: %X\n",
0278                   sub->Id, sub->Address, sub->GlobalIrqBase);
0279           if (mp_num_IOAPICs == MAX_IOAPICS)
0280             panic ("Too many IO-APICs.");
0281           mp_IOAPIC_addr = sub->Address;
0282           mp_IOAPICs[mp_num_IOAPICs].id = sub->Id;
0283           mp_IOAPICs[mp_num_IOAPICs].address = sub->Address;
0284           mp_IOAPICs[mp_num_IOAPICs].startGSI = sub->GlobalIrqBase;
0285           mp_IOAPICs[mp_num_IOAPICs].numGSIs = IOAPIC_num_entries();
0286           mp_num_IOAPICs++;
0287           break;
0288         }
0289         case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:{
0290           /* Interrupt Override entry */
0291           ACPI_MADT_INTERRUPT_OVERRIDE *sub =
0292             (ACPI_MADT_INTERRUPT_OVERRIDE *) ptr;
0293           printf ("Int. Override: Bus: %X SourceIRQ: %X GlobalIRQ: %X Flags: %X\n",
0294                   sub->Bus, sub->SourceIrq, sub->GlobalIrq, sub->IntiFlags);
0295           if (mp_num_overrides == MAX_INT_OVERRIDES)
0296             panic ("Too many interrupt overrides.");
0297           mp_overrides[mp_num_overrides].src_bus = sub->Bus;
0298           mp_overrides[mp_num_overrides].src_IRQ = sub->SourceIrq;
0299           mp_overrides[mp_num_overrides].dest_GSI = sub->GlobalIrq;
0300           mp_num_overrides++;
0301           /* (special case) SCI interrupt: it can be different in ACPI
0302            * tables vs Intel MPS tables. */
0303           if (sub->SourceIrq == acpi_sci_irq) {
0304             acpi_sci_irq = sub->GlobalIrq;
0305             acpi_sci_flags = sub->IntiFlags;
0306           }
0307           break;
0308         }
0309         default:
0310           printf ("MADT sub-entry: %X\n",
0311                   ((ACPI_SUBTABLE_HEADER *) ptr)->Type);
0312           break;
0313         }
0314         ptr += ((ACPI_SUBTABLE_HEADER *) ptr)->Length;
0315       }
0316     } else {
0317       printf ("AcpiGetTable MADT: FAILED\n");
0318       return 0;
0319     }
0320     if (AcpiGetTable (ACPI_SIG_BOOT, 0, (ACPI_TABLE_HEADER **) & boot) ==
0321         AE_OK) {
0322       /* Simple Boot Information Table */
0323       printf ("BOOT: CmosIndex=0x%X\n", boot->CmosIndex);
0324     }
0325     if (AcpiGetTable (ACPI_SIG_TCPA, 0, (ACPI_TABLE_HEADER **) & tcpa) ==
0326         AE_OK) {
0327       /* Trusted Computing Platform Alliance table */
0328       printf ("TCPA: MaxLog=0x%X Addr: 0x%llX\n",
0329               tcpa->MaxLogLength,
0330               tcpa->LogAddress);
0331     }
0332     if (AcpiGetTable (ACPI_SIG_HPET, 0, (ACPI_TABLE_HEADER **) & hpet) ==
0333         AE_OK) {
0334       /* High Precision Event Timer table */
0335       printf ("HPET: ID: 0x%X Addr: 0x%p Seq#: 0x%X MinTick: 0x%X Flags: 0x%X\n",
0336               hpet->Id,
0337               hpet->Address,
0338               (uint32) hpet->Sequence,
0339               (uint32) hpet->MinimumTick, (uint32) hpet->Flags);
0340     }
0341     if (AcpiGetTable (ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **) & mcfg) ==
0342         AE_OK) {
0343       /* PCI Memory Mapped Configuration table */
0344       printf ("MCFG: Length: %d Reserved: 0x%llX\n",
0345               mcfg->Header.Length,
0346               mcfg->Reserved);
0347     }
0348     if (AcpiGetTable (ACPI_SIG_ASF, 0, (ACPI_TABLE_HEADER **) & asf) == AE_OK) {
0349       /* Alert Standard Format table */
0350       printf ("ASF: Length: %d\n", mcfg->Header.Length);
0351     }
0352     if (AcpiGetTable (ACPI_SIG_SRAT, 0, (ACPI_TABLE_HEADER **) & srat) == AE_OK) {
0353       /* System Resource Affinity Table */
0354       printf ("SRAT: Length: %d\n", srat->Header.Length);
0355       acpi_parse_srat (srat);
0356     }
0357     if (AcpiGetTable (ACPI_SIG_DMAR, 0, (ACPI_TABLE_HEADER **) & dmar) == AE_OK) {
0358       /* DMA Remapping */
0359       printf ("DMAR: Length: %d Flags: 0x%X Width: %d\n",
0360               dmar->Header.Length,
0361               dmar->Flags,
0362               dmar->Width);
0363     }
0364   } else
0365     return 0;
0366 
0367   return mp_num_cpus;
0368 }
0369 
0370 #undef printf
0371 
0372 /* A small wrapper around smp_boot_cpu() which does some checks and
0373  * maintains two small tables. */
0374 static int
0375 acpi_add_processor (ACPI_MADT_LOCAL_APIC * ptr)
0376 {
0377 #ifndef NO_SMP
0378   u32 ebx;
0379   cpuid (1, 0, NULL, &ebx, NULL, NULL);
0380   uint8 this_apic_id = ebx >> 24;
0381   uint8 apic_id = ptr->Id;
0382 
0383   if (!(ptr->LapicFlags & 1))
0384     return 0;                   /* disabled processor */
0385   if (this_apic_id == apic_id)
0386     return 0;                   /* bootstrap processor */
0387 
0388   if (smp_boot_cpu (apic_id, APIC_VER_NEW)) {
0389     CPU_to_APIC[mp_num_cpus] = apic_id;
0390     APIC_to_CPU[apic_id] = mp_num_cpus;
0391     mp_num_cpus++;
0392     return 1;
0393   } else
0394     return 0;
0395 #else
0396   return 0;
0397 #endif
0398 }
0399 
0400 /* ************************************************** */
0401 
0402 extern char const *AcpiGbl_ExceptionNames_Env[];
0403 
0404 ACPI_STATUS
0405 GetLnkIrq (ACPI_RESOURCE *Resource, void *Context)
0406 {
0407   pci_irq_t *irq = (pci_irq_t *)Context;
0408   if (Resource->Type == ACPI_RESOURCE_TYPE_IRQ) {
0409     irq->gsi = Resource->Data.Irq.Interrupts[0];
0410     irq->trigger = Resource->Data.Irq.Triggering;
0411     irq->polarity = Resource->Data.Irq.Polarity;
0412     return AE_CTRL_TERMINATE;
0413   }
0414   return AE_OK;
0415 }
0416 
0417 void
0418 GetLnkInfo (char *lnkname, pci_irq_t *irq)
0419 {
0420   ACPI_HANDLE Handle;
0421   ACPI_STATUS Status;
0422 
0423   Status = AcpiGetHandle (NULL, lnkname, &Handle);
0424   if (ACPI_SUCCESS (Status)) {
0425     AcpiWalkResources (Handle, "_CRS", GetLnkIrq, (void *) irq);
0426   }
0427 }
0428 
0429 #define READ(bus, slot, func, reg, type)                \
0430   pci_read_##type (pci_addr (bus, slot, func, reg))
0431 
0432 ACPI_STATUS
0433 DisplayOneDevice (ACPI_HANDLE ObjHandle, UINT32 Level, void *Context,
0434                   void **RetVal)
0435 {
0436   ACPI_STATUS Status;
0437   ACPI_DEVICE_INFO *Info;
0438   ACPI_BUFFER Path;
0439   ACPI_BUFFER Result;
0440   ACPI_OBJECT Obj;
0441   char Buffer[256];
0442   uint8 prt_buf[1024];
0443   ACPI_BUFFER Prt = { .Length = sizeof (prt_buf), .Pointer = prt_buf };
0444   ACPI_PCI_ROUTING_TABLE *prtd;
0445   uint32 addr=0;
0446   uint32 fun = 0;
0447   bool pcibus=FALSE;
0448   u8 busnum;
0449 
0450   Path.Length = sizeof (Buffer);
0451   Path.Pointer = Buffer;
0452 
0453   Status = AcpiGetName (ObjHandle, ACPI_FULL_PATHNAME, &Path);
0454   if (ACPI_SUCCESS (Status)) {
0455     com1_printf ("%s: \n", Path.Pointer);
0456   }
0457   Status = AcpiGetObjectInfo (ObjHandle, &Info);
0458   if (ACPI_SUCCESS (Status)) {
0459     com1_printf ("    ");
0460     if (Info->Flags & ACPI_PCI_ROOT_BRIDGE) {
0461       com1_printf (" PCI_ROOT");
0462       busnum = 0;
0463       pcibus = TRUE;
0464     }
0465     if (Info->Valid & ACPI_VALID_STA)
0466       com1_printf (" STA %.8X", Info->CurrentStatus);
0467     if (Info->Valid & ACPI_VALID_ADR) {
0468       com1_printf (" ADR %.8X", Info->Address);
0469       addr = Info->Address >> 16;
0470       fun = Info->Address & 0x7;
0471     }
0472     if (Info->Valid & ACPI_VALID_HID)
0473       com1_printf (" HID %s", Info->HardwareId.String);
0474     if (Info->Valid & ACPI_VALID_UID)
0475       com1_printf (" UID %s", Info->UniqueId.String);
0476     if (Info->Valid & ACPI_VALID_CID)
0477       com1_printf (" CID");
0478 
0479     ACPI_FREE (Info);
0480   }
0481 
0482   Result.Length = sizeof (Obj);
0483   Result.Pointer = &Obj;
0484   Status =
0485     AcpiEvaluateObjectTyped (ObjHandle, "_DDN", NULL, &Result,
0486                              ACPI_TYPE_STRING);
0487   if (ACPI_SUCCESS (Status)) {
0488     com1_printf (" DDN=%s", Obj.String.Pointer);
0489   }
0490 
0491   Result.Length = sizeof (Obj);
0492   Result.Pointer = &Obj;
0493   Status =
0494     AcpiEvaluateObjectTyped (ObjHandle, "_STR", NULL, &Result,
0495                              ACPI_TYPE_STRING);
0496   if (ACPI_SUCCESS (Status)) {
0497     com1_printf (" STR=%s", Obj.String.Pointer);
0498   }
0499 
0500   Result.Length = sizeof (Obj);
0501   Result.Pointer = &Obj;
0502   Status =
0503     AcpiEvaluateObjectTyped (ObjHandle, "_MLS", NULL, &Result,
0504                              ACPI_TYPE_STRING);
0505   if (ACPI_SUCCESS (Status)) {
0506     com1_printf (" MLS=%s", Obj.String.Pointer);
0507   }
0508 
0509   Status =
0510     AcpiEvaluateObjectTyped (ObjHandle, "_BBN", NULL, &Result,
0511                              ACPI_TYPE_INTEGER);
0512   if (ACPI_SUCCESS (Status)) {
0513     com1_printf (" BBN=%d", Obj.Integer.Value);
0514   } else if (Status != AE_NOT_FOUND)
0515     com1_printf (" bbnERR=%d", Status);
0516 
0517   Status =
0518     AcpiEvaluateObjectTyped (ObjHandle, "_PXM", NULL, &Result,
0519                              ACPI_TYPE_INTEGER);
0520   if (ACPI_SUCCESS (Status)) {
0521     com1_printf (" PXM=%d", Obj.Integer.Value);
0522   } else if (Status != AE_NOT_FOUND)
0523     com1_printf (" pxmERR=%d", Status);
0524 
0525 
0526   com1_printf ("\n");
0527 
0528   for (;;) {
0529     Status = AcpiGetIrqRoutingTable (ObjHandle, &Prt);
0530     if (ACPI_FAILURE (Status)) {
0531       if (Status == AE_BUFFER_OVERFLOW) {
0532         com1_printf ("AcpiGetIrqRoutingTable failed: BUFFER OVERFLOW\n");
0533       }
0534       break;
0535     } else break;
0536   }
0537   if (ACPI_SUCCESS (Status)) {
0538     int i;
0539 
0540     /* Check if ObjHandle refers to a non-root PCI bus */
0541     if (READ (0, addr, 0, 0, dword) != 0xFFFFFFFF) {
0542       u8 hdrtype = READ (0, addr, 0, 0x0E, byte);
0543       if ((hdrtype & 0x7F) == 1) {
0544         /* PCI-to-PCI bridge headerType == 1 */
0545         busnum = READ (0, addr, fun, 0x19, byte);
0546         com1_printf ("  bus=0x%.02X\n", busnum);
0547         pcibus = TRUE;
0548       }
0549     }
0550 
0551     for (i=0;i<sizeof(prt_buf);) {
0552       pci_irq_t irq;
0553       prtd = (ACPI_PCI_ROUTING_TABLE *)(&prt_buf[i]);
0554       if (prtd->Length == 0) break;
0555 
0556       if (pcibus) {
0557         irq.bus = busnum;
0558         irq.dev = (uint32) ((prtd->Address >> 16) & 0xFF);
0559         irq.pin = prtd->Pin + 1; /* ACPI numbers pins from 0 */
0560         irq.gsi = 0;
0561       }
0562 
0563       if (prtd->Source[0]) {
0564         com1_printf ("  PRT entry: len=%d pin=%d addr=%p srcidx=0x%x src=%s\n",
0565                      prtd->Length,
0566                      prtd->Pin,
0567                      (uint32)prtd->Address,
0568                      prtd->SourceIndex,
0569                      &prtd->Source[0]);
0570         GetLnkInfo (&prtd->Source[0], &irq);
0571       } else {
0572         com1_printf ("  PRT entry: len=%d pin=%d addr=%p fixed IRQ=0x%x\n",
0573                      prtd->Length,
0574                      prtd->Pin,
0575                      (uint32)prtd->Address,
0576                      prtd->SourceIndex);
0577         irq.gsi = prtd->SourceIndex;
0578         irq.polarity = POLARITY_DEFAULT;
0579         irq.trigger = TRIGGER_DEFAULT;
0580       }
0581 
0582       if (pcibus && irq.gsi != 0)
0583         pci_irq_register (&irq);
0584 
0585       i+=prtd->Length;
0586     }
0587   }
0588 
0589 #if 0
0590   ACPI_STATUS DisplayResource (ACPI_RESOURCE *Resource, void *Context);
0591   com1_printf ("  _PRS:\n");
0592   AcpiWalkResources (ObjHandle, "_PRS", DisplayResource, NULL);
0593   com1_printf ("  _CRS:\n");
0594   AcpiWalkResources (ObjHandle, "_CRS", DisplayResource, NULL);
0595 #endif
0596   return AE_OK;
0597 }
0598 
0599 ACPI_STATUS
0600 DisplayResource (ACPI_RESOURCE *Resource, void *Context)
0601 {
0602   int i;
0603   com1_printf ("Resource: type=%d ", Resource->Type);
0604   switch (Resource->Type) {
0605   case ACPI_RESOURCE_TYPE_IRQ:
0606     com1_printf ("IRQ dlen=%d trig=%d pol=%d shar=%d cnt=%d\n  int=",
0607                  Resource->Data.Irq.DescriptorLength,
0608                  Resource->Data.Irq.Triggering,
0609                  Resource->Data.Irq.Polarity,
0610                  Resource->Data.Irq.Sharable,
0611                  Resource->Data.Irq.InterruptCount);
0612     for (i=0;i<Resource->Data.Irq.InterruptCount;i++)
0613       com1_printf ("%.02X ", Resource->Data.Irq.Interrupts[i]);
0614     com1_printf ("\n");
0615     break;
0616   case ACPI_RESOURCE_TYPE_IO:
0617     com1_printf ("IO decode=0x%x align=0x%x addrlen=%d min=0x%.04X max=0x%.04X\n",
0618                  Resource->Data.Io.IoDecode,
0619                  Resource->Data.Io.Alignment,
0620                  Resource->Data.Io.AddressLength,
0621                  Resource->Data.Io.Minimum,
0622                  Resource->Data.Io.Maximum);
0623     break;
0624   case ACPI_RESOURCE_TYPE_END_TAG:
0625     com1_printf ("end_tag\n");
0626     break;
0627   case ACPI_RESOURCE_TYPE_ADDRESS16:
0628     com1_printf ("ADDR16 type=%d min=0x%.04X max=0x%.04X gran=0x%.04X trans=0x%.04X\n",
0629                  Resource->Data.Address16.ResourceType,
0630                  Resource->Data.Address16.Minimum,
0631                  Resource->Data.Address16.Maximum,
0632                  Resource->Data.Address16.Granularity,
0633                  Resource->Data.Address16.TranslationOffset);
0634     break;
0635   case ACPI_RESOURCE_TYPE_ADDRESS32:
0636     com1_printf ("ADDR32 type=%d min=0x%.04X max=0x%.04X\n",
0637                  Resource->Data.Address32.ResourceType,
0638                  Resource->Data.Address32.Minimum,
0639                  Resource->Data.Address32.Maximum);
0640     break;
0641   default:
0642     com1_printf ("unhandled\n");
0643     break;
0644   }
0645   return AE_OK;
0646 }
0647 
0648 /* ************************************************** */
0649 
0650 static void
0651 acpi_parse_srat (ACPI_TABLE_SRAT *srat)
0652 {
0653   ACPI_SRAT_CPU_AFFINITY *cpu;
0654   ACPI_SRAT_MEM_AFFINITY *mem;
0655   ACPI_SRAT_X2APIC_CPU_AFFINITY *x2apic;
0656   u32 prox;
0657   ACPI_SUBTABLE_HEADER *sub = (ACPI_SUBTABLE_HEADER *) &srat[1];
0658   int len = srat->Header.Length;
0659 
0660   len -= sizeof (ACPI_TABLE_SRAT);
0661   while (len > 0) {
0662     /* len = size of remaining subtables */
0663     /* sub = pointer to subtable */
0664     switch (sub->Type) {
0665     case ACPI_SRAT_TYPE_CPU_AFFINITY:
0666       cpu = (ACPI_SRAT_CPU_AFFINITY *) sub;
0667       prox = cpu->ProximityDomainLo |
0668         (cpu->ProximityDomainHi[0] << 0x08 |
0669          cpu->ProximityDomainHi[1] << 0x10 |
0670          cpu->ProximityDomainHi[2] << 0x18);
0671       logger_printf ("SRAT: CPU: prox=0x%X apicID=0x%X flags=0x%X%s sapicEID=0x%X\n",
0672                      prox, cpu->ApicId, cpu->Flags,
0673                      cpu->Flags & ACPI_SRAT_CPU_ENABLED ? " enabled" : "",
0674                      cpu->LocalSapicEid);
0675       break;
0676     case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
0677       mem = (ACPI_SRAT_MEM_AFFINITY *) sub;
0678       logger_printf ("SRAT: MEM: prox=0x%X base=0x%llX len=0x%llX flags=0x%X%s%s%s\n",
0679                      mem->ProximityDomain, mem->BaseAddress, mem->Length, mem->Flags,
0680                      mem->Flags & ACPI_SRAT_MEM_ENABLED ? " enabled" : "",
0681                      mem->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE ? " hotplug" : "",
0682                      mem->Flags & ACPI_SRAT_MEM_NON_VOLATILE ? " nonvolatile" : "");
0683       break;
0684     case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY:
0685       x2apic = (ACPI_SRAT_X2APIC_CPU_AFFINITY *) sub;
0686       logger_printf ("SRAT: X2APIC: prox=0x%X apicID=0x%X flags=0x%X%s clockDom=0x%X\n",
0687                      x2apic->ProximityDomain, x2apic->ApicId, x2apic->Flags,
0688                      x2apic->Flags & ACPI_SRAT_CPU_ENABLED ? " enabled" : "",
0689                      x2apic->ClockDomain);
0690       break;
0691     default:
0692       logger_printf ("SRAT: unknown subtype type=%d\n", sub->Type);
0693       break;
0694     }
0695     len -= sub->Length;
0696     sub = (ACPI_SUBTABLE_HEADER *) &((u8 *) sub)[sub->Length];
0697   }
0698 }
0699 
0700 /* End ACPI support */
0701 
0702 
0703 /*
0704  * Local Variables:
0705  * indent-tabs-mode: nil
0706  * mode: C
0707  * c-file-style: "gnu"
0708  * c-basic-offset: 2
0709  * End:
0710  */
0711 
0712 /* vi: set et sw=2 sts=2: */