示例#1
0
int
magma_match(device_t parent, cfdata_t cf, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct magma_board_info *card;

	/* See if we support this device */
	for (card = supported_cards; ; card++) {
		if (card->mb_sbusname == NULL)
			/* End of table: no match */
			return (0);
		if (strcmp(sa->sa_name, card->mb_sbusname) == 0)
			break;
	}

	dprintf(("magma: matched `%s'\n", sa->sa_name));
	dprintf(("magma: magma_prom `%s'\n",
		prom_getpropstring(sa->sa_node, "magma_prom")));
	dprintf(("magma: intlevels `%s'\n",
		prom_getpropstring(sa->sa_node, "intlevels")));
	dprintf(("magma: chiprev `%s'\n",
		prom_getpropstring(sa->sa_node, "chiprev")));
	dprintf(("magma: clock `%s'\n",
		prom_getpropstring(sa->sa_node, "clock")));

	return (1);
}
/*
 * Get the number of CPUs in the system and the CPUs' SPARC architecture
 * version. We need this information early in the boot process.
 */
int
find_cpus(void)
{
	int n;
#if defined(SUN4M) || defined(SUN4D)
	int node;
#endif
	/*
	 * Set default processor architecture version
	 *
	 * All sun4 and sun4c platforms have v7 CPUs;
	 * sun4m may have v7 (Cyrus CY7C601 modules) or v8 CPUs (all
	 * other models, presumably).
	 */
	cpu_arch = 7;

	/* On sun4 and sun4c we support only one CPU */
	if (!CPU_ISSUN4M && !CPU_ISSUN4D)
		return (1);

	n = 0;
#if defined(SUN4M)
	node = findroot();
	for (node = firstchild(node); node; node = nextsibling(node)) {
		if (strcmp(prom_getpropstring(node, "device_type"), "cpu") != 0)
			continue;
		if (n++ == 0)
			cpu_arch = prom_getpropint(node, "sparc-version", 7);
	}
#endif /* SUN4M */
#if defined(SUN4D)
	node = findroot();
	for (node = firstchild(node); node; node = nextsibling(node)) {
		int unode;

		if (strcmp(prom_getpropstring(node, "name"), "cpu-unit") != 0)
				continue;
		for (unode = firstchild(node); unode;
		     unode = nextsibling(unode)) {
			if (strcmp(prom_getpropstring(unode, "device_type"),
				   "cpu") != 0)
				continue;
			if (n++ == 0)
				cpu_arch = prom_getpropint(unode,
							   "sparc-version", 7);
		}
	}
#endif

	return (n);
}
示例#3
0
/*
 * Match a struct device against the bootpath, by
 * comparing it's firmware package handle and calculating
 * the target/lun suffix and comparing that against
 * the bootpath remainder.
 */
static void
dev_path_drive_match(struct device *dev, int ctrlnode, int target, int lun)
{
	int child = 0;
	char buf[OFPATHLEN];

	DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, "
	    "target %d lun %d\n", device_xname(dev), ctrlnode, target, 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) {
		/* boot device is on this controller */
		DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n"));
		sprintf(buf, "%s@%d,%d", prom_getpropstring(child, "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));
		}
	}
}
示例#4
0
static	int
psycho_match(device_t parent, cfdata_t match, void *aux)
{
	struct mainbus_attach_args *ma = aux;
	char *model = prom_getpropstring(ma->ma_node, "model");
	int i;

	/* match on a name of "pci" and a sabre or a psycho */
	if (strcmp(ma->ma_name, ROM_PCI_NAME) == 0) {
		for (i=0; psycho_names[i].p_name; i++)
			if (strcmp(model, psycho_names[i].p_name) == 0)
				return (1);

		model = prom_getpropstring(ma->ma_node, "compatible");
		for (i=0; psycho_names[i].p_name; i++)
			if (strcmp(model, psycho_names[i].p_name) == 0)
				return (1);
	}
	return (0);
}
示例#5
0
/*
 * Match a graphics device.
 */
static int
genfb_match_sbus(device_t parent, cfdata_t cf, void *aux)
{
	struct sbus_attach_args *sa = aux;

	/* if there's no address property we can't use the device */
	if (prom_getpropint(sa->sa_node, "address", -1) == -1)
		return 0;
	if (strcmp("display", prom_getpropstring(sa->sa_node, "device_type"))
	    == 0)
		return 1;

	return 0;
}
示例#6
0
文件: sab.c 项目: lacombar/netbsd-alc
int
sab_match(struct device *parent, struct cfdata *match, void *aux)
{
	struct ebus_attach_args *ea = aux;
	char *compat;

	if (strcmp(ea->ea_name, "se") == 0)
		return (1);

	compat = prom_getpropstring(ea->ea_node, "compatible");
	if (compat != NULL && !strcmp(compat, "sab82532"))
		return (1);

	return (0);
}
示例#7
0
/*
 * Match a device_t against the bootpath, by
 * comparing it's 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;
	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) {
		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)
			sprintf(buf, "%s@w%016" PRIx64 ",%d", name, wwn,
			    lun);
		else
			sprintf(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));
		}
	}
}
示例#8
0
/*
 * Attach the CPU.
 * Discover interesting goop about the virtual address cache
 * (slightly funny place to do it, but this is where it is to be found).
 */
void
cpu_attach(device_t parent, device_t dev, void *aux)
{
	int node;
	long clk, sclk = 0;
	struct mainbus_attach_args *ma = aux;
	struct cpu_info *ci;
	const char *sep;
	register int i, l;
	int bigcache, cachesize;
	char buf[100];
	int 	totalsize = 0;
	int 	linesize, dcachesize, icachesize;

	/* tell them what we have */
	node = ma->ma_node;

	/*
	 * Allocate cpu_info structure if needed.
	 */
	ci = alloc_cpuinfo((u_int)node);

	/*
	 * Only do this on the boot cpu.  Other cpu's call
	 * cpu_reset_fpustate() from cpu_hatch() before they
	 * call into the idle loop.
	 * For other cpus, we need to call mi_cpu_attach()
	 * and complete setting up cpcb.
	 */
	if (ci->ci_flags & CPUF_PRIMARY) {
		fpstate_cache = pool_cache_init(sizeof(struct fpstate64),
					SPARC64_BLOCK_SIZE, 0, 0, "fpstate",
					NULL, IPL_NONE, NULL, NULL, NULL);
		cpu_reset_fpustate();
	}
#ifdef MULTIPROCESSOR
	else {
		mi_cpu_attach(ci);
		ci->ci_cpcb = lwp_getpcb(ci->ci_data.cpu_idlelwp);
	}
	for (i = 0; i < IPI_EVCNT_NUM; ++i)
		evcnt_attach_dynamic(&ci->ci_ipi_evcnt[i], EVCNT_TYPE_INTR,
				     NULL, device_xname(dev), ipi_evcnt_names[i]);
#endif
	evcnt_attach_dynamic(&ci->ci_tick_evcnt, EVCNT_TYPE_INTR, NULL,
			     device_xname(dev), "timer");
	mutex_init(&ci->ci_ctx_lock, MUTEX_SPIN, IPL_VM);

	clk = prom_getpropint(node, "clock-frequency", 0);
	if (clk == 0) {
		/*
		 * Try to find it in the OpenPROM root...
		 */
		clk = prom_getpropint(findroot(), "clock-frequency", 0);
	}
	if (clk) {
		/* Tell OS what frequency we run on */
		ci->ci_cpu_clockrate[0] = clk;
		ci->ci_cpu_clockrate[1] = clk / 1000000;
	}

	sclk = prom_getpropint(findroot(), "stick-frequency", 0);

	ci->ci_system_clockrate[0] = sclk;
	ci->ci_system_clockrate[1] = sclk / 1000000;

	snprintf(buf, sizeof buf, "%s @ %s MHz",
		prom_getpropstring(node, "name"), clockfreq(clk));
	snprintf(cpu_model, sizeof cpu_model, "%s (%s)", machine_model, buf);

	aprint_normal(": %s, UPA id %d\n", buf, ci->ci_cpuid);
	aprint_naive("\n");

	if (ci->ci_system_clockrate[0] != 0) {
		aprint_normal_dev(dev, "system tick frequency %d MHz\n", 
		    (int)ci->ci_system_clockrate[1]);
	}
	aprint_normal_dev(dev, "");

	bigcache = 0;

	icachesize = prom_getpropint(node, "icache-size", 0);
	if (icachesize > icache_size)
		icache_size = icachesize;
	linesize = l = prom_getpropint(node, "icache-line-size", 0);
	if (linesize > icache_line_size)
		icache_line_size = linesize;

	for (i = 0; (1 << i) < l && l; i++)
		/* void */;
	if ((1 << i) != l && l)
		panic("bad icache line size %d", l);
	totalsize = icachesize;
	if (totalsize == 0)
		totalsize = l *
			prom_getpropint(node, "icache-nlines", 64) *
			prom_getpropint(node, "icache-associativity", 1);

	cachesize = totalsize /
	    prom_getpropint(node, "icache-associativity", 1);
	bigcache = cachesize;

	sep = "";
	if (totalsize > 0) {
		aprint_normal("%s%ldK instruction (%ld b/l)", sep,
		       (long)totalsize/1024,
		       (long)linesize);
		sep = ", ";
	}

	dcachesize = prom_getpropint(node, "dcache-size", 0);
	if (dcachesize > dcache_size)
		dcache_size = dcachesize;
	linesize = l = prom_getpropint(node, "dcache-line-size", 0);
	if (linesize > dcache_line_size)
		dcache_line_size = linesize;

	for (i = 0; (1 << i) < l && l; i++)
		/* void */;
	if ((1 << i) != l && l)
		panic("bad dcache line size %d", l);
	totalsize = dcachesize;
	if (totalsize == 0)
		totalsize = l *
			prom_getpropint(node, "dcache-nlines", 128) *
			prom_getpropint(node, "dcache-associativity", 1);

	cachesize = totalsize /
	    prom_getpropint(node, "dcache-associativity", 1);
	if (cachesize > bigcache)
		bigcache = cachesize;

	if (totalsize > 0) {
		aprint_normal("%s%ldK data (%ld b/l)", sep,
		       (long)totalsize/1024,
		       (long)linesize);
		sep = ", ";
	}

	linesize = l =
		prom_getpropint(node, "ecache-line-size", 0);
	for (i = 0; (1 << i) < l && l; i++)
		/* void */;
	if ((1 << i) != l && l)
		panic("bad ecache line size %d", l);
	totalsize = prom_getpropint(node, "ecache-size", 0);
	if (totalsize == 0)
		totalsize = l *
			prom_getpropint(node, "ecache-nlines", 32768) *
			prom_getpropint(node, "ecache-associativity", 1);

	cachesize = totalsize /
	     prom_getpropint(node, "ecache-associativity", 1);
	if (cachesize > bigcache)
		bigcache = cachesize;

	if (totalsize > 0) {
		aprint_normal("%s%ldK external (%ld b/l)", sep,
		       (long)totalsize/1024,
		       (long)linesize);
	}
	aprint_normal("\n");

	if (ecache_min_line_size == 0 ||
	    linesize < ecache_min_line_size)
		ecache_min_line_size = linesize;

	/*
	 * Now that we know the size of the largest cache on this CPU,
	 * re-color our pages.
	 */
	uvm_page_recolor(atop(bigcache)); /* XXX */

}
示例#9
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);
}
示例#10
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));
		}
	}
}
示例#11
0
/*
 * SUNW,psycho initialisation ..
 *	- find the per-psycho registers
 *	- figure out the IGN.
 *	- find our partner psycho
 *	- configure ourselves
 *	- bus range, bus,
 *	- get interrupt-map and interrupt-map-mask
 *	- setup the chipsets.
 *	- if we're the first of the pair, initialise the IOMMU, otherwise
 *	  just copy its tags and addresses.
 */
static	void
psycho_attach(device_t parent, device_t self, void *aux)
{
	struct psycho_softc *sc = device_private(self);
	struct psycho_softc *osc = NULL;
	struct psycho_pbm *pp;
	struct pcibus_attach_args pba;
	struct mainbus_attach_args *ma = aux;
	struct psycho_ranges *pr;
	prop_dictionary_t dict;
	bus_space_handle_t bh;
	uint64_t csr, mem_base;
	int psycho_br[2], n, i;
	bus_space_handle_t pci_ctl;
	char *model = prom_getpropstring(ma->ma_node, "model");

	aprint_normal("\n");

	sc->sc_dev = self;
	sc->sc_node = ma->ma_node;
	sc->sc_bustag = ma->ma_bustag;
	sc->sc_dmatag = ma->ma_dmatag;
	sc->sc_last_stick = 0;

	if (psycho0 == NULL)
		psycho0 = sc;
	DPRINTF(PDB_STICK, ("init psycho0 %lx\n", (long)sc));
	/*
	 * Identify the device.
	 */
	for (i=0; psycho_names[i].p_name; i++)
		if (strcmp(model, psycho_names[i].p_name) == 0) {
			sc->sc_mode = psycho_names[i].p_type;
			goto found;
		}

	model = prom_getpropstring(ma->ma_node, "compatible");
	for (i=0; psycho_names[i].p_name; i++)
		if (strcmp(model, psycho_names[i].p_name) == 0) {
			sc->sc_mode = psycho_names[i].p_type;
			goto found;
		}

	panic("unknown psycho model %s", model);
found:

	/*
	 * The psycho gets three register banks:
	 * (0) per-PBM configuration and status registers
	 * (1) per-PBM PCI configuration space, containing only the
	 *     PBM 256-byte PCI header
	 * (2) the shared psycho configuration registers (struct psychoreg)
	 */

	/* Register layouts are different.  stuupid. */
	if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
		sc->sc_basepaddr = (paddr_t)ma->ma_reg[2].ur_paddr;

		if (ma->ma_naddress > 2) {
			sparc_promaddr_to_handle(sc->sc_bustag,
				ma->ma_address[2], &sc->sc_bh);
			sparc_promaddr_to_handle(sc->sc_bustag,
				ma->ma_address[0], &pci_ctl);

			sc->sc_regs = (struct psychoreg *)
				bus_space_vaddr(sc->sc_bustag, sc->sc_bh);
		} else if (ma->ma_nreg > 2) {

			/* We need to map this in ourselves. */
			if (bus_space_map(sc->sc_bustag,
				ma->ma_reg[2].ur_paddr,
				ma->ma_reg[2].ur_len, BUS_SPACE_MAP_LINEAR,
				&sc->sc_bh))
				panic("psycho_attach: cannot map regs");
			sc->sc_regs = (struct psychoreg *)
				bus_space_vaddr(sc->sc_bustag, sc->sc_bh);

			if (bus_space_map(sc->sc_bustag,
				ma->ma_reg[0].ur_paddr,
				ma->ma_reg[0].ur_len, BUS_SPACE_MAP_LINEAR,
				&pci_ctl))
				panic("psycho_attach: cannot map ctl");
		} else
			panic("psycho_attach: %d not enough registers",
				ma->ma_nreg);

	} else {
		sc->sc_basepaddr = (paddr_t)ma->ma_reg[0].ur_paddr;

		if (ma->ma_naddress) {
			sparc_promaddr_to_handle(sc->sc_bustag,
				ma->ma_address[0], &sc->sc_bh);
			sc->sc_regs = (struct psychoreg *)
				bus_space_vaddr(sc->sc_bustag, sc->sc_bh);

			bus_space_subregion(sc->sc_bustag, sc->sc_bh,
				offsetof(struct psychoreg,  psy_pcictl),
				sizeof(struct pci_ctl), &pci_ctl);
		} else if (ma->ma_nreg) {
示例#12
0
void
magma_attach(device_t parent, device_t self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct magma_softc *sc = device_private(self);
	struct magma_board_info *card;
	bus_space_handle_t bh;
	char *magma_prom, *clockstr;
	int cd_clock;
	int node, chip;

	sc->ms_dev = self;
	node = sa->sa_node;

	/*
	 * Find the card model.
	 * Older models all have sbus node name `MAGMA_Sp' (see
	 * `supported_cards[]' above), and must be distinguished
	 * by the `magma_prom' property.
	 */
	magma_prom = prom_getpropstring(node, "magma_prom");

	for (card = supported_cards; card->mb_name != NULL; card++) {
		if (strcmp(sa->sa_name, card->mb_sbusname) != 0)
			/* Sbus node name doesn't match */
			continue;
		if (strcmp(magma_prom, card->mb_name) == 0)
			/* Model name match */
			break;
	}

	if( card->mb_name == NULL ) {
		printf(": %s (unsupported)\n", magma_prom);
		return;
	}

	dprintf((" addr %p", sc));
	printf(": %s\n", card->mb_realname);

	sc->ms_board = card;
	sc->ms_ncd1400 = card->mb_ncd1400;
	sc->ms_ncd1190 = card->mb_ncd1190;

	if (sbus_bus_map(sa->sa_bustag,
			 sa->sa_slot, sa->sa_offset, sa->sa_size,
			 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
		aprint_error("%s @ sbus: cannot map registers\n",
			device_xname(self));
		return;
	}

	/* the SVCACK* lines are daisychained */
	sc->ms_svcackr = (char *)bus_space_vaddr(sa->sa_bustag, bh)
		+ card->mb_svcackr;
	sc->ms_svcackt = (char *)bus_space_vaddr(sa->sa_bustag, bh)
		+ card->mb_svcackt;
	sc->ms_svcackm = (char *)bus_space_vaddr(sa->sa_bustag, bh)
		+ card->mb_svcackm;

	/*
	 * Find the clock speed; it's the same for all CD1400 chips
	 * on the board.
	 */
	clockstr = prom_getpropstring(node, "clock");
	if (*clockstr == '\0')
		/* Default to 25MHz */
		cd_clock = 25;
	else {
		cd_clock = 0;
		while (*clockstr != '\0')
			cd_clock = (cd_clock * 10) + (*clockstr++ - '0');
	}

	/* init the cd1400 chips */
	for( chip = 0 ; chip < card->mb_ncd1400 ; chip++ ) {
		struct cd1400 *cd = &sc->ms_cd1400[chip];

		cd->cd_clock = cd_clock;
		cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) +
		    card->mb_cd1400[chip];

		/* prom_getpropstring(node, "chiprev"); */
		/* seemingly the Magma drivers just ignore the propstring */
		cd->cd_chiprev = cd1400_read_reg(cd, CD1400_GFRCR);

		dprintf(("%s attach CD1400 %d addr %p rev %x clock %dMHz\n",
			device_xname(sc->ms_dev), chip,
			cd->cd_reg, cd->cd_chiprev, cd->cd_clock));

		/* clear GFRCR */
		cd1400_write_reg(cd, CD1400_GFRCR, 0x00);

		/* reset whole chip */
		cd1400_write_ccr(cd, CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);

		/* wait for revision code to be restored */
		while( cd1400_read_reg(cd, CD1400_GFRCR) != cd->cd_chiprev )
		        ;

		/* set the Prescaler Period Register to tick at 1ms */
		cd1400_write_reg(cd, CD1400_PPR,
			((cd->cd_clock * 1000000 / CD1400_PPR_PRESCALER + 500) / 1000));

		/* The LC2+1Sp card is the only card that doesn't have
		 * a CD1190 for the parallel port, but uses channel 0 of
		 * the CD1400, so we make a note of it for later and set up
		 * the CD1400 for parallel mode operation.
		 */
		if( card->mb_npar && card->mb_ncd1190 == 0 ) {
			cd1400_write_reg(cd, CD1400_GCR, CD1400_GCR_PARALLEL);
			cd->cd_parmode = 1;
		}
	}

	/* init the cd1190 chips */
	for( chip = 0 ; chip < card->mb_ncd1190 ; chip++ ) {
		struct cd1190 *cd = &sc->ms_cd1190[chip];

		cd->cd_reg = (char *)bus_space_vaddr(sa->sa_bustag, bh) +
		    card->mb_cd1190[chip];

		/* XXX don't know anything about these chips yet */
		printf("%s: CD1190 %d addr %p (unsupported)\n",
			device_xname(self), chip, cd->cd_reg);
	}

	/* configure the children */
	(void)config_found(self, mtty_match, NULL);
	(void)config_found(self, mbpp_match, NULL);

	/*
	 * Establish the interrupt handlers.
	 */
	if (sa->sa_nintr == 0)
		return;		/* No interrupts to service!? */

	(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_SERIAL,
				 magma_hard, sc);
	sc->ms_sicookie = softint_establish(SOFTINT_SERIAL, magma_soft, sc);
	if (sc->ms_sicookie == NULL) {
		aprint_normal("\n");
		aprint_error_dev(sc->ms_dev, "cannot establish soft int handler\n");
		return;
	}
	evcnt_attach_dynamic(&sc->ms_intrcnt, EVCNT_TYPE_INTR, NULL,
	    device_xname(sc->ms_dev), "intr");
}
示例#13
0
void
dmaattach_sbus(device_t parent, device_t self, void *aux)
{
	struct dma_softc *dsc = device_private(self);
	struct lsi64854_softc *sc = &dsc->sc_lsi64854;
	struct sbus_attach_args *sa = aux;
	struct sbus_softc *sbsc = device_private(parent);
	bus_space_tag_t sbt;
	int sbusburst, burst;
	int node;

	node = sa->sa_node;

	sc->sc_dev = self;
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	/* Map registers */
	if (sa->sa_npromvaddrs) {
		sbus_promaddr_to_handle(sa->sa_bustag,
		    sa->sa_promvaddrs[0], &sc->sc_regs);
	} else {
		if (sbus_bus_map(sa->sa_bustag,
		    sa->sa_slot, sa->sa_offset, sa->sa_size,
		    0, &sc->sc_regs) != 0) {
			aprint_error(": cannot map registers\n");
			return;
		}
	}

	/*
	 * Get transfer burst size from PROM and plug it into the
	 * controller registers. This is needed on the Sun4m; do
	 * others need it too?
	 */
	sbusburst = sbsc->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1; /* 1->16 */

	burst = prom_getpropint(node,"burst-sizes", -1);
	if (burst == -1)
		/* take SBus burst sizes */
		burst = sbusburst;

	/* Clamp at parent's burst sizes */
	burst &= sbusburst;
	sc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
		       (burst & SBUS_BURST_16) ? 16 : 0;

	if (device_is_a(self, "ledma")) {
		char *cabletype;
		uint32_t csr;
		/*
		 * Check to see which cable type is currently active and
		 * set the appropriate bit in the ledma csr so that it
		 * gets used. If we didn't netboot, the PROM won't have
		 * the "cable-selection" property; default to TP and then
		 * the user can change it via a "media" option to ifconfig.
		 */
		cabletype = prom_getpropstring(node, "cable-selection");
		csr = L64854_GCSR(sc);
		if (strcmp(cabletype, "tpe") == 0) {
			csr |= E_TP_AUI;
		} else if (strcmp(cabletype, "aui") == 0) {
			csr &= ~E_TP_AUI;
		} else {
			/* assume TP if nothing there */
			csr |= E_TP_AUI;
		}
		L64854_SCSR(sc, csr);
		delay(20000);	/* manual says we need a 20ms delay */
		sc->sc_channel = L64854_CHANNEL_ENET;
	} else {
		sc->sc_channel = L64854_CHANNEL_SCSI;
	}

	sbus_establish(&dsc->sc_sd, self);
	if ((sbt = bus_space_tag_alloc(sc->sc_bustag, dsc)) == NULL) {
		aprint_error(": out of memory\n");
		return;
	}
	sbt->sparc_intr_establish = dmabus_intr_establish;
	lsi64854_attach(sc);

	/* Attach children */
	for (node = firstchild(sa->sa_node); node; node = nextsibling(node)) {
		struct sbus_attach_args sax;
		sbus_setup_attach_args(sbsc, sbt, sc->sc_dmatag, node, &sax);
		(void)config_found(self, (void *)&sax, dmaprint_sbus);
		sbus_destroy_attach_args(&sax);
	}
}
示例#14
0
文件: fhc.c 项目: ryo/netbsd-src
void
fhc_attach(struct fhc_softc *sc)
{
	int node0, node;
	u_int32_t ctrl;

	printf(" board %d: %s\n", sc->sc_board,
	    prom_getpropstring(sc->sc_node, "board-model"));

	sc->sc_cbt = fhc_alloc_bus_tag(sc);

	sc->sc_ign = sc->sc_board << 1;
	bus_space_write_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN, sc->sc_ign);
	sc->sc_ign = bus_space_read_4(sc->sc_bt, sc->sc_ireg, FHC_I_IGN);

	ctrl = bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL);
	if (!sc->sc_is_central)
		ctrl |= FHC_P_CTRL_IXIST;
	ctrl &= ~(FHC_P_CTRL_AOFF | FHC_P_CTRL_BOFF | FHC_P_CTRL_SLINE);
	bus_space_write_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL, ctrl);
	bus_space_read_4(sc->sc_bt, sc->sc_preg, FHC_P_CTRL);

	/* clear interrupts */
	bus_space_write_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR, 0);
	bus_space_read_4(sc->sc_bt, sc->sc_freg, FHC_F_ICLR);
	bus_space_write_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR, 0);
	bus_space_read_4(sc->sc_bt, sc->sc_sreg, FHC_S_ICLR);
	bus_space_write_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR, 0);
	bus_space_read_4(sc->sc_bt, sc->sc_ureg, FHC_U_ICLR);
	bus_space_write_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR, 0);
	bus_space_read_4(sc->sc_bt, sc->sc_treg, FHC_T_ICLR);

	prom_getprop(sc->sc_node, "ranges", sizeof(struct fhc_range),
	    &sc->sc_nrange, (void **)&sc->sc_range);

	node0 = firstchild(sc->sc_node);
	for (node = node0; node; node = nextsibling(node)) {
		struct fhc_attach_args fa;

#if 0
		if (!checkstatus(node))
			continue;
#endif

		bzero(&fa, sizeof(fa));

		fa.fa_node = node;
		fa.fa_bustag = sc->sc_cbt;

		if (fhc_get_string(fa.fa_node, "name", &fa.fa_name)) {
			printf("can't fetch name for node 0x%x\n", node);
			continue;
		}
		prom_getprop(node, "reg", sizeof(struct fhc_reg),
		    &fa.fa_nreg, (void **)&fa.fa_reg);
		prom_getprop(node, "interrupts", sizeof(int),
		    &fa.fa_nintr, (void **)&fa.fa_intr);
		prom_getprop(node, "address", sizeof(*fa.fa_promvaddrs),
		    &fa.fa_npromvaddrs, (void **)&fa.fa_promvaddrs);

		(void)config_found(sc->sc_dev, (void *)&fa, fhc_print);

		if (fa.fa_name != NULL)
			free(fa.fa_name, M_DEVBUF);
		if (fa.fa_reg != NULL)
			free(fa.fa_reg, M_DEVBUF);
		if (fa.fa_intr != NULL)
			free(fa.fa_intr, M_DEVBUF);
		if (fa.fa_promvaddrs != NULL)
			free(fa.fa_promvaddrs, M_DEVBUF);
	}
}