void zynq7000_device_register(device_t self, void *aux) { prop_dictionary_t dict = device_properties(self); if (device_is_a(self, "armperiph") && device_is_a(device_parent(self), "mainbus")) { /* * XXX KLUDGE ALERT XXX * The iot mainbus supplies is completely wrong since it scales * addresses by 2. The simpliest remedy is to replace with our * bus space used for the armcore registers (which armperiph uses). */ struct mainbus_attach_args * const mb = aux; mb->mb_iot = zynq7000_armcore_bst; return; } /* * We need to tell the A9 Global/Watchdog Timer * what frequency it runs at. */ if (device_is_a(self, "a9tmr") || device_is_a(self, "a9wdt")) { prop_dictionary_set_uint32(dict, "frequency", 666666666 / PERIPHCLK_N); return; } }
void ibm4xx_device_register(struct device *dev, void *aux) { struct device *parent = device_parent(dev); if (device_is_a(dev, "emac") && device_is_a(parent, "opb")) { /* Set the mac-addr of the on-chip Ethernet. */ struct opb_attach_args *oaa = aux; if (oaa->opb_instance < 10) { prop_data_t pd; unsigned char prop_name[15]; snprintf(prop_name, sizeof(prop_name), "emac%d-mac-addr", oaa->opb_instance); pd = prop_dictionary_get(board_properties, prop_name); if (pd == NULL) { printf("WARNING: unable to get mac-addr " "property from board properties\n"); return; } if (prop_dictionary_set(device_properties(dev), "mac-addr", pd) == false) { printf("WARNING: unable to set mac-addr " "property for %s\n", dev->dv_xname); } } return; } }
int rlphymatch(device_t parent, cfdata_t match, void *aux) { struct mii_attach_args *ma = aux; struct mii_data *mii = ma->mii_data; if (mii->mii_instance != 0) return 0; if (mii_phy_match(ma, rlphys) != NULL) return (10); if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 || MII_MODEL(ma->mii_id2) != 0) return 0; if (!device_is_a(parent, "rtk") && !device_is_a(parent, "re")) return 0; /* * A "real" phy should get preference, but on the 8139 there * is no phyid register. */ return 5; }
void vexpress_device_register(device_t self, void *aux) { prop_dictionary_t dict = device_properties(self); if (device_is_a(self, "armperiph") && device_is_a(device_parent(self), "mainbus")) { /* * XXX KLUDGE ALERT XXX * The iot mainbus supplies is completely wrong since it scales * addresses by 2. The simpliest remedy is to replace with our * bus space used for the armcore regisers (which armperiph uses). */ struct mainbus_attach_args *const mb = aux; mb->mb_iot = &vexpress_bs_tag; return; } #if defined(CPU_CORTEXA7) || defined(CPU_CORTEXA15) if (device_is_a(self, "armgtmr")) { /* * The frequency of the generic timer is the reference * frequency. */ prop_dictionary_set_uint32(dict, "frequency", VEXPRESS_REF_FREQ); return; } #endif }
void device_register(device_t self, void *aux) { device_t parent = device_parent(self); if (parent != NULL && device_is_a(parent, "mainbus")) { // If we are attaching a mainbus device, see if we know how // to bring it out of reset. struct mainbus_attach_args * const ma = aux; for (const struct cfg_info *map = map_info; map < map_info + __arraycount(map_info); map++) { if (device_is_a(self, map->map_name)) { ra_device_fixup(ma->ma_memt, map); delay(1000); break; } } #if defined(RT3883) || defined(MT7620) if (device_is_a(self, "ohci") || device_is_a(self, "ehci")) { const uint32_t cfg1 = bus_space_read_4(ma->ma_memt, ra_sysctl_bsh, RA_SYSCTL_CFG1); if ((cfg1 & SYSCTL_CFG1_USB0_HOST_MODE) == 0) { bus_space_write_4(ma->ma_memt, ra_sysctl_bsh, RA_SYSCTL_CFG1, cfg1 | SYSCTL_CFG1_USB0_HOST_MODE); delay(10); } } #endif } }
/* * Attempt to find the device from which we were booted. */ void device_register(struct device *dev, void *aux) { struct bootdev_data *b = bootdev_data; struct device *parent = device_parent(dev); static int found = 0, initted = 0, scsiboot = 0; static struct device *scsibusdev = NULL; if (b == NULL) return; /* There is no hope. */ if (found) return; if (!initted) { if (strcmp(b->dev_type, "sd") == 0) scsiboot = 1; initted = 1; } if (scsiboot && device_is_a(dev, "scsibus")) { /* XXX device_unit() abuse */ if (device_unit(dev) == b->bus) { scsibusdev = dev; #if 0 printf("\nscsibus = %s\n", dev->dv_xname); #endif } return; } if (!device_is_a(dev, b->dev_type)) return; if (device_is_a(dev, "sd")) { struct scsipibus_attach_args *sa = aux; if (scsiboot && scsibusdev && parent == scsibusdev && sa->sa_periph->periph_target == b->unit) { booted_device = dev; #if 0 printf("\nbooted_device = %s\n", dev->dv_xname); #endif found = 1; } return; } /* XXX device_unit() abuse */ if (device_unit(dev) == b->unit) { booted_device = dev; #if 0 printf("\nbooted_device = %s\n", dev->dv_xname); #endif found = 1; } }
static int is_valid_disk(device_t dv) { if (device_class(dv) != DV_DISK) return (0); return (device_is_a(dv, "dk") || device_is_a(dv, "sd") || device_is_a(dv, "wd") || device_is_a(dv, "ld") || device_is_a(dv, "ed")); }
void obs405_device_register(device_t dev, void *aux, int com_freq) { device_t parent = device_parent(dev); /* register "com" device */ if (device_is_a(dev, "com") && device_is_a(parent, "opb")) { /* Set the frequency of the on-chip UART. */ com_opb_device_register(dev, com_freq); return; } ibm4xx_device_register(dev, aux); }
/* * Simple checks. Return 1 on fail. */ int jmfr(const char *n, device_t dev, int nr) { if (rpb.devtyp != nr) return 1; return !device_is_a(dev, n); }
int ddc_dev_read_edid_block(device_t dev, uint8_t *dest, size_t len, uint8_t block) { if (!device_is_a(dev, "ddc")) return EINVAL; const struct ddc_softc *sc = device_private(dev); return ddc_read_edid_block(sc->sc_tag, dest, len, block); }
device_t device_isa_register(device_t dev, void *aux) { /* * Handle network interfaces here, the attachment information is * not available driver-independently later. * * For disks, there is nothing useful available at attach time. */ if (device_class(dev) == DV_IFNET) { struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF); if (bin == NULL) return NULL; /* * We don't check the driver name against the device name * passed by the boot ROM. The ROM should stay usable if * the driver becomes obsolete. The physical attachment * information (checked below) must be sufficient to * identify the device. */ if (bin->bus == BI_BUS_ISA && device_is_a(device_parent(dev), "isa")) { struct isa_attach_args *iaa = aux; /* Compare IO base address */ /* XXXJRT What about multiple IO addrs? */ if (iaa->ia_nio > 0 && bin->addr.iobase == iaa->ia_io[0].ir_addr) return dev; } } #if NACPICA > 0 #if notyet if (device_is_a(dev, "isa") && acpi_active) { if (!(AcpiGbl_FADT.BootFlags & ACPI_FADT_LEGACY_DEVICES)) prop_dictionary_set_bool(device_properties(dev), "no-legacy-devices", true); } #endif #endif /* NACPICA > 0 */ return NULL; }
/* * Helper function for findroot(): * Return non-zero if disk device matches bootinfo. */ static int match_bootdisk(device_t dv, struct btinfo_bootdisk *bid) { struct vnode *tmpvn; int error; struct disklabel label; int found = 0; if (device_is_a(dv, "dk")) { DPRINTF(("%s: dk %s\n", __func__, device_xname(dv))); return 0; } /* * A disklabel is required here. The boot loader doesn't refuse * to boot from a disk without a label, but this is normally not * wanted. */ if (bid->labelsector == -1) { DPRINTF(("%s: no label %s\n", __func__, device_xname(dv))); return 0; } if ((tmpvn = opendisk(dv)) == NULL) { DPRINTF(("%s: can't open %s\n", __func__, device_xname(dv))); return 0; } error = VOP_IOCTL(tmpvn, DIOCGDINFO, &label, FREAD, NOCRED); if (error) { /* * XXX Can't happen -- open() would have errored out * or faked one up. */ printf("%s: can't get label for dev %s (%d)\n", __func__, device_xname(dv), error); goto closeout; } /* Compare with our data. */ if (label.d_type == bid->label.type && label.d_checksum == bid->label.checksum && strncmp(label.d_packname, bid->label.packname, 16) == 0) found = 1; DPRINTF(("%s: %s found=%d\n", __func__, device_xname(dv), found)); closeout: VOP_CLOSE(tmpvn, FREAD, NOCRED); vput(tmpvn); return (found); }
void device_register(struct device *dev, void *aux) { if (booted_device != NULL) return; if (netboot == 1) { /* check tlp0 on netboot */ if (device_class(dev) == DV_IFNET && device_is_a(dev, "tlp")) { struct pci_attach_args *pa = aux; if (pa->pa_bus == 0 && pa->pa_device == 7 && pa->pa_function == 0) booted_device = dev; } } else { /* check wd channel and drive */ if (device_class(dev) == DV_DISK && device_is_a(dev, "wd")) { struct ata_device *adev = aux; int unit; unit = adev->adev_channel * 2 + adev->adev_drv_data->drive; if (unit == bootunit) { booted_device = dev; } } /* * XXX Match up MBR boot specification with BSD disklabel * for root? */ booted_partition = 0; } }
static void armadillo9_device_register(device_t dev, void *aux) { /* MAC address for the built-in Ethernet. */ if (device_is_a(dev, "epe")) { prop_data_t pd = prop_data_create_data_nocopy( armadillo9_ethaddr, ETHER_ADDR_LEN); KASSERT(pd != NULL); if (prop_dictionary_set(device_properties(dev), "mac-address", pd) == false) { printf("WARNING: unable to set mac-addr property " "for %s\n", device_xname(dev)); } prop_object_release(pd); } }
void device_register(device_t dev, void *aux) { #if NPCI > 0 device_t parent = device_parent(dev); if (parent != NULL && device_is_a(parent, "pci")) device_pci_register(dev, aux); #endif if (bootdev_data == NULL) { /* * There is no hope. */ return; } if (platform.device_register) (*platform.device_register)(dev, aux); }
static int urlphy_match(device_t parent, cfdata_t match, void *aux) { struct mii_attach_args *ma = aux; /* * RTL8150 reports OUI == 0, MODEL == 0 */ if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 && MII_MODEL(ma->mii_id2) != 0) return (0); /* * Make sure the parent is an 'url' device. */ if (!device_is_a(parent, "url")) return(0); return (10); }
void device_register(struct device *dev, void *aux) { struct device *pdev; /* * We don't ever know the boot device. But that's because the * firmware only loads from the network or the parallel port. */ /* * Fetch the MAC address for the built-in Ethernet (we grab it * from PMON earlier in the boot process). */ if ((pdev = device_parent(dev)) != NULL && device_is_a(pdev, "pci")) { struct pci_attach_args *pa = aux; if (BUILTIN_ETHERNET_P(pa)) { prop_data_t pd = prop_data_create_data_nocopy( algor_ethaddr, ETHER_ADDR_LEN); KASSERT(pd != NULL); if (prop_dictionary_set(device_properties(dev), "mac-addr", pd) == false) { printf("WARNING: unable to set mac-addr " "property for %s\n", dev->dv_xname); } prop_object_release(pd); #if defined(ALGOR_P4032) /* * XXX This is gross, disgusting, and otherwise vile, * XXX but V962 rev. < B2 have broken DMA FIFOs. Give * XXX the on-board Ethernet a different DMA window * XXX that has pre-fetching disabled so that Ethernet * XXX performance doesn't completely suck. */ pa->pa_dmat = &p4032_configuration.ac_pci_pf_dmat; pa->pa_dmat64 = NULL; #endif /* ALGOR_P4032 */ } } }
static void micphy_fixup(struct mii_softc *sc, int model, int rev, device_t parent) { switch (model) { case MII_MODEL_MICREL_KSZ9021RNI: if (!device_is_a(parent, "cpsw")) break; aprint_normal_dev(sc->mii_dev, "adjusting RGMII signal timing for cpsw\n"); // RGMII RX Data Pad Skew micphy_writexreg(sc, REG_RGMII_RX_DATA, 0x0000); // RGMII Clock and Control Pad Skew micphy_writexreg(sc, REG_RGMII_CLOCK_AND_CONTROL, 0x9090); break; } return; }
/* * Setting LED interface for inside kernel. * Argumnt `led' is 3-bit LED state (led=0-7/ON=1/OFF=0). */ void obs266_led_set(int led) { device_t dv; deviter_t di; /* * Sarching "obsled" devices from device tree. * Do you have something better idea? */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_is_a(dv, "obsles")) { struct obsled_softc *sc = device_private(dv); sc->sc_led_state = (led & (1 << device_unit(dv))) >> device_unit(dv); obsled_set_state(sc); } } deviter_release(&di); }
void device_register(struct device *dev, void *aux) { struct device *pdev; if ((pdev = device_parent(dev)) != NULL && device_is_a(pdev, "pci")) { /* * cats builtin aceride is on 0:16:0 */ struct pci_attach_args *pa = aux; if (((pa)->pa_bus == 0 && (pa)->pa_device == 16 && (pa)->pa_function == 0)) { if (prop_dictionary_set_bool(device_properties(dev), "ali1543-ide-force-compat-mode", true) == false) { printf("WARNING: unable to set " "ali1543-ide-force-compat-mode " "property for %s\n", dev->dv_xname); } } } }
static void findroot(void) { device_t dv; deviter_t di; if (booted_device) return; if ((booted_device == NULL) && netboot == 0) { for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_class(dv) == DV_DISK && device_is_a(dv, "wd")) booted_device = dv; } deviter_release(&di); } /* * XXX Match up MBR boot specification with BSD disklabel for root? */ booted_partition = 0; }
static void findbootdev(void) { int type, ctlr, slave, punit, part; int scsiboot, hpibboot, netboot; struct dev_data *dd; booted_device = NULL; booted_partition = 0; if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) return; type = B_TYPE(bootdev); ctlr = B_ADAPTOR(bootdev); slave = B_CONTROLLER(bootdev); punit = B_UNIT(bootdev); part = B_PARTITION(bootdev); scsiboot = (type == 4); /* sd major */ hpibboot = (type == 0 || type == 2); /* ct/rd major */ netboot = (type == 6); /* le - special */ /* * Check for network boot first, since it's a little * different. The BOOTROM/boot program can only boot * off of the first (lowest select code) ethernet * device. device_register() knows this and only * registers one DV_IFNET. This is a safe assumption * since the code that finds devices on the DIO bus * always starts at scode 0 and works its way up. */ if (netboot) { for (dd = LIST_FIRST(&dev_data_list); dd != NULL; dd = LIST_NEXT(dd, dd_list)) { if (device_class(dd->dd_dev) == DV_IFNET) { /* * Found it! */ booted_device = dd->dd_dev; break; } } return; } /* * Check for HP-IB boots next. */ if (hpibboot) { findbootdev_slave(&dev_data_list_hpib, ctlr, slave, punit); if (booted_device == NULL) return; /* * Sanity check. */ if ((type == 0 && !device_is_a(booted_device, "ct")) || (type == 2 && !device_is_a(booted_device, "rd"))) { printf("WARNING: boot device/type mismatch!\n"); printf("device = %s, type = %d\n", booted_device->dv_xname, type); booted_device = NULL; } goto out; } /* * Check for SCSI boots last. */ if (scsiboot) { findbootdev_slave(&dev_data_list_scsi, ctlr, slave, punit); if (booted_device == NULL) return; /* * Sanity check. */ if ((type == 4 && !device_is_a(booted_device, "sd"))) { printf("WARNING: boot device/type mismatch!\n"); printf("device = %s, type = %d\n", booted_device->dv_xname, type); booted_device = NULL; } goto out; } /* Oof! */ printf("WARNING: UNKNOWN BOOT DEVICE TYPE = %d\n", type); out: if (booted_device != NULL) booted_partition = part; }
/* * Register a device. We're passed the device and the arguments * used to attach it. This is used to find the boot device. */ void device_register(struct device *dev, void *aux) { struct dev_data *dd; static int seen_netdevice = 0; /* * Allocate a dev_data structure and fill it in. * This means making some tests twice, but we don't * care; this doesn't really have to be fast. * * Note that we only really care about devices that * we can mount as root. */ dd = malloc(sizeof(struct dev_data), M_DEVBUF, M_NOWAIT | M_ZERO); if (dd == NULL) panic("device_register: can't allocate dev_data"); dd->dd_dev = dev; /* * BOOTROM and boot program can really only understand * using the lowest select code network interface, * so we ignore all but the first. */ if (device_class(dev) == DV_IFNET && seen_netdevice == 0) { struct dio_attach_args *da = aux; seen_netdevice = 1; dd->dd_scode = da->da_scode; goto linkup; } if (device_is_a(dev, "fhpib") || device_is_a(dev, "nhpib") || device_is_a(dev, "spc")) { struct dio_attach_args *da = aux; dd->dd_scode = da->da_scode; goto linkup; } if (device_is_a(dev, "rd")) { struct hpibbus_attach_args *ha = aux; dd->dd_slave = ha->ha_slave; dd->dd_punit = ha->ha_punit; goto linkup; } if (device_is_a(dev, "sd")) { struct scsipibus_attach_args *sa = aux; dd->dd_slave = sa->sa_periph->periph_target; dd->dd_punit = sa->sa_periph->periph_lun; goto linkup; } /* * Didn't need the dev_data. */ free(dd, M_DEVBUF); return; linkup: LIST_INSERT_HEAD(&dev_data_list, dd, dd_list); if (device_is_a(dev, "fhpib") || device_is_a(dev, "nhpib")) { dev_data_insert(dd, &dev_data_list_hpib); return; } if (device_is_a(dev, "spc")) { dev_data_insert(dd, &dev_data_list_scsi); return; } }
static void dec_2100_a500_device_register(device_t dev, void *aux) { static int found, initted, diskboot, netboot; static device_t pcidev, ctrlrdev; struct bootdev_data *b = bootdev_data; device_t parent = device_parent(dev); if (found) return; if (!initted) { diskboot = (strcasecmp(b->protocol, "SCSI") == 0) || (strcasecmp(b->protocol, "RAID") == 0); netboot = (strcasecmp(b->protocol, "BOOTP") == 0) || (strcasecmp(b->protocol, "MOP") == 0); #if 0 printf("diskboot = %d, netboot = %d\n", diskboot, netboot); #endif initted =1; } if (pcidev == NULL) { if (!device_is_a(dev, "pci")) return; else { struct pcibus_attach_args *pba = aux; if ((b->slot / 1000) != pba->pba_bus) return; pcidev = dev; #if 0 printf("\npcidev = %s\n", device_xname(dev)); #endif return; } } if (ctrlrdev == NULL) { if (parent != pcidev) return; else { struct pci_attach_args *pa = aux; int slot; slot = pa->pa_bus * 1000 + pa->pa_function * 100 + pa->pa_device; if (b->slot != slot) return; if (netboot) { booted_device = dev; #if 0 printf("\nbooted_device = %s\n", device_xname(dev)); #endif found = 1; } else { ctrlrdev = dev; #if 0 printf("\nctrlrdev = %s\n", device_xname(dev)); #endif } return; } } if (!diskboot) return; if (device_is_a(dev, "sd") || device_is_a(dev, "st") || device_is_a(dev, "cd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; int unit; if (device_parent(parent) != ctrlrdev) return; unit = periph->periph_target * 100 + periph->periph_lun; if (b->unit != unit) return; if (b->channel != periph->periph_channel->chan_channel) return; /* we've found it! */ booted_device = dev; #if 0 printf("\nbooted_device = %s\n", device_xname(dev)); #endif found = 1; } if (device_is_a(dev, "ld") && device_is_a(parent, "mlx")) { /* * Argh! The attach arguments for ld devices is not * consistent, so each supported raid controller requires * different checks. */ struct mlx_attach_args *mlxa = aux; if (parent != ctrlrdev) return; if (b->unit != mlxa->mlxa_unit) return; /* we've found it! */ booted_device = dev; #if 0 printf("\nbooted_device = %s\n", device_xname(dev)); #endif found = 1; } }
/* * Match a device_t against the bootpath, by * comparing its firmware package handle and calculating * the target/lun suffix and comparing that against * the bootpath remainder. */ static void dev_path_drive_match(device_t dev, int ctrlnode, int target, uint64_t wwn, int lun) { int child = 0, ide_node = 0; char buf[OFPATHLEN]; DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, " "target %d wwn %016" PRIx64 " lun %d\n", device_xname(dev), ctrlnode, target, wwn, lun)); /* * The ofbootpackage points to a disk on this controller, so * iterate over all child nodes and compare. */ for (child = prom_firstchild(ctrlnode); child != 0; child = prom_nextsibling(child)) if (child == ofbootpackage) break; if (child != ofbootpackage) { /* * Try Mac firmware style (also used by QEMU/OpenBIOS): * below the controller there is an intermediate node * for each IDE channel, and individual targets always * are "@0" */ for (ide_node = prom_firstchild(ctrlnode); ide_node != 0; ide_node = prom_nextsibling(ide_node)) { const char * name = prom_getpropstring(ide_node, "device_type"); if (strcmp(name, "ide") != 0) continue; for (child = prom_firstchild(ide_node); child != 0; child = prom_nextsibling(child)) if (child == ofbootpackage) break; if (child == ofbootpackage) break; } } if (child == ofbootpackage) { const char * name = prom_getpropstring(child, "name"); /* boot device is on this controller */ DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n")); /* * Note: "child" here is == ofbootpackage (s.a.), which * may be completely wrong for the device we are checking, * what we realy do here is to match "target" and "lun". */ if (wwn) snprintf(buf, sizeof(buf), "%s@w%016" PRIx64 ",%d", name, wwn, lun); else if (ide_node) snprintf(buf, sizeof(buf), "%s@0", device_is_a(dev, "cd") ? "cdrom" : "disk"); else snprintf(buf, sizeof(buf), "%s@%d,%d", name, target, lun); if (ofboottarget && strcmp(buf, ofboottarget) == 0) { booted_device = dev; if (ofbootpartition) booted_partition = *ofbootpartition - 'a'; DPRINTF(ACDB_BOOTDEV, ("found boot device: %s" ", partition %d\n", device_xname(dev), booted_partition)); } } }
static void dec_kn20aa_device_register(device_t dev, void *aux) { static int found, initted, diskboot, netboot; static device_t pcidev, ctrlrdev; struct bootdev_data *b = bootdev_data; device_t parent = device_parent(dev); if (found) return; if (!initted) { diskboot = (strcasecmp(b->protocol, "SCSI") == 0); netboot = (strcasecmp(b->protocol, "BOOTP") == 0) || (strcasecmp(b->protocol, "MOP") == 0); #if 0 printf("diskboot = %d, netboot = %d\n", diskboot, netboot); #endif initted =1; } if (pcidev == NULL) { if (!device_is_a(dev, "pci")) return; else { struct pcibus_attach_args *pba = aux; if ((b->slot / 1000) != pba->pba_bus) return; pcidev = dev; #if 0 printf("\npcidev = %s\n", device_xname(dev)); #endif return; } } if (ctrlrdev == NULL) { if (parent != pcidev) return; else { struct pci_attach_args *pa = aux; int slot; slot = pa->pa_bus * 1000 + pa->pa_function * 100 + pa->pa_device; if (b->slot != slot) return; if (netboot) { booted_device = dev; #if 0 printf("\nbooted_device = %s\n", device_xname(dev)); #endif found = 1; } else { ctrlrdev = dev; #if 0 printf("\nctrlrdev = %s\n", device_xname(dev)); #endif } return; } } if (!diskboot) return; if (device_is_a(dev, "sd") || device_is_a(dev, "st") || device_is_a(dev, "cd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; int unit; if (device_parent(parent) != ctrlrdev) return; unit = periph->periph_target * 100 + periph->periph_lun; if (b->unit != unit) return; if (b->channel != periph->periph_channel->chan_channel) return; /* we've found it! */ booted_device = dev; #if 0 printf("\nbooted_device = %s\n", device_xname(dev)); #endif found = 1; } }
/* * Attempt to find the device from which we were booted. If we can do so, * and not instructed not to do so, change rootdev to correspond to the * load device. */ static void findroot(void) { struct btinfo_rootdevice *biv; struct btinfo_bootdisk *bid; struct btinfo_bootwedge *biw; struct btinfo_biosgeom *big; device_t dv; deviter_t di; if (booted_device) return; if (lookup_bootinfo(BTINFO_NETIF) != NULL) { /* * We got netboot interface information, but device_register() * failed to match it to a configured device. Boot disk * information cannot be present at the same time, so give * up. */ printf("%s: netboot interface not found.\n", __func__); return; } if ((biv = lookup_bootinfo(BTINFO_ROOTDEVICE)) != NULL) { for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { cfdata_t cd; size_t len; if (device_class(dv) != DV_DISK) continue; cd = device_cfdata(dv); len = strlen(cd->cf_name); if (strncmp(cd->cf_name, biv->devname, len) == 0 && biv->devname[len] - '0' == device_unit(dv)) { booted_device = dv; booted_partition = biv->devname[len + 1] - 'a'; booted_nblks = 0; break; } } DPRINTF(("%s: BTINFO_ROOTDEVICE %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); deviter_release(&di); if (dv != NULL) return; } bid = lookup_bootinfo(BTINFO_BOOTDISK); biw = lookup_bootinfo(BTINFO_BOOTWEDGE); if (biw != NULL) { /* * Scan all disk devices for ones that match the passed data. * Don't break if one is found, to get possible multiple * matches - for problem tracking. Use the first match anyway * because lower devices numbers are more likely to be the * boot device. */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (is_valid_disk(dv)) { /* * Don't trust BIOS device numbers, try * to match the information passed by the * boot loader instead. */ if ((biw->biosdev & 0x80) == 0 || match_bootwedge(dv, biw) == 0) continue; goto bootwedge_found; } continue; bootwedge_found: if (booted_device) { dmatch(__func__, dv); continue; } booted_device = dv; booted_partition = bid != NULL ? bid->partition : 0; booted_nblks = biw->nblks; booted_startblk = biw->startblk; } deviter_release(&di); DPRINTF(("%s: BTINFO_BOOTWEDGE %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); if (booted_nblks) return; } if (bid != NULL) { /* * Scan all disk devices for ones that match the passed data. * Don't break if one is found, to get possible multiple * matches - for problem tracking. Use the first match anyway * because lower device numbers are more likely to be the * boot device. */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_is_a(dv, "fd") && device_class(dv) == DV_DISK) { /* * Assume the configured unit number matches * the BIOS device number. (This is the old * behavior.) Needs some ideas how to handle * the BIOS's "swap floppy drive" options. */ /* XXX device_unit() abuse */ if ((bid->biosdev & 0x80) != 0 || device_unit(dv) != bid->biosdev) continue; goto bootdisk_found; } if (is_valid_disk(dv)) { /* * Don't trust BIOS device numbers, try * to match the information passed by the * boot loader instead. */ if ((bid->biosdev & 0x80) == 0 || match_bootdisk(dv, bid) == 0) continue; goto bootdisk_found; } continue; bootdisk_found: if (booted_device) { dmatch(__func__, dv); continue; } booted_device = dv; booted_partition = bid->partition; booted_nblks = 0; } deviter_release(&di); DPRINTF(("%s: BTINFO_BOOTDISK %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); if (booted_device) return; /* * No booted device found; check CD-ROM boot at last. * * Our bootloader assumes CD-ROM boot if biosdev is larger * or equal than the number of hard drives recognized by the * BIOS. The number of drives can be found in BTINFO_BIOSGEOM * here. For example, if we have wd0, wd1, and cd0: * * big->num = 2 (for wd0 and wd1) * bid->biosdev = 0x80 (wd0) * bid->biosdev = 0x81 (wd1) * bid->biosdev = 0x82 (cd0) * * See src/sys/arch/i386/stand/boot/devopen.c and * src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c . */ if ((big = lookup_bootinfo(BTINFO_BIOSGEOM)) != NULL && bid->biosdev >= 0x80 + big->num) { /* * XXX * There is no proper way to detect which unit is * recognized as a bootable CD-ROM drive by the BIOS. * Assume the first unit is the one. */ for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL; dv = deviter_next(&di)) { if (device_class(dv) == DV_DISK && device_is_a(dv, "cd")) { booted_device = dv; booted_partition = 0; booted_nblks = 0; break; } } deviter_release(&di); DPRINTF(("%s: BTINFO_BIOSGEOM %s\n", __func__, booted_device ? device_xname(booted_device) : "not found")); } } }
static void setbootdev(void) { struct dev_data *cdd, *dd; int type, ctlr; /* * Note our magic numbers for type: * * 0 == ct * 2 == rd * 4 == sd * 6 == le * * Allare bdevsw major numbers, except for le, which * is just special. * * We can't mount root on a tape, so we ignore those. */ /* * Start with a clean slate. */ bootdev = 0; /* * If the root device is network, we're done * early. */ if (device_class(root_device) == DV_IFNET) { bootdev = MAKEBOOTDEV(6, 0, 0, 0, 0); goto out; } /* * Determine device type. */ if (device_is_a(root_device, "rd")) type = 2; else if (device_is_a(root_device, "sd")) type = 4; else if (device_is_a(root_device, "md")) goto out; else { printf("WARNING: strange root device!\n"); goto out; } dd = dev_data_lookup(root_device); /* * Get parent's info. */ switch (type) { case 2: /* rd */ case 4: /* sd */ /* * "rd" -> "hpibbus" -> "fhpib" * "sd" -> "scsibus" -> "spc" */ for (cdd = LIST_FIRST(&dev_data_list_hpib), ctlr = 0; cdd != NULL; cdd = LIST_NEXT(cdd, dd_clist), ctlr++) { if (cdd->dd_dev == device_parent(device_parent(root_device))) { /* * Found it! */ bootdev = MAKEBOOTDEV(type, ctlr, dd->dd_slave, dd->dd_punit, DISKPART(rootdev)); break; } } break; } out: /* Don't need this anymore. */ for (dd = LIST_FIRST(&dev_data_list); dd != NULL; ) { cdd = dd; dd = LIST_NEXT(dd, dd_list); free(cdd, M_DEVBUF); } }
/* * Called back during autoconfiguration for each device found */ void device_register(device_t dev, void *aux) { device_t busdev = device_parent(dev); int ofnode = 0; /* * We don't know the type of 'aux' - it depends on the * bus this device attaches to. We are only interested in * certain bus types, this only is used to find the boot * device. */ if (busdev == NULL) { /* * Ignore mainbus0 itself, it certainly is not a boot * device. */ } else if (device_is_a(busdev, "mainbus")) { struct mainbus_attach_args *ma = aux; ofnode = ma->ma_node; } else if (device_is_a(busdev, "pci")) { struct pci_attach_args *pa = aux; ofnode = PCITAG_NODE(pa->pa_tag); } else if (device_is_a(busdev, "sbus") || device_is_a(busdev, "dma") || device_is_a(busdev, "ledma")) { struct sbus_attach_args *sa = aux; ofnode = sa->sa_node; } else if (device_is_a(busdev, "ebus")) { struct ebus_attach_args *ea = aux; ofnode = ea->ea_node; } else if (device_is_a(busdev, "iic")) { struct i2c_attach_args *ia = aux; if (ia->ia_name == NULL) /* indirect config */ return; ofnode = (int)ia->ia_cookie; } else if (device_is_a(dev, "sd") || device_is_a(dev, "cd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; int off = 0; /* * There are two "cd" attachments: * atapibus -> atabus -> controller * scsibus -> controller * We want the node of the controller. */ if (device_is_a(busdev, "atapibus")) { busdev = device_parent(busdev); /* * if the atapibus is connected to the secondary * channel of the atabus, we need an offset of 2 * to match OF's idea of the target number. * (i.e. on U5/U10 "cdrom" and "disk2" have the * same target encoding, though different names) */ if (periph->periph_channel->chan_channel == 1) off = 2; } ofnode = device_ofnode(device_parent(busdev)); dev_path_drive_match(dev, ofnode, periph->periph_target + off, 0, periph->periph_lun); return; } else if (device_is_a(dev, "wd")) { struct ata_device *adev = aux; ofnode = device_ofnode(device_parent(busdev)); dev_path_drive_match(dev, ofnode, adev->adev_channel*2+ adev->adev_drv_data->drive, 0, 0); return; } if (busdev == NULL) return; if (ofnode != 0) { uint8_t eaddr[ETHER_ADDR_LEN]; char tmpstr[32]; char tmpstr2[32]; int node; uint32_t id = 0; uint64_t nwwn = 0, pwwn = 0; prop_dictionary_t dict; prop_data_t blob; prop_number_t pwwnd = NULL, nwwnd = NULL; prop_number_t idd = NULL; device_setofnode(dev, ofnode); dev_path_exact_match(dev, ofnode); if (OF_getprop(ofnode, "name", tmpstr, sizeof(tmpstr)) <= 0) tmpstr[0] = 0; if (OF_getprop(ofnode, "device_type", tmpstr2, sizeof(tmpstr2)) <= 0) tmpstr2[0] = 0; /* * If this is a network interface, note the * mac address. */ if (strcmp(tmpstr, "network") == 0 || strcmp(tmpstr, "ethernet") == 0 || strcmp(tmpstr2, "network") == 0 || strcmp(tmpstr2, "ethernet") == 0 || OF_getprop(ofnode, "mac-address", &eaddr, sizeof(eaddr)) >= ETHER_ADDR_LEN || OF_getprop(ofnode, "local-mac-address", &eaddr, sizeof(eaddr)) >= ETHER_ADDR_LEN) { dict = device_properties(dev); /* * Is it a network interface with FCode? */ if (strcmp(tmpstr, "network") == 0 || strcmp(tmpstr2, "network") == 0) { prop_dictionary_set_bool(dict, "without-seeprom", true); prom_getether(ofnode, eaddr); } else { if (!prom_get_node_ether(ofnode, eaddr)) goto noether; } blob = prop_data_create_data(eaddr, ETHER_ADDR_LEN); prop_dictionary_set(dict, "mac-address", blob); prop_object_release(blob); of_to_dataprop(dict, ofnode, "shared-pins", "shared-pins"); } noether: /* is this a FC node? */ if (strcmp(tmpstr, "scsi-fcp") == 0) { dict = device_properties(dev); if (OF_getprop(ofnode, "port-wwn", &pwwn, sizeof(pwwn)) == sizeof(pwwn)) { pwwnd = prop_number_create_unsigned_integer(pwwn); prop_dictionary_set(dict, "port-wwn", pwwnd); prop_object_release(pwwnd); } if (OF_getprop(ofnode, "node-wwn", &nwwn, sizeof(nwwn)) == sizeof(nwwn)) { nwwnd = prop_number_create_unsigned_integer(nwwn); prop_dictionary_set(dict, "node-wwn", nwwnd); prop_object_release(nwwnd); } } /* is this an spi device? look for scsi-initiator-id */ if (strcmp(tmpstr2, "scsi") == 0 || strcmp(tmpstr2, "scsi-2") == 0) { dict = device_properties(dev); for (node = ofnode; node != 0; node = OF_parent(node)) { if (OF_getprop(node, "scsi-initiator-id", &id, sizeof(id)) <= 0) continue; idd = prop_number_create_unsigned_integer(id); prop_dictionary_set(dict, "scsi-initiator-id", idd); prop_object_release(idd); break; } } } /* * Check for I2C busses and add data for their direct configuration. */ if (device_is_a(dev, "iic")) { int busnode = device_ofnode(busdev); if (busnode) { prop_dictionary_t props = device_properties(busdev); prop_object_t cfg = prop_dictionary_get(props, "i2c-child-devices"); if (!cfg) { int node; const char *name; /* * pmu's i2c devices are under the "i2c" node, * so find it out. */ name = prom_getpropstring(busnode, "name"); if (strcmp(name, "pmu") == 0) { for (node = OF_child(busnode); node != 0; node = OF_peer(node)) { name = prom_getpropstring(node, "name"); if (strcmp(name, "i2c") == 0) { busnode = node; break; } } } of_enter_i2c_devs(props, busnode, sizeof(cell_t)); } } /* * Add SPARCle spdmem devices (0x50 and 0x51) that the * firmware does not know about. */ if (!strcmp(machine_model, "TAD,SPARCLE")) { prop_dictionary_t props = device_properties(busdev); prop_array_t cfg = prop_array_create(); int i; DPRINTF(ACDB_PROBE, ("\nAdding spdmem for SPARCle ")); for (i = 0x50; i <= 0x51; i++) { prop_dictionary_t spd = prop_dictionary_create(); prop_dictionary_set_cstring(spd, "name", "dimm-spd"); prop_dictionary_set_uint32(spd, "addr", i); prop_dictionary_set_uint64(spd, "cookie", 0); prop_array_add(cfg, spd); prop_object_release(spd); } prop_dictionary_set(props, "i2c-child-devices", cfg); prop_object_release(cfg); } } /* set properties for PCI framebuffers */ if (device_is_a(busdev, "pci")) { /* see if this is going to be console */ struct pci_attach_args *pa = aux; prop_dictionary_t dict; int sub; int console = 0; dict = device_properties(dev); /* we only care about display devices from here on */ if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY) return; console = (ofnode == console_node); if (!console) { /* * see if any child matches since OF attaches * nodes for each head and /chosen/stdout * points to the head rather than the device * itself in this case */ sub = OF_child(ofnode); while ((sub != 0) && (sub != console_node)) { sub = OF_peer(sub); } if (sub == console_node) { console = true; } } copyprops(busdev, ofnode, dict, console); if (console) { uint64_t cmap_cb; prop_dictionary_set_uint32(dict, "instance_handle", console_instance); gfb_cb.gcc_cookie = (void *)(intptr_t)console_instance; gfb_cb.gcc_set_mapreg = of_set_palette; cmap_cb = (uint64_t)(uintptr_t)&gfb_cb; prop_dictionary_set_uint64(dict, "cmap_callback", cmap_cb); } #ifdef notyet else { int width; /* * the idea is to 'open' display devices with no useful * properties, in the hope that the firmware will * properly initialize them and we can run things like * genfb on them */ if (OF_getprop(node, "width", &width, sizeof(width)) != 4) { instance = OF_open(name); #endif } } /* * Called back after autoconfiguration of a device is done */ void device_register_post_config(device_t dev, void *aux) { if (booted_device == NULL && device_is_a(dev, "sd")) { struct scsipibus_attach_args *sa = aux; struct scsipi_periph *periph = sa->sa_periph; uint64_t wwn = 0; int ofnode; /* * If this is a FC-AL drive it will have * aquired its WWN device property by now, * so we can properly match it. */ if (prop_dictionary_get_uint64(device_properties(dev), "port-wwn", &wwn)) { /* * Different to what we do in device_register, * we do not pass the "controller" ofnode, * because FC-AL devices attach below a "fp" node, * E.g.: /pci/SUNW,qlc@4/fp@0,0/disk * and we need the parent of "disk" here. */ ofnode = device_ofnode( device_parent(device_parent(dev))); for (ofnode = OF_child(ofnode); ofnode != 0 && booted_device == NULL; ofnode = OF_peer(ofnode)) { dev_path_drive_match(dev, ofnode, periph->periph_target, wwn, periph->periph_lun); } } } } static void copyprops(device_t busdev, int node, prop_dictionary_t dict, int is_console) { device_t cntrlr; prop_dictionary_t psycho; paddr_t fbpa, mem_base = 0; uint32_t temp, fboffset; uint32_t fbaddr = 0; int options; char output_device[256]; char *pos; cntrlr = device_parent(busdev); if (cntrlr != NULL) { psycho = device_properties(cntrlr); prop_dictionary_get_uint64(psycho, "mem_base", &mem_base); } if (is_console) prop_dictionary_set_bool(dict, "is_console", 1); of_to_uint32_prop(dict, node, "width", "width"); of_to_uint32_prop(dict, node, "height", "height"); of_to_uint32_prop(dict, node, "linebytes", "linebytes"); if (!of_to_uint32_prop(dict, node, "depth", "depth") && /* Some cards have an extra space in the property name */ !of_to_uint32_prop(dict, node, "depth ", "depth")) { /* * XXX we should check linebytes vs. width but those * FBs that don't have a depth property ( /chaos/control... ) * won't have linebytes either */ prop_dictionary_set_uint32(dict, "depth", 8); } OF_getprop(node, "address", &fbaddr, sizeof(fbaddr)); if (fbaddr != 0) { pmap_extract(pmap_kernel(), fbaddr, &fbpa); #ifdef DEBUG printf("membase: %lx fbpa: %lx\n", (unsigned long)mem_base, (unsigned long)fbpa); #endif if (mem_base == 0) { /* XXX this is guesswork */ fboffset = (uint32_t)(fbpa & 0xffffffff); } fboffset = (uint32_t)(fbpa - mem_base); prop_dictionary_set_uint32(dict, "address", fboffset); } if (!of_to_dataprop(dict, node, "EDID", "EDID")) of_to_dataprop(dict, node, "edid", "EDID"); temp = 0; if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) { OF_getprop(OF_parent(node), "ATY,RefCLK", &temp, sizeof(temp)); } if (temp != 0) prop_dictionary_set_uint32(dict, "refclk", temp / 10); /* * finally, let's see if there's a video mode specified in * output-device and pass it on so drivers like radeonfb * can do their thing */ if (!is_console) return; options = OF_finddevice("/options"); if ((options == 0) || (options == -1)) return; if (OF_getprop(options, "output-device", output_device, 256) == 0) return; /* find the mode string if there is one */ pos = strstr(output_device, ":r"); if (pos == NULL) return; prop_dictionary_set_cstring(dict, "videomode", pos + 2); } static void of_set_palette(void *cookie, int index, int r, int g, int b) { int ih = (int)((intptr_t)cookie); OF_call_method_1("color!", ih, 4, r, g, b, index); }
void device_register(struct device *dev, void *aux) { static struct device *controller; static int foundboot; struct device *parent = device_parent(dev); if (foundboot) return; if (controller == NULL && parent) { switch (machineid) { #ifdef MVME147 case MVME_147: /* * We currently only support booting from the 147's * onboard scsi and ethernet. So ensure this * device's parent is the PCC driver. */ if (!device_is_a(parent, "pcc")) return; if (bootaddr == PCC_PADDR(PCC_WDSC_OFF) && device_is_a(dev, "wdsc")) { controller = dev; return; } if (bootaddr == PCC_PADDR(PCC_LE_OFF) && device_is_a(dev, "le")) { booted_device = dev; foundboot = 1; return; } break; #endif /* MVME_147 */ #if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177) case MVME_162: case MVME_167: case MVME_172: case MVME_177: /* * We currently only support booting from the 16x and * 17x onboard scsi and ethernet. So ensure this * device's parent is the PCCTWO driver. */ if (!device_is_a(parent, "pcctwo")) return; if (bootaddr == PCCTWO_PADDR(PCCTWO_NCRSC_OFF) && device_is_a(dev, "osiop")) { controller = dev; return; } if (bootaddr == PCCTWO_PADDR(PCCTWO_IE_OFF) && device_is_a(dev, "ie")) { booted_device = dev; foundboot = 1; return; } break; #endif /* MVME_162 || MVME_167 || MVME_172 || MVME_177 */ default: break; } return; } /* * Find out which device on the scsibus we booted from */ if (device_is_a(dev, "sd") || device_is_a(dev, "cd") || device_is_a(dev, "st")) { struct scsipibus_attach_args *sa = aux; if (device_parent(parent) != controller || bootdevlun != sa->sa_periph->periph_target) return; booted_device = dev; foundboot = 1; } }