Index: head/stand/i386/libfirewire/firewire.c =================================================================== --- head/stand/i386/libfirewire/firewire.c (revision 327611) +++ head/stand/i386/libfirewire/firewire.c (revision 327612) @@ -1,484 +1,484 @@ /*- * Copyright (c) 2004 Hidetoshi Shimokawa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * FireWire disk device handling. * */ #include #include #include #include #include #include #include "fwohci.h" #include /* XXX */ #define BIT4x2(x,y) uint8_t y:4, x:4 #define BIT16x2(x,y) uint32_t y:16, x:16 #define _KERNEL #include extern uint32_t dcons_paddr; extern struct console dconsole; struct crom_src_buf { struct crom_src src; struct crom_chunk root; struct crom_chunk vendor; struct crom_chunk hw; /* for dcons */ struct crom_chunk unit; struct crom_chunk spec; struct crom_chunk ver; }; static int fw_init(void); static int fw_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize); static int fw_open(struct open_file *f, ...); static int fw_close(struct open_file *f); static int fw_print(int verbose); static void fw_cleanup(void); void fw_enable(void); struct devsw fwohci = { "FW1394", /* 7 chars at most */ DEVT_NET, fw_init, fw_strategy, fw_open, fw_close, noioctl, fw_print, fw_cleanup }; static struct fwohci_softc fwinfo[MAX_OHCI]; static int fw_initialized = 0; static void fw_probe(int index, struct fwohci_softc *sc) { int err; sc->state = FWOHCI_STATE_INIT; err = biospci_find_devclass( 0x0c0010 /* Serial:FireWire:OHCI */, index /* index */, &sc->locator); if (err != 0) { sc->state = FWOHCI_STATE_DEAD; return; } biospci_write_config(sc->locator, 0x4 /* command */, 0x6 /* enable bus master and memory mapped I/O */, - 1 /* word */); + BIOSPCI_16BITS); - biospci_read_config(sc->locator, 0x00 /*devid*/, 2 /*dword*/, + biospci_read_config(sc->locator, 0x00 /*devid*/, BIOSPCI_32BITS, &sc->devid); - biospci_read_config(sc->locator, 0x10 /*base_addr*/, 2 /*dword*/, + biospci_read_config(sc->locator, 0x10 /*base_addr*/, BIOSPCI_32BITS, &sc->base_addr); sc->handle = (uint32_t)PTOV(sc->base_addr); sc->bus_id = OREAD(sc, OHCI_BUS_ID); return; } static int fw_init(void) { int i, avail; struct fwohci_softc *sc; if (fw_initialized) return (0); avail = 0; for (i = 0; i < MAX_OHCI; i ++) { sc = &fwinfo[i]; fw_probe(i, sc); if (sc->state == FWOHCI_STATE_DEAD) break; avail ++; break; } fw_initialized = 1; return (0); } /* * Print information about OHCI chips */ static int fw_print(int verbose) { char line[80]; int i, ret = 0; struct fwohci_softc *sc; printf("%s devices:", fwohci.dv_name); if ((ret = pager_output("\n")) != 0) return (ret); for (i = 0; i < MAX_OHCI; i ++) { sc = &fwinfo[i]; if (sc->state == FWOHCI_STATE_DEAD) break; snprintf(line, sizeof(line), "%d: locator=0x%04x devid=0x%08x" " base_addr=0x%08x handle=0x%08x bus_id=0x%08x\n", i, sc->locator, sc->devid, sc->base_addr, sc->handle, sc->bus_id); ret = pager_output(line); if (ret != 0) break; } return (ret); } static int fw_open(struct open_file *f, ...) { #if 0 va_list ap; struct i386_devdesc *dev; struct open_disk *od; int error; va_start(ap, f); dev = va_arg(ap, struct i386_devdesc *); va_end(ap); #endif return (ENXIO); } static int fw_close(struct open_file *f) { return (0); } static void fw_cleanup() { struct dcons_buf *db; /* invalidate dcons buffer */ if (dcons_paddr) { db = (struct dcons_buf *)PTOV(dcons_paddr); db->magic = 0; } } static int fw_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { return (EIO); } static void fw_init_crom(struct fwohci_softc *sc) { struct crom_src *src; printf("fw_init_crom\n"); sc->crom_src_buf = (struct crom_src_buf *) malloc(sizeof(struct crom_src_buf)); if (sc->crom_src_buf == NULL) return; src = &sc->crom_src_buf->src; bzero(src, sizeof(struct crom_src)); /* BUS info sample */ src->hdr.info_len = 4; src->businfo.bus_name = CSR_BUS_NAME_IEEE1394; src->businfo.irmc = 1; src->businfo.cmc = 1; src->businfo.isc = 1; src->businfo.bmc = 1; src->businfo.pmc = 0; src->businfo.cyc_clk_acc = 100; src->businfo.max_rec = sc->maxrec; src->businfo.max_rom = MAXROM_4; #define FW_GENERATION_CHANGEABLE 2 src->businfo.generation = FW_GENERATION_CHANGEABLE; src->businfo.link_spd = sc->speed; src->businfo.eui64.hi = sc->eui.hi; src->businfo.eui64.lo = sc->eui.lo; STAILQ_INIT(&src->chunk_list); sc->crom_src = src; sc->crom_root = &sc->crom_src_buf->root; } static void fw_reset_crom(struct fwohci_softc *sc) { struct crom_src_buf *buf; struct crom_src *src; struct crom_chunk *root; printf("fw_reset\n"); if (sc->crom_src_buf == NULL) fw_init_crom(sc); buf = sc->crom_src_buf; src = sc->crom_src; root = sc->crom_root; STAILQ_INIT(&src->chunk_list); bzero(root, sizeof(struct crom_chunk)); crom_add_chunk(src, NULL, root, 0); crom_add_entry(root, CSRKEY_NCAP, 0x0083c0); /* XXX */ /* private company_id */ crom_add_entry(root, CSRKEY_VENDOR, CSRVAL_VENDOR_PRIVATE); #ifdef __DragonFly__ crom_add_simple_text(src, root, &buf->vendor, "DragonFly Project"); #else crom_add_simple_text(src, root, &buf->vendor, "FreeBSD Project"); #endif } #define ADDR_HI(x) (((x) >> 24) & 0xffffff) #define ADDR_LO(x) ((x) & 0xffffff) static void dcons_crom(struct fwohci_softc *sc) { struct crom_src_buf *buf; struct crom_src *src; struct crom_chunk *root; buf = sc->crom_src_buf; src = sc->crom_src; root = sc->crom_root; bzero(&buf->unit, sizeof(struct crom_chunk)); crom_add_chunk(src, root, &buf->unit, CROM_UDIR); crom_add_entry(&buf->unit, CSRKEY_SPEC, CSRVAL_VENDOR_PRIVATE); crom_add_simple_text(src, &buf->unit, &buf->spec, "FreeBSD"); crom_add_entry(&buf->unit, CSRKEY_VER, DCONS_CSR_VAL_VER); crom_add_simple_text(src, &buf->unit, &buf->ver, "dcons"); crom_add_entry(&buf->unit, DCONS_CSR_KEY_HI, ADDR_HI(dcons_paddr)); crom_add_entry(&buf->unit, DCONS_CSR_KEY_LO, ADDR_LO(dcons_paddr)); } void fw_crom(struct fwohci_softc *sc) { struct crom_src *src; void *newrom; fw_reset_crom(sc); dcons_crom(sc); newrom = malloc(CROMSIZE); src = &sc->crom_src_buf->src; crom_load(src, (uint32_t *)newrom, CROMSIZE); if (bcmp(newrom, sc->config_rom, CROMSIZE) != 0) { /* Bump generation and reload. */ src->businfo.generation++; /* Handle generation count wraps. */ if (src->businfo.generation < 2) src->businfo.generation = 2; /* Recalculate CRC to account for generation change. */ crom_load(src, (uint32_t *)newrom, CROMSIZE); bcopy(newrom, (void *)sc->config_rom, CROMSIZE); } free(newrom); } static int fw_busreset(struct fwohci_softc *sc) { int count; if (sc->state < FWOHCI_STATE_ENABLED) { printf("fwohci not enabled\n"); return(CMD_OK); } fw_crom(sc); fwohci_ibr(sc); count = 0; while (sc->state< FWOHCI_STATE_NORMAL) { fwohci_poll(sc); count ++; if (count > 1000) { printf("give up to wait bus initialize\n"); return (-1); } } printf("poll count = %d\n", count); return (0); } void fw_enable(void) { struct fwohci_softc *sc; int i; if (fw_initialized == 0) fw_init(); for (i = 0; i < MAX_OHCI; i ++) { sc = &fwinfo[i]; if (sc->state != FWOHCI_STATE_INIT) break; sc->config_rom = (uint32_t *) (((uint32_t)sc->config_rom_buf + (CROMSIZE - 1)) & ~(CROMSIZE - 1)); #if 0 printf("configrom: %08p %08p\n", sc->config_rom_buf, sc->config_rom); #endif if (fwohci_init(sc, 0) == 0) { sc->state = FWOHCI_STATE_ENABLED; fw_busreset(sc); } else sc->state = FWOHCI_STATE_DEAD; } } void fw_poll(void) { struct fwohci_softc *sc; int i; if (fw_initialized == 0) return; for (i = 0; i < MAX_OHCI; i ++) { sc = &fwinfo[i]; if (sc->state < FWOHCI_STATE_ENABLED) break; fwohci_poll(sc); } } #if 0 /* for debug */ static int fw_busreset_cmd(int argc, char *argv[]) { struct fwohci_softc *sc; int i; for (i = 0; i < MAX_OHCI; i ++) { sc = &fwinfo[i]; if (sc->state < FWOHCI_STATE_INIT) break; fw_busreset(sc); } return(CMD_OK); } static int fw_poll_cmd(int argc, char *argv[]) { fw_poll(); return(CMD_OK); } static int fw_enable_cmd(int argc, char *argv[]) { fw_print(0); fw_enable(); return(CMD_OK); } static int dcons_enable(int argc, char *argv[]) { dconsole.c_init(0); fw_enable(); dconsole.c_flags |= C_ACTIVEIN | C_ACTIVEOUT; return(CMD_OK); } static int dcons_read(int argc, char *argv[]) { char c; while (dconsole.c_ready()) { c = dconsole.c_in(); printf("%c", c); } printf("\r\n"); return(CMD_OK); } static int dcons_write(int argc, char *argv[]) { int len, i; if (argc < 2) return(CMD_OK); len = strlen(argv[1]); for (i = 0; i < len; i ++) dconsole.c_out(argv[1][i]); dconsole.c_out('\r'); dconsole.c_out('\n'); return(CMD_OK); } COMMAND_SET(firewire, "firewire", "enable firewire", fw_enable_cmd); COMMAND_SET(fwbusreset, "fwbusreset", "firewire busreset", fw_busreset_cmd); COMMAND_SET(fwpoll, "fwpoll", "firewire poll", fw_poll_cmd); COMMAND_SET(dcons, "dcons", "enable dcons", dcons_enable); COMMAND_SET(dread, "dread", "read from dcons", dcons_read); COMMAND_SET(dwrite, "dwrite", "write to dcons", dcons_write); #endif Index: head/stand/i386/libi386/biospci.c =================================================================== --- head/stand/i386/libi386/biospci.c (revision 327611) +++ head/stand/i386/libi386/biospci.c (revision 327612) @@ -1,588 +1,588 @@ /*- * Copyright (c) 1998 Michael Smith * Copyright (c) 2016 Netflix, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * PnP enumerator using the PCI BIOS. */ #include #include #include #include #include #include "libi386.h" #ifdef BOOT_FORTH #include "ficl.h" #endif /* * Stupid PCI BIOS interface doesn't let you simply enumerate everything * that's there, instead you have to ask it if it has something. * * So we have to scan by class code, subclass code and sometimes programming * interface. */ struct pci_progif { int pi_code; const char *pi_name; }; static struct pci_progif progif_null[] = { {0x0, NULL}, {-1, NULL} }; static struct pci_progif progif_display[] = { {0x0, "VGA"}, {0x1, "8514"}, {-1, NULL} }; static struct pci_progif progif_ide[] = { {0x00, NULL}, {0x01, NULL}, {0x02, NULL}, {0x03, NULL}, {0x04, NULL}, {0x05, NULL}, {0x06, NULL}, {0x07, NULL}, {0x08, NULL}, {0x09, NULL}, {0x0a, NULL}, {0x0b, NULL}, {0x0c, NULL}, {0x0d, NULL}, {0x0e, NULL}, {0x0f, NULL}, {0x80, NULL}, {0x81, NULL}, {0x82, NULL}, {0x83, NULL}, {0x84, NULL}, {0x85, NULL}, {0x86, NULL}, {0x87, NULL}, {0x88, NULL}, {0x89, NULL}, {0x8a, NULL}, {0x8b, NULL}, {0x8c, NULL}, {0x8d, NULL}, {0x8e, NULL}, {0x8f, NULL}, {-1, NULL} }; static struct pci_progif progif_serial[] = { {0x0, "8250"}, {0x1, "16450"}, {0x2, "16550"}, {-1, NULL} }; static struct pci_progif progif_parallel[] = { {0x0, "Standard"}, {0x1, "Bidirectional"}, {0x2, "ECP"}, {-1, NULL} }; static struct pci_progif progif_firewire[] = { {0x10, "OHCI"}, {-1, NULL} }; struct pci_subclass { int ps_subclass; const char *ps_name; struct pci_progif *ps_progif; /* if set, use for programming interface value(s) */ }; static struct pci_subclass subclass_old[] = { {0x0, "Old non-VGA", progif_null}, {0x1, "Old VGA", progif_null}, {-1, NULL, NULL} }; static struct pci_subclass subclass_mass[] = { {0x0, "SCSI", progif_null}, {0x1, "IDE", progif_ide}, {0x2, "Floppy disk", progif_null}, {0x3, "IPI", progif_null}, {0x4, "RAID", progif_null}, {0x80, "mass storage", progif_null}, {-1, NULL, NULL} }; static struct pci_subclass subclass_net[] = { {0x0, "Ethernet", progif_null}, {0x1, "Token ring", progif_null}, {0x2, "FDDI", progif_null}, {0x3, "ATM", progif_null}, {0x80, "network", progif_null}, {-1, NULL, NULL} }; static struct pci_subclass subclass_display[] = { {0x0, NULL, progif_display}, {0x1, "XGA", progif_null}, {0x80, "other", progif_null}, {-1, NULL, NULL} }; static struct pci_subclass subclass_comms[] = { {0x0, "serial", progif_serial}, {0x1, "parallel", progif_parallel}, {0x80, "communications", progif_null}, {-1, NULL, NULL} }; static struct pci_subclass subclass_serial[] = { {0x0, "FireWire", progif_firewire}, {0x1, "ACCESS.bus", progif_null}, {0x2, "SSA", progif_null}, {0x3, "USB", progif_null}, {0x4, "Fibrechannel", progif_null}, {-1, NULL, NULL} }; static struct pci_class { int pc_class; const char *pc_name; struct pci_subclass *pc_subclass; } pci_classes[] = { {0x0, "device", subclass_old}, {0x1, "controller", subclass_mass}, {0x2, "controller", subclass_net}, {0x3, "display", subclass_display}, {0x7, "controller", subclass_comms}, {0xc, "controller", subclass_serial}, {-1, NULL, NULL} }; static void biospci_enumerate(void); static void biospci_addinfo(int devid, struct pci_class *pc, struct pci_subclass *psc, struct pci_progif *ppi); struct pnphandler biospcihandler = { "PCI BIOS", biospci_enumerate }; static int biospci_version; #define PCI_BIOS_PRESENT 0xb101 #define FIND_PCI_DEVICE 0xb102 #define FIND_PCI_CLASS_CODE 0xb103 #define GENERATE_SPECIAL_CYCLE 0xb106 #define READ_CONFIG_BYTE 0xb108 #define READ_CONFIG_WORD 0xb109 #define READ_CONFIG_DWORD 0xb10a #define WRITE_CONFIG_BYTE 0xb10b #define WRITE_CONFIG_WORD 0xb10c #define WRITE_CONFIG_DWORD 0xb10d #define GET_IRQ_ROUTING_OPTIONS 0xb10e #define SET_PCI_IRQ 0xb10f #define PCI_INT 0x1a #define PCI_SIGNATURE 0x20494350 /* AKA "PCI " */ void biospci_detect(void) { uint16_t version, hwcap, maxbus; char buf[24]; /* Find the PCI BIOS */ v86.ctl = V86_FLAGS; v86.addr = PCI_INT; v86.eax = PCI_BIOS_PRESENT; v86.edi = 0x0; v86int(); /* Check for OK response */ if (V86_CY(v86.efl) || ((v86.eax & 0xff00) != 0) || (v86.edx != PCI_SIGNATURE)) return; version = v86.ebx & 0xffff; hwcap = v86.eax & 0xff; maxbus = v86.ecx & 0xff; #if 0 printf("PCI BIOS %d.%d%s%s maxbus %d\n", bcd2bin((version >> 8) & 0xf), bcd2bin(version & 0xf), (hwcap & 1) ? " config1" : "", (hwcap & 2) ? " config2" : "", maxbus); #endif sprintf(buf, "%d", bcd2bin((version >> 8) & 0xf)); setenv("pcibios.major", buf, 1); sprintf(buf, "%d", bcd2bin(version & 0xf)); setenv("pcibios.minor", buf, 1); sprintf(buf, "%d", !!(hwcap & 1)); setenv("pcibios.config1", buf, 1); sprintf(buf, "%d", !!(hwcap & 2)); setenv("pcibios.config2", buf, 1); sprintf(buf, "%d", maxbus); setenv("pcibios.maxbus", buf, 1); biospci_version = bcd2bin((version >> 8) & 0xf) * 10 + bcd2bin(version & 0xf); } static void biospci_enumerate(void) { int device_index, err; uint32_t locator, devid; struct pci_class *pc; struct pci_subclass *psc; struct pci_progif *ppi; /* Iterate over known classes */ for (pc = pci_classes; pc->pc_class >= 0; pc++) { /* Iterate over subclasses */ for (psc = pc->pc_subclass; psc->ps_subclass >= 0; psc++) { /* Iterate over programming interfaces */ for (ppi = psc->ps_progif; ppi->pi_code >= 0; ppi++) { /* Scan for matches */ for (device_index = 0; ; device_index++) { /* Look for a match */ err = biospci_find_devclass((pc->pc_class << 16) + (psc->ps_subclass << 8) + ppi->pi_code, device_index, &locator); if (err != 0) break; /* Read the device identifier from the nominated device */ - err = biospci_read_config(locator, 0, 2, &devid); + err = biospci_read_config(locator, 0, BIOSPCI_32BITS, &devid); if (err != 0) break; /* We have the device ID, create a PnP object and save everything */ biospci_addinfo(devid, pc, psc, ppi); } } } } } static void biospci_addinfo(int devid, struct pci_class *pc, struct pci_subclass *psc, struct pci_progif *ppi) { struct pnpinfo *pi; char desc[80]; /* build the description */ desc[0] = 0; if (ppi->pi_name != NULL) { strcat(desc, ppi->pi_name); strcat(desc, " "); } if (psc->ps_name != NULL) { strcat(desc, psc->ps_name); strcat(desc, " "); } if (pc->pc_name != NULL) strcat(desc, pc->pc_name); pi = pnp_allocinfo(); pi->pi_desc = strdup(desc); sprintf(desc,"0x%08x", devid); pnp_addident(pi, desc); pnp_addinfo(pi); } int biospci_find_devclass(uint32_t class, int index, uint32_t *locator) { v86.ctl = V86_FLAGS; v86.addr = PCI_INT; v86.eax = FIND_PCI_CLASS_CODE; v86.ecx = class; v86.esi = index; v86int(); /* error */ if (V86_CY(v86.efl) || (v86.eax & 0xff00)) return (-1); *locator = v86.ebx; return (0); } static int biospci_find_device(uint32_t devid, int index, uint32_t *locator) { v86.ctl = V86_FLAGS; v86.addr = PCI_INT; v86.eax = FIND_PCI_DEVICE; v86.edx = devid & 0xffff; /* EDX - Vendor ID */ v86.ecx = (devid >> 16) & 0xffff; /* ECX - Device ID */ v86.esi = index; v86int(); /* error */ if (V86_CY(v86.efl) || (v86.eax & 0xff00)) return (-1); *locator = v86.ebx; return (0); } /* * Configuration space access methods. * width = 0(byte), 1(word) or 2(dword). */ int biospci_write_config(uint32_t locator, int offset, int width, uint32_t val) { v86.ctl = V86_FLAGS; v86.addr = PCI_INT; v86.eax = WRITE_CONFIG_BYTE + width; v86.ebx = locator; v86.edi = offset; v86.ecx = val; v86int(); /* error */ if (V86_CY(v86.efl) || (v86.eax & 0xff00)) return (-1); return(0); } int biospci_read_config(uint32_t locator, int offset, int width, uint32_t *val) { v86.ctl = V86_FLAGS; v86.addr = PCI_INT; v86.eax = READ_CONFIG_BYTE + width; v86.ebx = locator; v86.edi = offset; v86int(); /* error */ if (V86_CY(v86.efl) || (v86.eax & 0xff00)) return (-1); *val = v86.ecx; return (0); } uint32_t biospci_locator(int8_t bus, uint8_t device, uint8_t function) { return ((bus << 8) | ((device & 0x1f) << 3) | (function & 0x7)); } /* * Counts the number of instances of devid we have in the system, as least as * far as the PCI BIOS is able to tell. */ static int biospci_count_device_type(uint32_t devid) { int i; for (i = 0; 1; i++) { v86.ctl = V86_FLAGS; v86.addr = PCI_INT; v86.eax = FIND_PCI_DEVICE; v86.edx = devid & 0xffff; /* EDX - Vendor ID */ v86.ecx = (devid >> 16) & 0xffff; /* ECX - Device ID */ v86.esi = i; v86int(); if (V86_CY(v86.efl) || (v86.eax & 0xff00)) break; } return i; } #ifdef BOOT_FORTH /* * pcibios-device-count (devid -- count) * * Returns the PCI BIOS' count of how many devices matching devid are in the system. * devid is the 32-bit vendor + device. */ static void ficlPciBiosCountDevices(FICL_VM *pVM) { uint32_t devid; int i; devid = stackPopINT(pVM->pStack); i = biospci_count_device_type(devid); stackPushINT(pVM->pStack, i); } /* * pcibios-write-config (locator offset width value -- ) * * Writes the specified config register. * Locator is bus << 8 | device << 3 | fuction * offset is the pci config register * width is 0 for byte, 1 for word, 2 for dword * value is the value to write */ static void ficlPciBiosWriteConfig(FICL_VM *pVM) { uint32_t value, width, offset, locator; value = stackPopINT(pVM->pStack); width = stackPopINT(pVM->pStack); offset = stackPopINT(pVM->pStack); locator = stackPopINT(pVM->pStack); biospci_write_config(locator, offset, width, value); } /* * pcibios-read-config (locator offset width -- value) * * Reads the specified config register. * Locator is bus << 8 | device << 3 | fuction * offset is the pci config register * width is 0 for byte, 1 for word, 2 for dword * value is the value to read from the register */ static void ficlPciBiosReadConfig(FICL_VM *pVM) { uint32_t value, width, offset, locator; width = stackPopINT(pVM->pStack); offset = stackPopINT(pVM->pStack); locator = stackPopINT(pVM->pStack); biospci_read_config(locator, offset, width, &value); stackPushINT(pVM->pStack, value); } /* * pcibios-find-devclass (class index -- locator) * * Finds the index'th instance of class in the pci tree. * must be an exact match. * class is the class to search for. * index 0..N (set to 0, increment until error) * * Locator is bus << 8 | device << 3 | fuction (or -1 on error) */ static void ficlPciBiosFindDevclass(FICL_VM *pVM) { uint32_t index, class, locator; index = stackPopINT(pVM->pStack); class = stackPopINT(pVM->pStack); if (biospci_find_devclass(class, index, &locator)) locator = 0xffffffff; stackPushINT(pVM->pStack, locator); } /* * pcibios-find-device(devid index -- locator) * * Finds the index'th instance of devid in the pci tree. * must be an exact match. * class is the class to search for. * index 0..N (set to 0, increment until error) * * Locator is bus << 8 | device << 3 | fuction (or -1 on error) */ static void ficlPciBiosFindDevice(FICL_VM *pVM) { uint32_t index, devid, locator; index = stackPopINT(pVM->pStack); devid = stackPopINT(pVM->pStack); if (biospci_find_device(devid, index, &locator)) locator = 0xffffffff; stackPushINT(pVM->pStack, locator); } /* * pcibios-find-device(bus device function -- locator) * * converts bus, device, function to locator. * * Locator is bus << 8 | device << 3 | fuction */ static void ficlPciBiosLocator(FICL_VM *pVM) { uint32_t bus, device, function, locator; function = stackPopINT(pVM->pStack); device = stackPopINT(pVM->pStack); bus = stackPopINT(pVM->pStack); locator = biospci_locator(bus, device, function); stackPushINT(pVM->pStack, locator); } /* * Glue function to add the appropriate forth words to access pci bios * functionality. */ static void ficlCompilePciBios(FICL_SYSTEM *pSys) { FICL_DICT *dp = pSys->dp; assert (dp); dictAppendWord(dp, "pcibios-device-count", ficlPciBiosCountDevices, FW_DEFAULT); dictAppendWord(dp, "pcibios-read-config", ficlPciBiosReadConfig, FW_DEFAULT); dictAppendWord(dp, "pcibios-write-config", ficlPciBiosWriteConfig, FW_DEFAULT); dictAppendWord(dp, "pcibios-find-devclass", ficlPciBiosFindDevclass, FW_DEFAULT); dictAppendWord(dp, "pcibios-find-device", ficlPciBiosFindDevice, FW_DEFAULT); dictAppendWord(dp, "pcibios-locator", ficlPciBiosLocator, FW_DEFAULT); ficlSetEnv(pSys, "pcibios-version", biospci_version); } FICL_COMPILE_SET(ficlCompilePciBios); #endif Index: head/stand/i386/libi386/comconsole.c =================================================================== --- head/stand/i386/libi386/comconsole.c (revision 327611) +++ head/stand/i386/libi386/comconsole.c (revision 327612) @@ -1,385 +1,385 @@ /*- * Copyright (c) 1998 Michael Smith (msmith@freebsd.org) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include "libi386.h" #define COMC_FMT 0x3 /* 8N1 */ #define COMC_TXWAIT 0x40000 /* transmit timeout */ #define COMC_BPS(x) (115200 / (x)) /* speed to DLAB divisor */ #define COMC_DIV2BPS(x) (115200 / (x)) /* DLAB divisor to speed */ #ifndef COMPORT #define COMPORT 0x3f8 #endif #ifndef COMSPEED #define COMSPEED 9600 #endif static void comc_probe(struct console *cp); static int comc_init(int arg); static void comc_putchar(int c); static int comc_getchar(void); static int comc_getspeed(void); static int comc_ischar(void); static int comc_parseint(const char *string); static uint32_t comc_parse_pcidev(const char *string); static int comc_pcidev_set(struct env_var *ev, int flags, const void *value); static int comc_pcidev_handle(uint32_t locator); static int comc_port_set(struct env_var *ev, int flags, const void *value); static void comc_setup(int speed, int port); static int comc_speed_set(struct env_var *ev, int flags, const void *value); static int comc_curspeed; static int comc_port = COMPORT; static uint32_t comc_locator; struct console comconsole = { "comconsole", "serial port", 0, comc_probe, comc_init, comc_putchar, comc_getchar, comc_ischar }; static void comc_probe(struct console *cp) { char intbuf[16]; char *cons, *env; int speed, port; uint32_t locator; if (comc_curspeed == 0) { comc_curspeed = COMSPEED; /* * Assume that the speed was set by an earlier boot loader if * comconsole is already the preferred console. */ cons = getenv("console"); if ((cons != NULL && strcmp(cons, comconsole.c_name) == 0) || getenv("boot_multicons") != NULL) { comc_curspeed = comc_getspeed(); } env = getenv("comconsole_speed"); if (env != NULL) { speed = comc_parseint(env); if (speed > 0) comc_curspeed = speed; } sprintf(intbuf, "%d", comc_curspeed); unsetenv("comconsole_speed"); env_setenv("comconsole_speed", EV_VOLATILE, intbuf, comc_speed_set, env_nounset); env = getenv("comconsole_port"); if (env != NULL) { port = comc_parseint(env); if (port > 0) comc_port = port; } sprintf(intbuf, "%d", comc_port); unsetenv("comconsole_port"); env_setenv("comconsole_port", EV_VOLATILE, intbuf, comc_port_set, env_nounset); env = getenv("comconsole_pcidev"); if (env != NULL) { locator = comc_parse_pcidev(env); if (locator != 0) comc_pcidev_handle(locator); } unsetenv("comconsole_pcidev"); env_setenv("comconsole_pcidev", EV_VOLATILE, env, comc_pcidev_set, env_nounset); } comc_setup(comc_curspeed, comc_port); } static int comc_init(int arg) { comc_setup(comc_curspeed, comc_port); if ((comconsole.c_flags & (C_PRESENTIN | C_PRESENTOUT)) == (C_PRESENTIN | C_PRESENTOUT)) return (CMD_OK); return (CMD_ERROR); } static void comc_putchar(int c) { int wait; for (wait = COMC_TXWAIT; wait > 0; wait--) if (inb(comc_port + com_lsr) & LSR_TXRDY) { outb(comc_port + com_data, (u_char)c); break; } } static int comc_getchar(void) { return (comc_ischar() ? inb(comc_port + com_data) : -1); } static int comc_ischar(void) { return (inb(comc_port + com_lsr) & LSR_RXRDY); } static int comc_speed_set(struct env_var *ev, int flags, const void *value) { int speed; if (value == NULL || (speed = comc_parseint(value)) <= 0) { printf("Invalid speed\n"); return (CMD_ERROR); } if (comc_curspeed != speed) comc_setup(speed, comc_port); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return (CMD_OK); } static int comc_port_set(struct env_var *ev, int flags, const void *value) { int port; if (value == NULL || (port = comc_parseint(value)) <= 0) { printf("Invalid port\n"); return (CMD_ERROR); } if (comc_port != port) comc_setup(comc_curspeed, port); env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return (CMD_OK); } /* * Input: bus:dev:func[:bar]. If bar is not specified, it is 0x10. * Output: bar[24:16] bus[15:8] dev[7:3] func[2:0] */ static uint32_t comc_parse_pcidev(const char *string) { #ifdef NO_PCI return (0); #else char *p, *p1; uint8_t bus, dev, func, bar; uint32_t locator; int pres; pres = strtol(string, &p, 0); if (p == string || *p != ':' || pres < 0 ) return (0); bus = pres; p1 = ++p; pres = strtol(p1, &p, 0); if (p == string || *p != ':' || pres < 0 ) return (0); dev = pres; p1 = ++p; pres = strtol(p1, &p, 0); if (p == string || (*p != ':' && *p != '\0') || pres < 0 ) return (0); func = pres; if (*p == ':') { p1 = ++p; pres = strtol(p1, &p, 0); if (p == string || *p != '\0' || pres <= 0 ) return (0); bar = pres; } else bar = 0x10; locator = (bar << 16) | biospci_locator(bus, dev, func); return (locator); #endif } static int comc_pcidev_handle(uint32_t locator) { #ifdef NO_PCI return (CMD_ERROR); #else char intbuf[64]; uint32_t port; if (biospci_read_config(locator & 0xffff, - (locator & 0xff0000) >> 16, 2, &port) == -1) { + (locator & 0xff0000) >> 16, BIOSPCI_32BITS, &port) == -1) { printf("Cannot read bar at 0x%x\n", locator); return (CMD_ERROR); } /* * biospci_read_config() sets port == 0xffffffff if the pcidev * isn't found on the bus. Check for 0xffffffff and return to not * panic in BTX. */ if (port == 0xffffffff) { printf("Cannot find specified pcidev\n"); return (CMD_ERROR); } if (!PCI_BAR_IO(port)) { printf("Memory bar at 0x%x\n", locator); return (CMD_ERROR); } port &= PCIM_BAR_IO_BASE; sprintf(intbuf, "%d", port); unsetenv("comconsole_port"); env_setenv("comconsole_port", EV_VOLATILE, intbuf, comc_port_set, env_nounset); comc_setup(comc_curspeed, port); comc_locator = locator; return (CMD_OK); #endif } static int comc_pcidev_set(struct env_var *ev, int flags, const void *value) { uint32_t locator; int error; if (value == NULL || (locator = comc_parse_pcidev(value)) <= 0) { printf("Invalid pcidev\n"); return (CMD_ERROR); } if ((comconsole.c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) != 0 && comc_locator != locator) { error = comc_pcidev_handle(locator); if (error != CMD_OK) return (error); } env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); return (CMD_OK); } static void comc_setup(int speed, int port) { static int TRY_COUNT = 1000000; char intbuf[64]; int tries; unsetenv("hw.uart.console"); comc_curspeed = speed; comc_port = port; if ((comconsole.c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) == 0) return; outb(comc_port + com_cfcr, CFCR_DLAB | COMC_FMT); outb(comc_port + com_dlbl, COMC_BPS(speed) & 0xff); outb(comc_port + com_dlbh, COMC_BPS(speed) >> 8); outb(comc_port + com_cfcr, COMC_FMT); outb(comc_port + com_mcr, MCR_RTS | MCR_DTR); tries = 0; do inb(comc_port + com_data); while (inb(comc_port + com_lsr) & LSR_RXRDY && ++tries < TRY_COUNT); if (tries < TRY_COUNT) { comconsole.c_flags |= (C_PRESENTIN | C_PRESENTOUT); sprintf(intbuf, "io:%d,br:%d", comc_port, comc_curspeed); env_setenv("hw.uart.console", EV_VOLATILE, intbuf, NULL, NULL); } else comconsole.c_flags &= ~(C_PRESENTIN | C_PRESENTOUT); } static int comc_parseint(const char *speedstr) { char *p; int speed; speed = strtol(speedstr, &p, 0); if (p == speedstr || *p != '\0' || speed <= 0) return (-1); return (speed); } static int comc_getspeed(void) { u_int divisor; u_char dlbh; u_char dlbl; u_char cfcr; cfcr = inb(comc_port + com_cfcr); outb(comc_port + com_cfcr, CFCR_DLAB | cfcr); dlbl = inb(comc_port + com_dlbl); dlbh = inb(comc_port + com_dlbh); outb(comc_port + com_cfcr, cfcr); divisor = dlbh << 8 | dlbl; /* XXX there should be more sanity checking. */ if (divisor == 0) return (COMSPEED); return (COMC_DIV2BPS(divisor)); } Index: head/stand/i386/libi386/libi386.h =================================================================== --- head/stand/i386/libi386/libi386.h (revision 327611) +++ head/stand/i386/libi386/libi386.h (revision 327612) @@ -1,156 +1,163 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * i386 fully-qualified device descriptor. * Note, this must match the 'struct devdesc' declaration * in bootstrap.h and also with struct zfs_devdesc for zfs * support. */ struct i386_devdesc { struct devsw *d_dev; int d_type; int d_unit; union { struct { void *data; int slice; int partition; off_t offset; } biosdisk; struct { void *data; } bioscd; struct { void *data; uint64_t pool_guid; uint64_t root_guid; } zfs; } d_kind; }; /* * relocater trampoline support. */ struct relocate_data { uint32_t src; uint32_t dest; uint32_t size; }; extern void relocater(void); /* * The relocater_data[] is fixed size array allocated in relocater_tramp.S */ extern struct relocate_data relocater_data[]; extern uint32_t relocater_size; extern uint16_t relocator_ip; extern uint16_t relocator_cs; extern uint16_t relocator_ds; extern uint16_t relocator_es; extern uint16_t relocator_fs; extern uint16_t relocator_gs; extern uint16_t relocator_ss; extern uint16_t relocator_sp; extern uint32_t relocator_esi; extern uint32_t relocator_eax; extern uint32_t relocator_ebx; extern uint32_t relocator_edx; extern uint32_t relocator_ebp; extern uint16_t relocator_a20_enabled; int i386_getdev(void **vdev, const char *devspec, const char **path); char *i386_fmtdev(void *vdev); int i386_setcurrdev(struct env_var *ev, int flags, const void *value); extern struct devdesc currdev; /* our current device */ #define MAXDEV 31 /* maximum number of distinct devices */ #define MAXBDDEV MAXDEV /* exported devices XXX rename? */ extern struct devsw bioscd; extern struct devsw biosdisk; extern struct devsw pxedisk; extern struct fs_ops pxe_fsops; int bc_add(int biosdev); /* Register CD booted from. */ int bc_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */ int bc_bios2unit(int biosdev); /* xlate BIOS device -> bioscd unit */ int bc_unit2bios(int unit); /* xlate bioscd unit -> BIOS device */ uint32_t bd_getbigeom(int bunit); /* return geometry in bootinfo format */ int bd_bios2unit(int biosdev); /* xlate BIOS device -> biosdisk unit */ int bd_unit2bios(int unit); /* xlate biosdisk unit -> BIOS device */ int bd_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */ ssize_t i386_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t i386_copyout(const vm_offset_t src, void *dest, const size_t len); ssize_t i386_readin(const int fd, vm_offset_t dest, const size_t len); struct preloaded_file; void bios_addsmapdata(struct preloaded_file *); void bios_getsmap(void); void bios_getmem(void); extern uint32_t bios_basemem; /* base memory in bytes */ extern uint32_t bios_extmem; /* extended memory in bytes */ extern vm_offset_t memtop; /* last address of physical memory + 1 */ extern vm_offset_t memtop_copyin; /* memtop less heap size for the cases */ /* when heap is at the top of */ /* extended memory; for other cases */ /* just the same as memtop */ extern uint32_t high_heap_size; /* extended memory region available */ extern vm_offset_t high_heap_base; /* for use as the heap */ +/* + * Values for width parameter to biospci_{read,write}_config + */ +#define BIOSPCI_8BITS 0 +#define BIOSPCI_16BITS 1 +#define BIOSPCI_32BITS 2 + void biospci_detect(void); int biospci_find_devclass(uint32_t class, int index, uint32_t *locator); int biospci_read_config(uint32_t locator, int offset, int width, uint32_t *val); uint32_t biospci_locator(int8_t bus, uint8_t device, uint8_t function); int biospci_write_config(uint32_t locator, int offset, int width, uint32_t val); void biosacpi_detect(void); int i386_autoload(void); int bi_getboothowto(char *kargs); void bi_setboothowto(int howto); vm_offset_t bi_copyenv(vm_offset_t addr); int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernend); int bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep, vm_offset_t *kernend, int add_smap); void pxe_enable(void *pxeinfo);