static void __init sal_desc_entry_point (void *p) { struct ia64_sal_desc_entry_point *ep = p; ia64_pal_handler_init(__va(ep->pal_proc)); ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp)); }
void __init early_sn_setup(void) { efi_system_table_t *efi_systab; efi_config_table_t *config_tables; struct ia64_sal_systab *sal_systab; struct ia64_sal_desc_entry_point *ep; char *p; int i, j; /* * Parse enough of the SAL tables to locate the SAL entry point. Since, console * IO on SN2 is done via SAL calls, early_printk won't work without this. * * This code duplicates some of the ACPI table parsing that is in efi.c & sal.c. * Any changes to those file may have to be made hereas well. */ efi_systab = (efi_system_table_t *) __va(ia64_boot_param->efi_systab); config_tables = __va(efi_systab->tables); for (i = 0; i < efi_systab->nr_tables; i++) { if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { sal_systab = __va(config_tables[i].table); p = (char *)(sal_systab + 1); for (j = 0; j < sal_systab->entry_count; j++) { if (*p == SAL_DESC_ENTRY_POINT) { ep = (struct ia64_sal_desc_entry_point *)p; ia64_sal_handler_init(__va (ep->sal_proc), __va(ep->gp)); return; } p += SAL_DESC_SIZE(*p); } } } /* Uh-oh, SAL not available?? */ printk(KERN_ERR "failed to find SAL entry point\n"); }
void __init ia64_sal_init (struct ia64_sal_systab *systab) { unsigned long min, max; char *p; struct ia64_sal_desc_entry_point *ep; int i; if (!systab) { printk("Hmm, no SAL System Table.\n"); return; } if (strncmp(systab->signature, "SST_", 4) != 0) printk("bad signature in system table!"); /* * revisions are coded in BCD, so %x does the job for us */ printk("SAL v%x.%02x: oem=%.32s, product=%.32s\n", systab->sal_rev_major, systab->sal_rev_minor, systab->oem_id, systab->product_id); min = ~0UL; max = 0; p = (char *) (systab + 1); for (i = 0; i < systab->entry_count; i++) { /* * The first byte of each entry type contains the type desciptor. */ switch (*p) { case SAL_DESC_ENTRY_POINT: ep = (struct ia64_sal_desc_entry_point *) p; printk("SAL: entry: pal_proc=0x%lx, sal_proc=0x%lx\n", ep->pal_proc, ep->sal_proc); ia64_pal_handler_init(__va(ep->pal_proc)); ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp)); break; case SAL_DESC_PTC: ia64_ptc_domain_info = (ia64_sal_desc_ptc_t *)p; break; case SAL_DESC_AP_WAKEUP: #ifdef CONFIG_SMP { struct ia64_sal_desc_ap_wakeup *ap = (void *) p; switch (ap->mechanism) { case IA64_SAL_AP_EXTERNAL_INT: ap_wakeup_vector = ap->vector; printk("SAL: AP wakeup using external interrupt " "vector 0x%lx\n", ap_wakeup_vector); break; default: printk("SAL: AP wakeup mechanism unsupported!\n"); break; } break; } #endif case SAL_DESC_PLATFORM_FEATURE: { struct ia64_sal_desc_platform_feature *pf = (void *) p; printk("SAL: Platform features "); if (pf->feature_mask & (1 << 0)) printk("BusLock "); if (pf->feature_mask & (1 << 1)) { printk("IRQ_Redirection "); #ifdef CONFIG_SMP if (no_int_routing) smp_int_redirect &= ~SMP_IRQ_REDIRECTION; else smp_int_redirect |= SMP_IRQ_REDIRECTION; #endif } if (pf->feature_mask & (1 << 2)) { printk("IPI_Redirection "); #ifdef CONFIG_SMP if (no_int_routing) smp_int_redirect &= ~SMP_IPI_REDIRECTION; else smp_int_redirect |= SMP_IPI_REDIRECTION; #endif } printk("\n"); break; } } p += SAL_DESC_SIZE(*p); } }