예제 #1
0
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;
	}
}
예제 #2
0
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;
    }
}
예제 #3
0
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
}
예제 #5
0
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
	}
}
예제 #6
0
/*
 * 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;
	}
}
예제 #7
0
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);
}
예제 #9
0
/*
 * 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);
}
예제 #10
0
파일: ddc.c 프로젝트: goroutines/rumprun
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);
}
예제 #11
0
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;
}
예제 #12
0
/*
 * 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);
}
예제 #13
0
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;
	}
}
예제 #14
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);
	}
}
예제 #15
0
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);
}
예제 #16
0
파일: urlphy.c 프로젝트: ryoon/netbsd-xhci
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);
}
예제 #17
0
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 */
		}
	}
}
예제 #18
0
파일: micphy.c 프로젝트: ryoon/netbsd-xhci
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;
}
예제 #19
0
/*
 * 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);
}
예제 #20
0
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);
			}
		}
	}
}
예제 #21
0
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;
}
예제 #22
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;
}
예제 #23
0
/*
 * 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;
	}
}
예제 #25
0
/*
 * 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;
	}
}
예제 #27
0
/*
 * 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"));
		}
	}
}
예제 #28
0
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);
	}
}
예제 #29
0
/*
 * 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);
}
예제 #30
0
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;
	}
}