Exemplo n.º 1
0
/*
 * 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);
}
Exemplo n.º 2
0
/*
 * Verify target ID is valid (exists in the OPENPROM tree), as
 * listed from node ID sid forward.
 */
static int
openpromcheckid(int sid, int tid)
{

	for (; sid != 0; sid = nextsibling(sid))
		if (sid == tid || openpromcheckid(firstchild(sid), tid))
			return (1);

	return (0);
}
Exemplo n.º 3
0
static void
cpuunit_attach(device_t parent, device_t self, void *aux)
{
	struct cpuunit_softc *sc = device_private(self);
	struct mainbus_attach_args *ma = aux;
	int node, error;
	bus_space_tag_t sbt;

	sc->sc_node = ma->ma_node;
	sc->sc_st = ma->ma_bustag;

	sc->sc_device_id = prom_getpropint(sc->sc_node, "device-id", -1);
	sc->sc_board = prom_getpropint(sc->sc_node, "board#", -1);

	printf(": board #%d, ID %d\n", sc->sc_board, sc->sc_device_id);

	/*
	 * Initialize the bus space tag we pass on to our children.
	 */
	sbt = sc->sc_bustag = malloc(sizeof(*sbt), M_DEVBUF, M_WAITOK);
	memcpy(sbt, sc->sc_st, sizeof(*sbt));
	sbt->cookie = sc;
	sbt->parent = sc->sc_st;
	sbt->nranges = 0;
	sbt->ranges = NULL;

	/*
	 * Collect address translations from the OBP.
	 */
	error = prom_getprop(sc->sc_node, "ranges",
	    sizeof(struct openprom_range), &sbt->nranges, &sbt->ranges);
	if (error) {
		printf("%s: error %d getting \"ranges\" property\n",
		    device_xname(self), error);
		panic("cpuunit_attach");
	}

	/* Attach the CPU (and possibly bootbus) child nodes. */
	for (node = firstchild(sc->sc_node); node != 0;
	     node = nextsibling(node)) {
		struct cpuunit_attach_args cpua;

		if (cpuunit_setup_attach_args(sc, sbt, node, &cpua))
			panic("cpuunit_attach: failed to set up attach args");

		(void) config_found(self, &cpua, cpuunit_print);

		cpuunit_destroy_attach_args(&cpua);
	}
}
Exemplo n.º 4
0
static void
central_attach(device_t parent, device_t self, void *aux)
{
	struct central_softc *sc = device_private(self);
	struct mainbus_attach_args *ma = aux;
	int node0, node;

	sc->sc_bt = ma->ma_bustag;
	sc->sc_node = ma->ma_node;
	sc->sc_cbt = central_alloc_bus_tag(sc);

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

	printf("\n");

	node0 = firstchild(sc->sc_node);
	for (node = node0; node; node = nextsibling(node)) {
		struct central_attach_args ca;

		bzero(&ca, sizeof(ca));
		ca.ca_node = node;
		ca.ca_bustag = sc->sc_cbt;
		if (central_get_string(ca.ca_node, "name", &ca.ca_name)) {
			printf("can't fetch name for node 0x%x\n", node);
			continue;
		}

		prom_getprop(node, "reg", sizeof(struct central_reg),
		    &ca.ca_nreg, (void **)&ca.ca_reg);

		(void)config_found(self, (void *)&ca, central_print);

		if (ca.ca_name != NULL)
			free(ca.ca_name, M_DEVBUF);
	}
}
Exemplo n.º 5
0
int
openpromioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
{
	struct opiocdesc *op;
	int node, optionsnode, len, ok, error, s;
	char *name, *value, *nextprop;

	optionsnode = prom_getoptionsnode();

	/* All too easy... */
	if (cmd == OPIOCGETOPTNODE) {
		*(int *)data = optionsnode;
		return (0);
	}

	/* Verify node id */
	op = (struct opiocdesc *)data;
	node = op->op_nodeid;
	if (node != 0 && node != lastnode && node != optionsnode) {
		/* Not an easy one, must search for it */
		s = splhigh();
		ok = openpromcheckid(findroot(), node);
		splx(s);
		if (!ok)
			return (EINVAL);
		lastnode = node;
	}

	name = value = NULL;
	error = 0;
	switch (cmd) {

	case OPIOCGET:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		s = splhigh();
		len = prom_proplen(node, name);
		splx(s);
		if (len > op->op_buflen) {
			error = ENOMEM;
			break;
		}
		op->op_buflen = len;
		/* -1 means no entry; 0 means no value */
		if (len <= 0)
			break;
		value = malloc(len, M_TEMP, M_WAITOK);
		s = splhigh();
		error = prom_getprop(node, name, 1, &len, &value);
		splx(s);
		if (error != 0)
			break;
		error = copyout(value, op->op_buf, len);
		break;

	case OPIOCSET:
		if ((flags & FWRITE) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		error = openpromgetstr(op->op_buflen, op->op_buf, &value);
		if (error)
			break;
		s = splhigh();
		len = prom_setprop(node, name, value, op->op_buflen + 1);
		splx(s);
		if (len != op->op_buflen)
			error = EINVAL;
		break;

	case OPIOCNEXTPROP:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		s = splhigh();
		nextprop = prom_nextprop(node, name);
		splx(s);
		len = strlen(nextprop);
		if (len > op->op_buflen)
			len = op->op_buflen;
		else
			op->op_buflen = len;
		error = copyout(nextprop, op->op_buf, len);
		break;

	case OPIOCGETNEXT:
		if ((flags & FREAD) == 0)
			return (EBADF);
		s = splhigh();
		node = nextsibling(node);
		splx(s);
		*(int *)data = lastnode = node;
		break;

	case OPIOCGETCHILD:
		if ((flags & FREAD) == 0)
			return (EBADF);
		if (node == 0)
			return (EINVAL);
		s = splhigh();
		node = firstchild(node);
		splx(s);
		*(int *)data = lastnode = node;
		break;

	case OPIOCFINDDEVICE:
		if ((flags & FREAD) == 0)
			return (EBADF);
		error = openpromgetstr(op->op_namelen, op->op_name, &name);
		if (error)
			break;
		node = prom_finddevice(name);
		if (node == 0 || node == -1) {
			error = ENOENT;
			break;
		}
		op->op_nodeid = lastnode = node;
		break;

	default:
		return (ENOTTY);
	}

	if (name)
		free(name, M_TEMP);
	if (value)
		free(value, M_TEMP);

	return (error);
}
Exemplo n.º 6
0
/*
 * Attach all the sub-devices we can find
 */
void
lebufattach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct lebuf_softc *sc = (void *)self;
	int node;
	int sbusburst;
	struct sparc_bus_space_tag *sbt;
	bus_space_handle_t bh;

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

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

	/*
	 * This device's "register space" is just a buffer where the
	 * Lance ring-buffers can be stored. Note the buffer's location
	 * and size, so the `le' driver can pick them up.
	 */
	sc->sc_buffer = (void *)bus_space_vaddr(sa->sa_bustag, bh);
	sc->sc_bufsiz = sa->sa_size;

	node = sc->sc_node = sa->sa_node;

	/*
	 * Get transfer burst size from PROM
	 */
	sbusburst = ((struct sbus_softc *)parent)->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1; /* 1->16 */

	sc->sc_burst = getpropint(node, "burst-sizes", -1);
	if (sc->sc_burst == -1)
		/* take SBus burst sizes */
		sc->sc_burst = sbusburst;

	/* Clamp at parent's burst sizes */
	sc->sc_burst &= sbusburst;

	/* Allocate a bus tag */
	sbt = malloc(sizeof(*sbt), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (sbt == NULL) {
		printf("%s: attach: out of memory\n", self->dv_xname);
		return;
	}

	printf(": %dK memory\n", sc->sc_bufsiz / 1024);

	sbt->cookie = sc;
	sbt->parent = sc->sc_bustag;
	sbt->asi = sbt->parent->asi;
	sbt->sasi = sbt->parent->sasi;

	/* search through children */
	for (node = firstchild(node); node; node = nextsibling(node)) {
		struct sbus_attach_args sa;
		sbus_setup_attach_args((struct sbus_softc *)parent,
		    sbt, sc->sc_dmatag, node, &sa);
		(void)config_found(&sc->sc_dev, (void *)&sa, lebufprint);
		sbus_destroy_attach_args(&sa);
	}
}
Exemplo n.º 7
0
void
fhc_attach(struct fhc_softc *sc)
{
	int node0, node;
	u_int32_t ctrl;

	printf(" board %d: %s\n", sc->sc_board,
	    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);

	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;

		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;
		}
		getprop(node, "reg", sizeof(struct fhc_reg),
		    &fa.fa_nreg, (void **)&fa.fa_reg);
		getprop(node, "interrupts", sizeof(int),
		    &fa.fa_nintr, (void **)&fa.fa_intr);
		getprop(node, "address", sizeof(*fa.fa_promvaddrs),
		    &fa.fa_npromvaddrs, (void **)&fa.fa_promvaddrs);

		(void)config_found(&sc->sc_dv, (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_nintr != NULL)
			free(fa.fa_intr, M_DEVBUF);
		if (fa.fa_promvaddrs != NULL)
			free(fa.fa_promvaddrs, M_DEVBUF);
	}

	sc->sc_blink.bl_func = fhc_led_blink;
	sc->sc_blink.bl_arg = sc;
	blink_led_register(&sc->sc_blink);
}
Exemplo n.º 8
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);
	}
}