/* Functions */ static void bios_mcabus_present(void * dummy) { struct vm86frame vmf; struct sys_config * scp; vm_offset_t paddr; bzero(&vmf, sizeof(struct vm86frame)); vmf.vmf_ah = 0xc0; if (vm86_intcall(0x15, &vmf)) { if (bootverbose) { printf("BIOS SDT: INT call failed.\n"); } return; } if ((vmf.vmf_ah != 0) && (vmf.vmf_flags & 0x01)) { if (bootverbose) { printf("BIOS SDT: Not supported. Not PS/2?\n"); printf("BIOS SDT: AH 0x%02x, Flags 0x%04x\n", vmf.vmf_ah, vmf.vmf_flags); } return; } paddr = vmf.vmf_es; paddr = (paddr << 4) + vmf.vmf_bx; scp = (struct sys_config *)BIOS_PADDRTOVADDR(paddr); if (bootverbose) { printf("BIOS SDT: model 0x%02x, submodel 0x%02x, bios_rev 0x%02x\n", scp->model, scp->submodel, scp->bios_rev); printf("BIOS SDT: features 0x%b\n", scp->feature, "\20" "\01RESV" "\02MCABUS" "\03EBDA" "\04WAITEV" "\05KBDINT" "\06RTC" "\07IC2" "\08DMA3\n"); } MCA_system = ((scp->feature & FEATURE_MCABUS) ? 1 : 0); if (MCA_system) printf("MicroChannel Architecture System detected.\n"); return; }
int k8pnow_states(struct k8pnow_cpu_state *cstate, uint32_t cpusig, unsigned int fid, unsigned int vid) { struct psb_s *psb; struct pst_s *pst; uint8_t *p; int i; for (p = (u_int8_t *) BIOS_PADDRTOVADDR(BIOS_START); p < (u_int8_t *) BIOS_PADDRTOVADDR(BIOS_START + BIOS_LEN); p += BIOS_STEP) { if (memcmp(p, "AMDK7PNOW!", 10) == 0) { psb = (struct psb_s *)p; if (psb->version != PN8_PSB_VERSION) return 0; cstate->vst = psb->ttime; cstate->rvo = PN8_PSB_TO_RVO(psb->reserved); cstate->irt = PN8_PSB_TO_IRT(psb->reserved); cstate->mvs = PN8_PSB_TO_MVS(psb->reserved); cstate->low = PN8_PSB_TO_BATT(psb->reserved); p += sizeof(struct psb_s); for (i = 0; i < psb->n_pst; ++i) { pst = (struct pst_s *)p; cstate->pll = pst->pll; cstate->n_states = pst->n_states; if (cpusig == pst->cpuid && pst->fid == fid && pst->vid == vid) { return (k8pnow_decode_pst(cstate, p += sizeof(struct pst_s))); } p += sizeof(struct pst_s) + 2 * cstate->n_states; } } } return 0; }
/*** * Finds the first structure of Type * Sets addr to start of structure if found or * NULL if no structure of Type is found * Return 1 if a structure was found */ static int smbios_FindStructure(u_int8_t Type, uintptr_t *addr) { int ret = 0; u_short i = 0; uintptr_t TableAddress = 0; /* Structure Table Address */ TableAddress = BIOS_PADDRTOVADDR(*((uintptr_t *)(smbios_eps + 0x18))); printf("SMBIOS: finding struct"); while (i < *((u_int16_t *)(smbios_eps + 0x1c))) /*Number of Structures*/ { printf("."); if ( *((u_int8_t *)TableAddress) == Type ) { ret = 1; break; } /* add Length */ TableAddress += *((u_int8_t *)TableAddress + 0x1); while ( *((u_int16_t *)TableAddress) != 0x00 ) { TableAddress++; } TableAddress += 2; /* set to start of next structure */ i++; } printf(" done!\n"); if (ret) *addr = TableAddress; else addr = NULL; return ret; }
static int smbios_find_eps(void) { uintptr_t addr; u_int8_t major, minor; if (smbios_eps == 0xffff) return 0; /* already set */ if (smbios_eps > 0) return 1; addr = bios_sigsearch(SMBIOS_START, SMBIOS_SIG, SMBIOS_LEN, SMBIOS_STEP, SMBIOS_OFF); if (addr != 0) { smbios_eps = BIOS_PADDRTOVADDR(addr); if (smbios_cksum(smbios_eps)) { printf("SMBIOS checksum failed.\n"); smbios_eps = 0xffff; return 0; } else { printf("SMBIOS found\n"); major = *((u_int8_t *)(smbios_eps + 0x6)); minor = *((u_int8_t *)(smbios_eps + 0x7)); printf("SMBIOS %i.%i found\n", major, minor); return 1; } } printf("SMBIOS Signature not found\n"); smbios_eps = 0xffff; return 0; }
static int smapi_attach (device_t dev) { struct smapi_softc *sc; int error; sc = device_get_softc(dev); error = 0; sc->dev = dev; sc->rid = 0; sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid, RF_ACTIVE); if (sc->res == NULL) { device_printf(dev, "Unable to allocate memory resource.\n"); error = ENOMEM; goto bad; } sc->header = (struct smapi_bios_header *)rman_get_virtual(sc->res); sc->smapi32_entry = (u_int32_t)BIOS_PADDRTOVADDR( sc->header->prot32_segment + sc->header->prot32_offset); sc->cdev = make_dev(&smapi_cdevsw, device_get_unit(sc->dev), UID_ROOT, GID_WHEEL, 0600, "%s%d", smapi_cdevsw.d_name, device_get_unit(sc->dev)); device_printf(dev, "Version: %d.%02d, Length: %d, Checksum: 0x%02x\n", bcd2bin(sc->header->version_major), bcd2bin(sc->header->version_minor), sc->header->length, sc->header->checksum); device_printf(dev, "Information=0x%b\n", sc->header->information, "\020" "\001REAL_VM86" "\002PROTECTED_16" "\003PROTECTED_32"); if (bootverbose) { if (sc->header->information & SMAPI_REAL_VM86) device_printf(dev, "Real/VM86 mode: Segment 0x%04x, Offset 0x%04x\n", sc->header->real16_segment, sc->header->real16_offset); if (sc->header->information & SMAPI_PROT_16BIT) device_printf(dev, "16-bit Protected mode: Segment 0x%08x, Offset 0x%04x\n", sc->header->prot16_segment, sc->header->prot16_offset); if (sc->header->information & SMAPI_PROT_32BIT) device_printf(dev, "32-bit Protected mode: Segment 0x%08x, Offset 0x%08x\n", sc->header->prot32_segment, sc->header->prot32_offset); } return (0); bad: if (sc->res) bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res); return (error); }
static int pn_decode_pst(device_t dev) { int maxpst; struct pn_softc *sc; u_int cpuid, maxfid, startvid; u_long sig; struct psb_header *psb; uint8_t *p; u_int regs[4]; uint64_t status; sc = device_get_softc(dev); do_cpuid(0x80000001, regs); cpuid = regs[0]; if ((cpuid & 0xfff) == 0x760) sc->errata |= A0_ERRATA; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); switch (sc->pn_type) { case PN7_TYPE: maxfid = PN7_STA_MFID(status); startvid = PN7_STA_SVID(status); break; case PN8_TYPE: maxfid = PN8_STA_MFID(status); /* * we should actually use a variable named 'maxvid' if K8, * but why introducing a new variable for that? */ startvid = PN8_STA_MVID(status); break; default: return (ENODEV); } if (bootverbose) { device_printf(dev, "STATUS: 0x%jx\n", status); device_printf(dev, "STATUS: maxfid: 0x%02x\n", maxfid); device_printf(dev, "STATUS: %s: 0x%02x\n", sc->pn_type == PN7_TYPE ? "startvid" : "maxvid", startvid); } sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF); if (sig) { struct pst_header *pst; psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig); switch (psb->version) { default: return (ENODEV); case 0x14: /* * We can't be picky about numpst since at least * some systems have a value of 1 and some have 2. * We trust that cpuid_is_k7() will be better at * catching that we're on a K8 anyway. */ if (sc->pn_type != PN8_TYPE) return (EINVAL); sc->vst = psb->settlingtime; sc->rvo = PN8_PSB_TO_RVO(psb->res1), sc->irt = PN8_PSB_TO_IRT(psb->res1), sc->mvs = PN8_PSB_TO_MVS(psb->res1), sc->low = PN8_PSB_TO_BATT(psb->res1); if (bootverbose) { device_printf(dev, "PSB: VST: %d\n", psb->settlingtime); device_printf(dev, "PSB: RVO %x IRT %d " "MVS %d BATT %d\n", sc->rvo, sc->irt, sc->mvs, sc->low); } break; case 0x12: if (sc->pn_type != PN7_TYPE) return (EINVAL); sc->sgtc = psb->settlingtime * sc->fsb; if (sc->sgtc < 100 * sc->fsb) sc->sgtc = 100 * sc->fsb; break; } p = ((uint8_t *) psb) + sizeof(struct psb_header); pst = (struct pst_header*) p; maxpst = 200; do { struct pst_header *pst = (struct pst_header*) p; if (cpuid == pst->cpuid && maxfid == pst->maxfid && startvid == pst->startvid) { sc->powernow_max_states = pst->numpstates; switch (sc->pn_type) { case PN7_TYPE: if (abs(sc->fsb - pst->fsb) > 5) continue; break; case PN8_TYPE: break; } return (decode_pst(sc, p + sizeof(struct pst_header), sc->powernow_max_states)); } p += sizeof(struct pst_header) + (2 * pst->numpstates); } while (cpuid_is_k7(pst->cpuid) && maxpst--); device_printf(dev, "no match for extended cpuid %.3x\n", cpuid); } return (ENODEV); }
void x86bios_set_intr(int intno, uint32_t saddr) { writel(BIOS_PADDRTOVADDR(intno * 4), saddr); }
uint32_t x86bios_get_intr(int intno) { return (readl(BIOS_PADDRTOVADDR(intno * 4))); }
/* * bios32_init * * Locate various bios32 entities. */ static void bios32_init(void *junk) { u_long sigaddr; struct bios32_SDheader *sdh; struct PnPBIOS_table *pt; u_int8_t ck, *cv; int i; char *p; /* * BIOS32 Service Directory, PCI BIOS */ /* look for the signature */ if ((sigaddr = bios_sigsearch(0, "_32_", 4, 16, 0)) != 0) { /* get a virtual pointer to the structure */ sdh = (struct bios32_SDheader *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); for (cv = (u_int8_t *)sdh, ck = 0, i = 0; i < (sdh->len * 16); i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ if ((ck == 0) && (BIOS_START <= sdh->entry ) && (sdh->entry < (BIOS_START + BIOS_SIZE))) { bios32_SDCI = BIOS_PADDRTOVADDR(sdh->entry); if (bootverbose) { printf("bios32: Found BIOS32 Service Directory header at %p\n", sdh); printf("bios32: Entry = 0x%x (%x) Rev = %d Len = %d\n", sdh->entry, bios32_SDCI, sdh->revision, sdh->len); } /* Allow user override of PCI BIOS search */ if (((p = getenv("machdep.bios.pci")) == NULL) || strcmp(p, "disable")) { /* See if there's a PCI BIOS entrypoint here */ PCIbios.ident.id = 0x49435024; /* PCI systems should have this */ if (!bios32_SDlookup(&PCIbios) && bootverbose) printf("pcibios: PCI BIOS entry at 0x%x+0x%x\n", PCIbios.base, PCIbios.entry); } if (p != NULL) freeenv(p); } else { printf("bios32: Bad BIOS32 Service Directory\n"); } } /* * PnP BIOS * * Allow user override of PnP BIOS search */ if ((((p = getenv("machdep.bios.pnp")) == NULL) || strcmp(p, "disable")) && ((sigaddr = bios_sigsearch(0, "$PnP", 4, 16, 0)) != 0)) { /* get a virtual pointer to the structure */ pt = (struct PnPBIOS_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < pt->len; i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ if (ck == 0) { PnPBIOStable = pt; if (bootverbose) { printf("pnpbios: Found PnP BIOS data at %p\n", pt); printf("pnpbios: Entry = %x:%x Rev = %d.%d\n", pt->pmentrybase, pt->pmentryoffset, pt->version >> 4, pt->version & 0xf); if ((pt->control & 0x3) == 0x01) printf("pnpbios: Event flag at %x\n", pt->evflagaddr); if (pt->oemdevid != 0) printf("pnpbios: OEM ID %x\n", pt->oemdevid); } } else {
void isci_get_oem_parameters(struct isci_softc *isci) { uint32_t OROM_PHYSICAL_ADDRESS_START = 0xC0000; uint32_t OROM_SEARCH_LENGTH = 0x30000; uint16_t OROM_SIGNATURE = 0xAA55; uint32_t OROM_SIZE = 512; uint8_t *orom_start = (uint8_t *)BIOS_PADDRTOVADDR(OROM_PHYSICAL_ADDRESS_START); uint32_t offset = 0; while (offset < OROM_SEARCH_LENGTH) { /* Look for the OROM signature at the beginning of every * 512-byte block in the OROM region */ if (*(uint16_t*)(orom_start + offset) == OROM_SIGNATURE) { uint32_t *rom; struct rom_header *rom_header; struct pcir_header *pcir_header; uint16_t vendor_id = isci->pci_common_header.vendor_id; uint16_t device_id = isci->pci_common_header.device_id; rom = (uint32_t *)(orom_start + offset); rom_header = (struct rom_header *)rom; pcir_header = (struct pcir_header *) ((uint8_t*)rom + rom_header->pcir_pointer); /* OROM signature was found. Now check if the PCI * device and vendor IDs match. */ if (pcir_header->vendor_id == vendor_id && pcir_header->device_id == device_id) { /* OROM for this PCI device was found. Search * this 512-byte block for the $OEM string, * which will mark the beginning of the OEM * parameter block. */ uint8_t oem_sig[4] = {'$', 'O', 'E', 'M'}; int dword_index; for (dword_index = 0; dword_index < OROM_SIZE/sizeof(uint32_t); dword_index++) if (rom[dword_index] == *(uint32_t *)oem_sig) { /* $OEM signature string was found. Now copy the OEM parameter block * into the struct ISCI_CONTROLLER objects. After the controllers are * constructed, we will pass this OEM parameter data to the SCI core * controller. */ struct oem_parameters_table *oem = (struct oem_parameters_table *)&rom[dword_index]; SCI_BIOS_OEM_PARAM_BLOCK_T *oem_data = (SCI_BIOS_OEM_PARAM_BLOCK_T *)oem->data; int index; isci->oem_parameters_found = TRUE; isci_log_message(1, "ISCI", "oem_data->header.num_elements = %d\n", oem_data->header.num_elements); for (index = 0; index < oem_data->header.num_elements; index++) { memcpy(&isci->controllers[index].oem_parameters.sds1, &oem_data->controller_element[index], sizeof(SCIC_SDS_OEM_PARAMETERS_T)); isci_log_message(1, "ISCI", "OEM Parameter Data for controller %d\n", index); for (int i = 0; i < sizeof(SCIC_SDS_OEM_PARAMETERS_T); i++) { uint8_t val = ((uint8_t *)&oem_data->controller_element[index])[i]; isci_log_message(1, "ISCI", "%02x ", val); } isci_log_message(1, "ISCI", "\n"); isci->controllers[index].oem_parameters_version = oem_data->header.version; } } /* No need to continue searching for another * OROM that matches this PCI device, so return * immediately. */ return; } } offset += OROM_SIZE; } }
/* * Quiz the PnP BIOS, build a list of PNP IDs and resource data. */ static int pnpbios_identify(driver_t *driver, device_t parent) { struct PnPBIOS_table *pt = PnPBIOStable; struct bios_args args; struct pnp_sysdev *pd; struct pnp_sysdevargs *pda; uint16_t ndevs, bigdev; int error, currdev; uint8_t *devnodebuf, tag; uint32_t *devid, *compid; int idx, left; device_t dev; /* * Umm, we aren't going to rescan the PnP BIOS to look for new additions. */ if (device_get_state(parent) == DS_ATTACHED) return (0); /* no PnP BIOS information */ if (pt == NULL) return (ENXIO); /* ACPI already active */ if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL) return (ENXIO); bzero(&args, sizeof(args)); args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase); args.seg.code16.limit = 0xffff; /* XXX ? */ args.seg.data.base = BIOS_PADDRTOVADDR(pt->pmdataseg); args.seg.data.limit = 0xffff; args.entry = pt->pmentryoffset; if ((error = bios16(&args, PNP_COUNT_DEVNODES, &ndevs, &bigdev)) || (args.r.eax & 0xff)) kprintf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax); ndevs &= 0xff; /* clear high byte garbage */ if (bootverbose) kprintf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev); devnodebuf = kmalloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_INTWAIT); pda = (struct pnp_sysdevargs *)devnodebuf; pd = &pda->node; for (currdev = 0, left = ndevs; (currdev != 0xff) && (left > 0); left--) { bzero(pd, bigdev); pda->next = currdev; /* get current configuration */ if ((error = bios16(&args, PNP_GET_DEVNODE, &pda->next, &pda->node, 1))) { kprintf("pnpbios: error %d making BIOS16 call\n", error); break; } if (bootverbose) kprintf("pnp_get_devnode cd=%d nxt=%d size=%d handle=%d devid=%08x type=%02x%02x%02x, attrib=%04x\n", currdev, pda->next, pd->size, pd->handle, pd->devid, pd->type[0], pd->type[1], pd->type[2], pd->attrib); if ((error = (args.r.eax & 0xff))) { if (bootverbose) kprintf("pnpbios: %s 0x%x fetching node %d\n", error & 0x80 ? "error" : "warning", error, currdev); if (error & 0x80) break; } currdev = pda->next; if (pd->size < sizeof(struct pnp_sysdev)) { kprintf("pnpbios: bogus system node data, aborting scan\n"); break; } /* * Ignore PICs so that we don't have to worry about the PICs * claiming IRQs to prevent their use. The PIC drivers * already ensure that invalid IRQs are not used. */ if (!strcmp(pnp_eisaformat(pd->devid), "PNP0000")) /* ISA PIC */ continue; if (!strcmp(pnp_eisaformat(pd->devid), "PNP0003")) /* APIC */ continue; /* Add the device and parse its resources */ dev = BUS_ADD_CHILD(parent, parent, ISA_ORDER_PNP, NULL, -1); isa_set_vendorid(dev, pd->devid); isa_set_logicalid(dev, pd->devid); /* * It appears that some PnP BIOS doesn't allow us to re-enable * the embedded system device once it is disabled. We shall * mark all system device nodes as "cannot be disabled", regardless * of actual settings in the device attribute byte. XXX */ #if 0 isa_set_configattr(dev, ((pd->attrib & PNPATTR_NODISABLE) ? 0 : ISACFGATTR_CANDISABLE) | ((!(pd->attrib & PNPATTR_NOCONFIG) && PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) ? ISACFGATTR_DYNAMIC : 0)); #endif isa_set_configattr(dev, (!(pd->attrib & PNPATTR_NOCONFIG) && PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) ? ISACFGATTR_DYNAMIC : 0); ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); pnp_parse_resources(dev, &pd->devdata[0], pd->size - sizeof(struct pnp_sysdev), 0); if (!device_get_desc(dev)) device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); /* Find device IDs */ devid = &pd->devid; compid = NULL; /* look for a compatible device ID too */ left = pd->size - sizeof(struct pnp_sysdev); idx = 0; while (idx < left) { tag = pd->devdata[idx++]; if (PNP_RES_TYPE(tag) == 0) { /* Small resource */ switch (PNP_SRES_NUM(tag)) { case PNP_TAG_COMPAT_DEVICE: compid = (uint32_t *)(pd->devdata + idx); if (bootverbose) kprintf("pnpbios: node %d compat ID 0x%08x\n", pd->handle, *compid); /* FALLTHROUGH */ case PNP_TAG_END: idx = left; break; default: idx += PNP_SRES_LEN(tag); break; } } else /* Large resource, skip it */ idx += *(uint16_t *)(pd->devdata + idx) + 2; } if (bootverbose) { kprintf("pnpbios: handle %d device ID %s (%08x)", pd->handle, pnp_eisaformat(*devid), *devid); if (compid != NULL) kprintf(" compat ID %s (%08x)", pnp_eisaformat(*compid), *compid); kprintf("\n"); } } return (0); }