Exemplo n.º 1
0
void
fb_setsize(struct sunfb *sf, int def_depth, int def_width, int def_height,
    int node, int unused)
{
	int def_linebytes;

	sf->sf_depth = getpropint(node, "depth", def_depth);
	sf->sf_width = getpropint(node, "width", def_width);
	sf->sf_height = getpropint(node, "height", def_height);

	def_linebytes =
	    roundup(sf->sf_width, sf->sf_depth) * sf->sf_depth / 8;
	sf->sf_linebytes = getpropint(node, "linebytes", def_linebytes);
	/*
	 * XXX If we are configuring a board in a wider depth level
	 * than the mode it is currently operating in, the PROM will
	 * return a linebytes property tied to the current depth value,
	 * which is NOT what we are relying upon!
	 */
	if (sf->sf_linebytes < (sf->sf_width * sf->sf_depth) / 8) {
		sf->sf_linebytes = def_linebytes;
	}

	sf->sf_fbsize = sf->sf_height * sf->sf_linebytes;
}
Exemplo n.º 2
0
int
vbus_intr_map(int node, int ino, uint64_t *sysino)
{
	int *imap = NULL, nimap;
	int *reg = NULL, nreg;
	int *imap_mask;
	int parent;
	int address_cells, interrupt_cells;
	uint64_t devhandle;
	uint64_t devino;
	int len;
	int err;

	parent = OF_parent(node);

	address_cells = getpropint(parent, "#address-cells", 2);
	interrupt_cells = getpropint(parent, "#interrupt-cells", 1);
	KASSERT(interrupt_cells == 1);

	len = OF_getproplen(parent, "interrupt-map-mask");
	if (len < (address_cells + interrupt_cells) * sizeof(int))
		return (-1);
	imap_mask = malloc(len, M_DEVBUF, M_NOWAIT);
	if (imap_mask == NULL)
		return (-1);
	if (OF_getprop(parent, "interrupt-map-mask", imap_mask, len) != len)
		return (-1);

	getprop(parent, "interrupt-map", sizeof(int), &nimap, (void **)&imap);
	getprop(node, "reg", sizeof(*reg), &nreg, (void **)&reg);
	if (nreg < address_cells)
		return (-1);

	while (nimap >= address_cells + interrupt_cells + 2) {
		if (vbus_cmp_cells(imap, reg, imap_mask, address_cells) &&
		    vbus_cmp_cells(&imap[address_cells], &ino,
		    &imap_mask[address_cells], interrupt_cells)) {
			node = imap[address_cells + interrupt_cells];
			devino = imap[address_cells + interrupt_cells + 1];

			free(reg, M_DEVBUF, 0);
			reg = NULL;

			getprop(node, "reg", sizeof(*reg), &nreg, (void **)&reg);
			devhandle = reg[0] & 0x0fffffff;

			err = hv_intr_devino_to_sysino(devhandle, devino, sysino);
			if (err != H_EOK)
				return (-1);

			KASSERT(*sysino == INTVEC(*sysino));
			return (0);
		}
		imap += address_cells + interrupt_cells + 2;
		nimap -= address_cells + interrupt_cells + 2;
	}

	return (-1);
}
Exemplo n.º 3
0
void
tcx_accel_init(struct tcx_softc *sc, struct confargs *ca)
{
	int stipple_align, regno;

	/*
	 * On S24, try and map raw blit and raw stipple spaces.
	 * We prefer the raw spaces so that we can eventually switch
	 * between 8 bit and 24 bit modes with blitter operations.
	 *
	 * However, on 8-bit TCX, these spaces are missing (and empty!),
	 * so we should fallback to non-raw spaces in this case.
	 *
	 * Since this frame buffer can only exist on SS4 and SS5,
	 * we can rely upon the fact this code will only run on sun4m,
	 * and use stda() bypassing the MMU to access these spaces,
	 * instead of mapping them (8MB KVA each, after all, even more
	 * on an SS4 with the resolution extender VSIMM).
	 */

	sc->sc_blit_width = getpropint(ca->ca_ra.ra_node, "blit-width", 0);
	if (sc->sc_blit_width > 5)
		sc->sc_blit_width = 5;	/* paranoia */
	if (sc->sc_blit_width <= 3)	/* not worth until more than 8 pixels */
		sc->sc_blit_width = 0;
	else {
		sc->sc_blit_width = 1 << sc->sc_blit_width;

		regno = sc->sc_cplane == 0 ? TCX_REG_BLIT : TCX_REG_RBLIT;
		if (ca->ca_ra.ra_reg[regno].rr_len >=
		    sc->sc_sunfb.sf_fbsize * 8)
			sc->sc_blit = (paddr_t)ca->ca_ra.ra_reg[regno].rr_paddr;
	}

	/*
	 * Do not assume the stipple space is usable unless there is a
	 * `stipple-align' property.  Also, don't try to use it if the
	 * alignment is not 32 - our code may not behave correctly.
	 */

	stipple_align = getpropint(ca->ca_ra.ra_node, "stipple-align", 0);
	if (stipple_align == 5) {
		regno = sc->sc_cplane == 0 ? TCX_REG_STIP : TCX_REG_RSTIP;
		if (ca->ca_ra.ra_reg[regno].rr_len >=
		    sc->sc_sunfb.sf_fbsize * 8)
			sc->sc_stipple =
			    (paddr_t)ca->ca_ra.ra_reg[regno].rr_paddr;
	}
}
Exemplo n.º 4
0
void
leattach_lebuffer(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct le_softc *lesc = (struct le_softc *)self;
	struct am7990_softc *sc = &lesc->sc_am7990;
	struct lebuf_softc *lebuf = (struct lebuf_softc *)parent;
	/* XXX the following declarations should be elsewhere */
	extern void myetheraddr(u_char *);

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

	if (sbus_bus_map(sa->sa_bustag,
	    sa->sa_slot, sa->sa_offset, sa->sa_size,
	    0, 0, &lesc->sc_reg)) {
		printf(": cannot map registers\n");
		return;
	}

	sc->sc_mem = lebuf->sc_buffer;
	sc->sc_memsize = lebuf->sc_bufsiz;
	sc->sc_addr = 0; /* Lance view is offset by buffer location */
	lebuf->attached = 1;

	/* That old black magic... */
	sc->sc_conf3 = getpropint(sa->sa_node, "busmaster-regval",
	    LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON);

	myetheraddr(sc->sc_arpcom.ac_enaddr);

	sc->sc_copytodesc = am7990_copytobuf_contig;
	sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
	sc->sc_copytobuf = am7990_copytobuf_contig;
	sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
	sc->sc_zerobuf = am7990_zerobuf_contig;

	sc->sc_rdcsr = le_lebuffer_rdcsr;
	sc->sc_wrcsr = le_lebuffer_wrcsr;

	am7990_config(&lesc->sc_am7990);

	/* Establish interrupt handler */
	if (sa->sa_nintr != 0)
		(void)bus_intr_establish(lesc->sc_bustag, sa->sa_pri,
		    IPL_NET, 0, am7990_intr, sc, self->dv_xname);
}
Exemplo n.º 5
0
void
zx_attach(struct device *parent, struct device *self, void *args)
{
	struct zx_softc *sc = (struct zx_softc *)self;
	struct sbus_attach_args *sa = args;
	struct rasops_info *ri;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, isconsole = 0;
	const char *nam;

	bt = sa->sa_bustag;
	ri = &sc->sc_sunfb.sf_ro;
	node = sa->sa_node;

	/*
	 * Map the various parts of the card.
	 */
	sc->sc_bustag = bt;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR,
	    sizeof(struct zx_command), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map command registers\n");
		return;
	}
	sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0,
	    sizeof(struct zx_draw), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map ss0 drawing registers\n");
		return;
	}
	sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1,
	    sizeof(struct zx_draw_ss1), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map ss1 drawing registers\n");
		return;
	}
	sc->sc_zd_ss1 = (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS,
	    sizeof(struct zx_cross), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map cross registers\n");
		return;
	}
	sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR,
	    sizeof(struct zx_cursor), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf(": couldn't map cursor registers\n");
		return;
	}
	sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh);

	nam = getpropstring(node, "model");
	if (*nam == '\0')
		nam = sa->sa_name;
	printf(": %s", nam);

	isconsole = node == fbnode;

	/*
	 * The console is using the 8-bit overlay plane, while the prom
	 * will correctly report 32 bit depth.
	 * The following is an equivalent for
	 *    fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
	 * forcing the depth value not to be overwritten.
	 * Furthermore, the linebytes value is in fact 8192 bytes.
	 */
	sc->sc_sunfb.sf_depth = 8;
	sc->sc_sunfb.sf_width = getpropint(node, "width", 1152);
	sc->sc_sunfb.sf_height = getpropint(node, "height", 900);
	sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH;
	sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH;

	printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0,
	    round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR,
	    0, &bh) != 0) {
		printf("%s: couldn't map video memory\n", self->dv_xname);
		return;
	}
	ri->ri_bits = bus_space_vaddr(bt, bh);
	ri->ri_hw = sc;

	fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);

 	/*
	 * Watch out! rasops_init() invoked via fbwscons_init() did not
	 * compute ri_bits correctly when centering the display, because
	 * it has been tricked with the low depth value.
	 * Recompute now.
 	 */
	ri->ri_emustride = ri->ri_emuwidth * 4;
	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
	ri->ri_pelbytes = 4;
	ri->ri_xscale = ri->ri_font->fontwidth * 4;
	ri->ri_bits = ri->ri_origbits;
	ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3;
	ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
	    ri->ri_stride;
	ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
	    / ri->ri_stride;
	ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
	    % ri->ri_stride) / 4);

	ri->ri_ops.copyrows = zx_copyrows;
	ri->ri_ops.copycols = zx_copycols;
	ri->ri_ops.eraserows = zx_eraserows;
	ri->ri_ops.erasecols = zx_erasecols;
	ri->ri_ops.putchar = zx_putchar;
	ri->ri_do_cursor = zx_do_cursor;

	if (isconsole) {
		/* zx_reset() below will clear screen, so restart at 1st row */
		fbwscons_console_init(&sc->sc_sunfb, 0);
	}

	/* reset cursor & frame buffer controls */
	zx_reset(sc, WSDISPLAYIO_MODE_EMUL);

	/* enable video */
	zx_burner(sc, 1, 0);

	fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole);
}
Exemplo n.º 6
0
void
fb_setsize(struct sunfb *sf, int def_depth, int def_width, int def_height,
    int node, int bustype)
{
	int def_linebytes;

	switch (bustype) {
	case BUS_VME16:
	case BUS_VME32:
	case BUS_OBIO:
#if defined(SUN4M)
		/* 4m may have SBus-like framebuffer on obio */
		if (CPU_ISSUN4M) {
			goto obpsize;
		}
#endif
		/* Set up some defaults. */
		sf->sf_width = def_width;
		sf->sf_height = def_height;
		sf->sf_depth = def_depth;

#if defined(SUN4)
		/*
		 * This is not particularly useful on Sun 4 VME framebuffers.
		 * The EEPROM only contains info about the built-in.
		 */
		if (CPU_ISSUN4 && bustype == BUS_OBIO) {
			struct eeprom *eep = (struct eeprom *)eeprom_va;

			if (ISSET(sf->sf_flags, FB_PFOUR)) {
				volatile u_int32_t pfour;
				u_int size;

				pfour = *sf->sf_pfour;

				/*
				 * Use the pfour register to determine
				 * the size.  Note that the cgsix and
				 * cgeight don't use this size encoding.
				 * In this case, we have to settle
				 * for the defaults we were provided
				 * with.
				 */
				if ((PFOUR_ID(pfour) == PFOUR_ID_COLOR24) ||
				    (PFOUR_ID(pfour) == PFOUR_ID_FASTCOLOR))
					size = 0x00; /* invalid */
				else
					size = PFOUR_SIZE(pfour);

				switch (size) {
				case PFOUR_SIZE_1152X900:
					sf->sf_width = 1152;
					sf->sf_height = 900;
					break;
				case PFOUR_SIZE_1024X1024:
					sf->sf_width = 1024;
					sf->sf_height = 1024;
					break;
				case PFOUR_SIZE_1280X1024:
					sf->sf_width = 1280;
					sf->sf_height = 1024;
					break;
				case PFOUR_SIZE_1600X1280:
					sf->sf_width = 1600;
					sf->sf_height = 1280;
					break;
				case PFOUR_SIZE_1440X1440:
					sf->sf_width = 1440;
					sf->sf_height = 1440;
					break;
				case PFOUR_SIZE_640X480:
					sf->sf_width = 640;
					sf->sf_height = 480;
					break;
				}
			} else if (eep != NULL) {
				switch (eep->eeScreenSize) {
				case EE_SCR_1152X900:
					sf->sf_width = 1152;
					sf->sf_height = 900;
					break;
				case EE_SCR_1024X1024:
					sf->sf_width = 1024;
					sf->sf_height = 1024;
					break;
				case EE_SCR_1600X1280:
					sf->sf_width = 1600;
					sf->sf_height = 1280;
					break;
				case EE_SCR_1440X1440:
					sf->sf_width = 1440;
					sf->sf_height = 1440;
					break;
				}
			}
		}
#endif /* SUN4 */
#if defined(SUN4M)
		if (CPU_ISSUN4M) {
			/* XXX: need code to find 4/600 vme screen size */
		}
#endif /* SUN4M */

		sf->sf_linebytes = (sf->sf_width * sf->sf_depth) / 8;
		break;

	case BUS_SBUS:
#if defined(SUN4M)
obpsize:
#endif
		sf->sf_depth = getpropint(node, "depth", def_depth);
		sf->sf_width = getpropint(node, "width", def_width);
		sf->sf_height = getpropint(node, "height", def_height);

		def_linebytes =
		    roundup(sf->sf_width, sf->sf_depth) * sf->sf_depth / 8;
		sf->sf_linebytes = getpropint(node, "linebytes", def_linebytes);

		/*
		 * XXX If we are configuring a board in a wider depth level
		 * than the mode it is currently operating in, the PROM will
		 * return a linebytes property tied to the current depth value,
		 * which is NOT what we are relying upon!
		 */
		if (sf->sf_linebytes < (sf->sf_width * sf->sf_depth) / 8)
			sf->sf_linebytes = def_linebytes;

		break;
	}

	sf->sf_fbsize = sf->sf_height * sf->sf_linebytes;
}
Exemplo n.º 7
0
void
com_ebus_attach(struct device *parent, struct device *self, void *aux)
{
	struct com_softc *sc = (void *)self;
	struct ebus_attach_args *ea = aux;
	int i, com_is_input, com_is_output;
	int node, port;
	char buf[32];

	sc->sc_iobase = EBUS_PADDR_FROM_REG(&ea->ea_regs[0]);
	/*
	 * Addresses that should be supplied by the prom:
	 *	- normal com registers
	 *	- ns873xx configuration registers
	 *	- DMA space
	 * The `com' driver does not use DMA accesses, so we can
	 * ignore that for now.  We should enable the com port in
	 * the ns873xx registers here. XXX
	 *
	 * Use the prom address if there.
	 */
	if (ea->ea_nvaddrs) {
		if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
		    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh) != 0) {
			printf(": can't map register space\n");
			return;
		}
		sc->sc_iot = ea->ea_memtag;
	} else if (ebus_bus_map(ea->ea_memtag, 0,
	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
		sc->sc_iot = ea->ea_memtag;
	} else if (ebus_bus_map(ea->ea_iotag, 0,
	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
		sc->sc_iot = ea->ea_iotag;
	} else {
		printf(": can't map register space\n");
               	return;
	}
	sc->sc_hwflags = 0;
	sc->sc_swflags = 0;
	sc->sc_frequency = BAUD_BASE;

	for (i = 0; i < ea->ea_nintrs; i++)
		bus_intr_establish(sc->sc_iot, ea->ea_intrs[i],
		    IPL_TTY, 0, comintr, sc, self->dv_xname);

	/*
	 * Figure out if we're the console.
	 *
	 * The Fujitsu SPARC Enterprise M4000/M5000/M8000/M9000 has a
	 * serial port on each I/O board and a pseudo console that is
	 * redirected to one of these serial ports.  The board number
	 * of the serial port in question is encoded in the "tty-port#"
	 * property of the pseudo console, so we figure out what our
	 * board number is by walking up the device tree, and check
	 * for a match.
	 */

	node = OF_instance_to_package(OF_stdin());
	com_is_input = (ea->ea_node == node);
	if (OF_getprop(node, "name", buf, sizeof(buf)) > 0 &&
	    strcmp(buf, "pseudo-console") == 0) {
		port = getpropint(node, "tty-port#", -1);
		node = OF_parent(OF_parent(ea->ea_node));
		com_is_input = (getpropint(node, "board#", -2) == port);
	}

	node = OF_instance_to_package(OF_stdout());
	com_is_output = (ea->ea_node == node);
	if (OF_getprop(node, "name", buf, sizeof(buf)) > 0 &&
	    strcmp(buf, "pseudo-console") == 0) {
		port = getpropint(node, "tty-port#", -1);
		node = OF_parent(OF_parent(ea->ea_node));
		com_is_output = (getpropint(node, "board#", -2) == port);
	}

	if (com_is_input || com_is_output) {
		struct consdev *cn_orig;
		int speed;

		speed = com_ebus_speed(ea);

		comconsioh = sc->sc_ioh;
		cn_orig = cn_tab;
		/* Attach com as the console. */
		if (comcnattach(sc->sc_iot, sc->sc_iobase, speed,
		    sc->sc_frequency,
		    ((TTYDEF_CFLAG & ~(CSIZE | PARENB))|CREAD | CS8 | HUPCL))) {
			printf("Error: comcnattach failed\n");
		}
		cn_tab = cn_orig;
		if (com_is_input) {
			cn_tab->cn_dev = /*XXX*/makedev(36, sc->sc_dev.dv_unit);
			cn_tab->cn_probe = comcnprobe;
			cn_tab->cn_init = comcninit;
			cn_tab->cn_getc = comcngetc;
			cn_tab->cn_pollc = comcnpollc;
		}
		if (com_is_output)
			cn_tab->cn_putc = comcnputc;
	}

	/*
	 * Apparently shoving too much data down the TX FIFO on the
	 * Fujitsu SPARC Enterprise M4000/M5000 causes a hardware
	 * fault.  Avoid this issue by setting the FIFO depth to 1.
	 * This will effectively disable the TX FIFO, but will still
	 * enable the RX FIFO, which is what we really care about.
	 */
	if (OF_getprop(ea->ea_node, "compatible", buf, sizeof(buf)) > 0 &&
	    strcmp(buf, "FJSV,su") == 0)
		sc->sc_uarttype = COM_UART_16550;

        if (OF_getproplen(ea->ea_node, "keyboard") == 0)
		printf(": keyboard");
	else if (OF_getproplen(ea->ea_node, "mouse") == 0)
		printf(": mouse");

	/* Now attach the driver */
	com_attach_subr(sc);
}
Exemplo n.º 8
0
/*
 * Attach an MGX frame buffer.
 * This will keep the frame buffer in the actual PROM mode, and attach
 * a wsdisplay child device to itself.
 */
void
mgxattach(struct device *parent, struct device *self, void *args)
{
	struct mgx_softc *sc = (struct mgx_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, fbsize;
	int isconsole;
	uint16_t chipid;

	bt = sa->sa_bustag;
	node = sa->sa_node;

	printf(": %s", getpropstring(node, "model"));

	isconsole = node == fbnode;

	/* Check registers */
	if (sa->sa_nreg < MGX_NREG) {
		printf("\n%s: expected %d registers, got %d\n",
		    self->dv_xname, MGX_NREG, sa->sa_nreg);
		return;
	}

	sc->sc_bustag = bt;
	if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_CRTC].sbr_slot,
	    sa->sa_reg[MGX_REG_CRTC].sbr_offset, PAGE_SIZE,
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
		return;
	}
	sc->sc_vidc = (vaddr_t)bus_space_vaddr(bt, bh);

	sc->sc_bustag = bt;
	if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_ATREG].sbr_slot,
	    sa->sa_reg[MGX_REG_ATREG].sbr_offset + MGX_REG_ATREG_OFFSET,
	    MGX_REG_ATREG_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
		/* XXX unmap vidc */
		return;
	}
	sc->sc_xreg = (vaddr_t)bus_space_vaddr(bt, bh);

	/*
	 * Check the chip ID. If it's not an AT24, prefer not to access
	 * the extended registers at all.
	 */
	chipid = mgx_read_2(sc->sc_xreg, ATR_ID);
	if (chipid != ID_AT24) {
		sc->sc_xreg = (vaddr_t)0;
	}

	/* enable video */
	mgx_burner(sc, 1, 0);

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);

	/* Sanity check frame buffer memory */
	fbsize = getpropint(node, "fb_size", 0);
	if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) {
		printf("\n%s: expected at least %d bytes of vram, but card "
		    "only provides %d\n",
		    self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize);
		return;
	}

	/* Map the frame buffer memory area we're interested in */
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
	    sa->sa_reg[MGX_REG_VRAM8].sbr_offset);
	if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
	    sa->sa_reg[MGX_REG_VRAM8].sbr_offset,
	    round_page(sc->sc_sunfb.sf_fbsize),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map video memory\n", self->dv_xname);
		/* XXX unmap vidc and xreg */
		return;
	}
	sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
	sc->sc_sunfb.sf_ro.ri_hw = sc;

	printf(", %dx%d\n",
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	fbwscons_init(&sc->sc_sunfb, 0, isconsole);

	bzero(sc->sc_cmap, sizeof(sc->sc_cmap));
	fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor);

	if (chipid != ID_AT24) {
		printf("%s: unexpected engine id %04x\n",
		    self->dv_xname, chipid);
	}

	mgx_ras_init(sc, chipid);

	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &mgx_accessops, isconsole);
}
Exemplo n.º 9
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.º 10
0
void
bppattach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct bpp_softc *dsc = (void *)self;
	struct lsi64854_softc *sc = &dsc->sc_lsi64854;
	int burst, sbusburst;
	int node;

	node = sa->sa_node;

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

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

	/* Check for the interrupt property */
	if (sa->sa_nintr == 0) {
		printf(": no interrupt property\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 = ((struct sbus_softc *)parent)->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1; /* 1->16 */

	burst = 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;

	/* Initialize the DMA channel */
	sc->sc_channel = L64854_CHANNEL_PP;
	if (lsi64854_attach(sc) != 0)
		return;

	/* Establish interrupt handler */
	sc->sc_intrchain = bppintr;
	sc->sc_intrchainarg = dsc;
	(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0,
	    bppintr, sc, self->dv_xname);

	/* Allocate buffer XXX - should actually use dmamap_uio() */
	dsc->sc_bufsz = 1024;
	dsc->sc_buf = malloc(dsc->sc_bufsz, M_DEVBUF, M_NOWAIT);

	/* XXX read default state */
    {
	bus_space_handle_t h = sc->sc_regs;
	struct hwstate *hw = &dsc->sc_hwstate;
	int ack_rate = sa->sa_frequency/1000000;

	hw->hw_hcr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_HCR);
	hw->hw_ocr = bus_space_read_2(sc->sc_bustag, h, L64854_REG_OCR);
	hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR);
	hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR);

	DPRINTF(("bpp: hcr %x ocr %x tcr %x or %x\n",
		 hw->hw_hcr, hw->hw_ocr, hw->hw_tcr, hw->hw_or));
	/* Set these to sane values */
	hw->hw_hcr = ((ack_rate<<BPP_HCR_DSS_SHFT)&BPP_HCR_DSS_MASK)
		| ((ack_rate<<BPP_HCR_DSW_SHFT)&BPP_HCR_DSW_MASK);
	hw->hw_ocr |= BPP_OCR_ACK_OP;
    }
}
Exemplo n.º 11
0
void
agtenattach(struct device *parent, struct device *self, void *args)
{
	struct agten_softc *sc = (struct agten_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, isconsole;
	char *nam;

	bt = sa->sa_bustag;
	node = sa->sa_node;
	nam = getpropstring(node, "model");
	printf(": model %s", nam);

	isconsole = node == fbnode;

	/*
	 * Map the various beasts of this card we are interested in.
	 */

	sc->sc_bustag = bt;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);

	sc->sc_physoffset =
	    (off_t)getpropint(node, "i128_fb_physaddr", 0x8000000);

	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + sc->sc_physoffset,
	    getpropint(node, "i128_fb_size", 0x400000), BUS_SPACE_MAP_LINEAR,
	    0, &bh) != 0) {
		printf("\n%s: couldn't map video memory\n", self->dv_xname);
		return;
	}
	sc->sc_i128_fb = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    getpropint(node, "p9100_reg_physaddr", 0x10a0000), 0x4000,
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("\n%s: couldn't map control registers\n", self->dv_xname);
		return;
	}
	sc->sc_p9100 = bus_space_vaddr(bt, bh);

	/*
	 * For some reason the agten does not use the canonical name for
	 * properties, but uses an ffb_ prefix; and the linebytes property is
	 * missing.
	 * The following is a specific version of
	 *   fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, BUS_SBUS);
	 * using the correct property names.
	 */
#ifdef notyet
	sc->sc_sunfb.sf_depth = 32;
#else
	sc->sc_sunfb.sf_depth = getpropint(node, "ffb_depth", 8);
#endif
	sc->sc_sunfb.sf_width = getpropint(node, "ffb_width", 1152);
	sc->sc_sunfb.sf_height = getpropint(node, "ffb_height", 900);
	sc->sc_sunfb.sf_linebytes =
	    roundup(sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_depth) *
	        sc->sc_sunfb.sf_depth / 8;
	sc->sc_sunfb.sf_fbsize =
	    sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;

	printf(", %dx%d, depth %d\n",
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
	    sc->sc_sunfb.sf_depth);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_i128_fb;
	
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, 0, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, agten_setcolor);

	if (isconsole)
		fbwscons_console_init(&sc->sc_sunfb, -1);

	fbwscons_attach(&sc->sc_sunfb, &agten_accessops, isconsole);
}
Exemplo n.º 12
0
void    
cs4231_attach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct cs4231_softc *sc = (struct cs4231_softc *)self;
	int node;
	u_int32_t sbusburst, burst;

	node = sa->sa_node;

	/* Pass on the bus tags */
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	/* Make sure things are sane. */
	if (sa->sa_nintr != 1) {
		printf(": expected 1 interrupt, got %d\n", sa->sa_nintr);
		return;
	}
	if (sa->sa_nreg != 1) {
		printf(": expected 1 register set, got %d\n",
		    sa->sa_nreg);
		return;
	}

	if (bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_AUDIO, 0,
	    cs4231_intr, sc, self->dv_xname) == NULL) {
		printf(": couldn't establish interrupt, pri %d\n",
		    INTLEV(sa->sa_pri));
		return;
	}

	if (sbus_bus_map(sa->sa_bustag,
	    sa->sa_reg[0].sbr_slot,
	    (bus_addr_t)sa->sa_reg[0].sbr_offset,
	    (bus_size_t)sa->sa_reg[0].sbr_size,
	    BUS_SPACE_MAP_LINEAR, 0, &sc->sc_regs) != 0) {
		printf(": couldn't map registers\n");
		return;
	}

	sbusburst = ((struct sbus_softc *)parent)->sc_burst;
	if (sbusburst == 0)
		sbusburst = SBUS_BURST_32 - 1;	/* 1->16 */
	burst = getpropint(node, "burst-sizes", -1);
	if (burst == -1)
		burst = sbusburst;
	sc->sc_burst = burst & sbusburst;

	printf("\n");

	audio_attach_mi(&cs4231_sa_hw_if, sc, &sc->sc_dev);

	/* Default to speaker, unmuted, reasonable volume */
	sc->sc_out_port = CSPORT_SPEAKER;
	sc->sc_in_port = CSPORT_MICROPHONE;
	sc->sc_mute[CSPORT_SPEAKER] = 1;
	sc->sc_mute[CSPORT_MONITOR] = 1;
	sc->sc_volume[CSPORT_SPEAKER].left = 192;
	sc->sc_volume[CSPORT_SPEAKER].right = 192;
}
Exemplo n.º 13
0
Arquivo: agten.c Projeto: MarginC/kame
void
agtenattach(struct device *parent, struct device *self, void *args)
{
	struct agten_softc *sc = (struct agten_softc *)self;
	struct confargs *ca = args;
	struct wsemuldisplaydev_attach_args waa;
	int node, isconsole;
	char *nam;

	sc->sc_sunfb.sf_flags = self->dv_cfdata->cf_flags;

	node = ca->ca_ra.ra_node;
	nam = getpropstring(node, "model");
	printf(": model %s", nam);

	isconsole = node == fbnode;

	sc->sc_phys = ca->ca_ra.ra_reg[0];

	/*
	 * Map the various beasts of this card we are interested in.
	 */

	sc->sc_physoffset =
	    (off_t)getpropint(node, "i128_fb_physaddr", 0x8000000);
	sc->sc_i128_fb = mapiodev(ca->ca_ra.ra_reg, sc->sc_physoffset,
	    getpropint(node, "i128_fb_size", 0x400000));
	sc->sc_dac = mapiodev(ca->ca_ra.ra_reg,
	    getpropint(node, "p9100_reg_physaddr", 0x10a0000) + 0x200,
	    0x800 - 0x200);

	/*
	 * For some reason the agten does not use the canonical name for
	 * properties, but uses an ffb_ prefix; and the linebytes property is
	 * missing.
	 * The following is a specific version of
	 *   fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, BUS_SBUS);
	 * using the correct property names.
	 */
#ifdef notyet
	sc->sc_sunfb.sf_depth = 32;
#else
	sc->sc_sunfb.sf_depth = getpropint(node, "ffb_depth", 8);
#endif
	sc->sc_sunfb.sf_width = getpropint(node, "ffb_width", 1152);
	sc->sc_sunfb.sf_height = getpropint(node, "ffb_height", 900);
	sc->sc_sunfb.sf_linebytes =
	    roundup(sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_depth) *
	        sc->sc_sunfb.sf_depth / 8;
	sc->sc_sunfb.sf_fbsize =
	    sc->sc_sunfb.sf_height * sc->sc_sunfb.sf_linebytes;

	printf(", %dx%d, depth %d\n",
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
	    sc->sc_sunfb.sf_depth);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_i128_fb;
	
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, agten_setcolor);

	agten_stdscreen.capabilities = sc->sc_sunfb.sf_ro.ri_caps;
	agten_stdscreen.nrows = sc->sc_sunfb.sf_ro.ri_rows;
	agten_stdscreen.ncols = sc->sc_sunfb.sf_ro.ri_cols;
	agten_stdscreen.textops = &sc->sc_sunfb.sf_ro.ri_ops;

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb, &agten_stdscreen, -1,
		    NULL);
	}

	sbus_establish(&sc->sc_sd, &sc->sc_sunfb.sf_dev);

	waa.console = isconsole;
	waa.scrdata = &agten_screenlist;
	waa.accessops = &agten_accessops;
	waa.accesscookie = sc;
	config_found(self, &waa, wsemuldisplaydevprint);
}
Exemplo n.º 14
0
void
leattach_sbus(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct le_softc *lesc = (struct le_softc *)self;
	struct lance_softc *sc = &lesc->sc_am7990.lsc;
	bus_dma_tag_t dmatag;
	/* XXX the following declarations should be elsewhere */
	extern void myetheraddr(u_char *);
	extern struct cfdriver lebuffer_cd;

	lesc->sc_bustag = sa->sa_bustag;
	lesc->sc_dmatag = dmatag = sa->sa_dmatag;

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
	    BUS_SPACE_MAP_LINEAR, 0, &lesc->sc_reg) != 0) {
		printf(": cannot map registers\n");
		return;
	}

	/*
	 * Look for an "unallocated" lebuffer and pair it with
	 * this `le' device on the assumption that we're on
	 * a pre-historic ROM that doesn't establish le<=>lebuffer
	 * parent-child relationships.
	 */
	if (lebuffer_cd.cd_ndevs != 0) {
		struct lebuf_softc *lebuf;
		int i;

		for (i = 0; i < lebuffer_cd.cd_ndevs; i++) {
			lebuf = (struct lebuf_softc *)lebuffer_cd.cd_devs[i];
			if (lebuf == NULL || lebuf->attached != 0)
				continue;

			sc->sc_mem = lebuf->sc_buffer;
			sc->sc_memsize = lebuf->sc_bufsiz;
			/* Lance view is offset by buffer location */
			sc->sc_addr = 0;
			lebuf->attached = 1;

			/* That old black magic... */
			sc->sc_conf3 = getpropint(sa->sa_node,
			    "busmaster-regval",
			    LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON);
			break;
		}
	}

	if (sc->sc_mem == 0) {
		bus_dma_segment_t seg;
		int rseg, error;

		/* Get a DMA handle */
		if ((error = bus_dmamap_create(dmatag, MEMSIZE, 1, MEMSIZE, 0,
		     BUS_DMA_NOWAIT|BUS_DMA_24BIT, &lesc->sc_dmamap)) != 0) {
			printf(": DMA map create error %d\n", error);
			return;
		}

		/* Allocate DMA buffer */
		if ((error = bus_dmamem_alloc(dmatag, MEMSIZE, 0, 0,
		     &seg, 1, &rseg, BUS_DMA_NOWAIT|BUS_DMA_24BIT)) != 0){
			printf(": DMA buffer allocation error %d\n", error);
			return;
		}

		/* Map DMA buffer into kernel space */
		if ((error = bus_dmamem_map(dmatag, &seg, rseg, MEMSIZE,
		     (caddr_t *)&sc->sc_mem,
		     BUS_DMA_NOWAIT|BUS_DMA_COHERENT|BUS_DMA_24BIT)) != 0) {
			printf(": DMA buffer map error %d\n", error);
			bus_dmamem_free(lesc->sc_dmatag, &seg, rseg);
			return;
		}

		/* Load DMA buffer */
		if ((error = bus_dmamap_load(dmatag, lesc->sc_dmamap, sc->sc_mem,
		    MEMSIZE, NULL, BUS_DMA_NOWAIT|BUS_DMA_COHERENT|BUS_DMA_24BIT)) != 0) {
			printf(": DMA buffer map load error %d\n", error);
			bus_dmamem_free(dmatag, &seg, rseg);
			bus_dmamem_unmap(dmatag, sc->sc_mem, MEMSIZE);
			return;
		}

		sc->sc_addr = lesc->sc_dmamap->dm_segs[0].ds_addr & 0xffffff;
		sc->sc_memsize = MEMSIZE;
		sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
	}

	myetheraddr(sc->sc_arpcom.ac_enaddr);

	sc->sc_supmedia = lemedia;
	sc->sc_nsupmedia = nitems(lemedia);
	sc->sc_defaultmedia = sc->sc_supmedia[sc->sc_nsupmedia - 1];

	sc->sc_copytodesc = lance_copytobuf_contig;
	sc->sc_copyfromdesc = lance_copyfrombuf_contig;
	sc->sc_copytobuf = lance_copytobuf_contig;
	sc->sc_copyfrombuf = lance_copyfrombuf_contig;
	sc->sc_zerobuf = lance_zerobuf_contig;

	sc->sc_rdcsr = le_sbus_rdcsr;
	sc->sc_wrcsr = le_sbus_wrcsr;

	am7990_config(&lesc->sc_am7990);

	/* Establish interrupt handler */
	if (sa->sa_nintr != 0)
		(void)bus_intr_establish(lesc->sc_bustag, sa->sa_pri,
		    IPL_NET, 0, am7990_intr, sc, self->dv_xname);
}
Exemplo n.º 15
0
void
beattach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct qec_softc *qec = (struct qec_softc *)parent;
	struct be_softc *sc = (struct be_softc *)self;
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	struct mii_data *mii = &sc->sc_mii;
	struct mii_softc *child;
	int node = sa->sa_node;
	bus_dma_tag_t dmatag = sa->sa_dmatag;
	bus_dma_segment_t seg;
	bus_size_t size;
	int instance;
	int rseg, error;
	u_int32_t v;
	extern void myetheraddr(u_char *);

	/* Pass on the bus tags */
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_dmatag = sa->sa_dmatag;

	if (sa->sa_nreg < 3) {
		printf("%s: only %d register sets\n",
		    self->dv_xname, sa->sa_nreg);
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    (bus_addr_t)sa->sa_reg[0].sbr_offset,
	    (bus_size_t)sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_cr) != 0) {
		printf("beattach: cannot map registers\n");
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
	    (bus_addr_t)sa->sa_reg[1].sbr_offset,
	    (bus_size_t)sa->sa_reg[1].sbr_size, 0, 0, &sc->sc_br) != 0) {
		printf("beattach: cannot map registers\n");
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[2].sbr_slot,
	    (bus_addr_t)sa->sa_reg[2].sbr_offset,
	    (bus_size_t)sa->sa_reg[2].sbr_size, 0, 0, &sc->sc_tr) != 0) {
		printf("beattach: cannot map registers\n");
		return;
	}

	sc->sc_qec = qec;
	sc->sc_qr = qec->sc_regs;

	sc->sc_rev = getpropint(node, "board-version", -1);
	printf(" rev %x", sc->sc_rev);

	bestop(sc);

	sc->sc_channel = getpropint(node, "channel#", -1);
	if (sc->sc_channel == -1)
		sc->sc_channel = 0;

	sc->sc_burst = getpropint(node, "burst-sizes", -1);
	if (sc->sc_burst == -1)
		sc->sc_burst = qec->sc_burst;

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

	/* Establish interrupt handler */
	if (sa->sa_nintr == 0 || bus_intr_establish(sa->sa_bustag, sa->sa_pri,
	    IPL_NET, 0, beintr, sc, self->dv_xname) == NULL) {
		printf(": no interrupt established\n");
		return;
	}

	myetheraddr(sc->sc_arpcom.ac_enaddr);
	printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));

	/*
	 * Allocate descriptor ring and buffers.
	 */

	/* for now, allocate as many bufs as there are ring descriptors */
	sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE;
	sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE;

	size =	QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
		QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
		sc->sc_rb.rb_ntbuf * BE_PKT_BUF_SZ +
		sc->sc_rb.rb_nrbuf * BE_PKT_BUF_SZ;

	/* Get a DMA handle */
	if ((error = bus_dmamap_create(dmatag, size, 1, size, 0,
	    BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
		printf("%s: DMA map create error %d\n", self->dv_xname, error);
		return;
	}

	/* Allocate DMA buffer */
	if ((error = bus_dmamem_alloc(sa->sa_dmatag, size, 0, 0,
	    &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
		printf("%s: DMA buffer alloc error %d\n",
			self->dv_xname, error);
		return;
	}

	/* Map DMA memory in CPU addressable space */
	if ((error = bus_dmamem_map(sa->sa_dmatag, &seg, rseg, size,
	    &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
		printf("%s: DMA buffer map error %d\n",
			self->dv_xname, error);
		bus_dmamem_free(sa->sa_dmatag, &seg, rseg);
		return;
	}

	/* Load the buffer */
	if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap,
	    sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) {
		printf("%s: DMA buffer map load error %d\n",
		    self->dv_xname, error);
		bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size);
		bus_dmamem_free(dmatag, &seg, rseg);
		return;
	}
	sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr;

	/*
	 * Initialize our media structures and MII info.
	 */
	mii->mii_ifp = ifp;
	mii->mii_readreg = be_mii_readreg;
	mii->mii_writereg = be_mii_writereg;
	mii->mii_statchg = be_mii_statchg;

	ifmedia_init(&mii->mii_media, 0, be_ifmedia_upd, be_ifmedia_sts);

	timeout_set(&sc->sc_tick_ch, be_tick, sc);

	/*
	 * Initialize transceiver and determine which PHY connection to use.
	 */
	be_mii_sync(sc);
	v = bus_space_read_4(sc->sc_bustag, sc->sc_tr, BE_TRI_MGMTPAL);

	instance = 0;

	if ((v & MGMT_PAL_EXT_MDIO) != 0) {

		mii_attach(&sc->sc_dev, mii, 0xffffffff, BE_PHY_EXTERNAL,
		    MII_OFFSET_ANY, 0);

		child = LIST_FIRST(&mii->mii_phys);
		if (child == NULL) {
			/* No PHY attached */
			ifmedia_add(&sc->sc_media,
			    IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance),
			    0, NULL);
			ifmedia_set(&sc->sc_media,
			    IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance));
		} else {
			/*
			 * Note: we support just one PHY on the external
			 * MII connector.
			 */
#ifdef DIAGNOSTIC
			if (LIST_NEXT(child, mii_list) != NULL) {
				printf("%s: spurious MII device %s attached\n",
				    sc->sc_dev.dv_xname,
				    child->mii_dev.dv_xname);
			}
#endif
			if (child->mii_phy != BE_PHY_EXTERNAL ||
			    child->mii_inst > 0) {
				printf("%s: cannot accommodate MII device %s"
				    " at phy %d, instance %d\n",
				    sc->sc_dev.dv_xname,
				    child->mii_dev.dv_xname,
				    child->mii_phy, child->mii_inst);
			} else {
				sc->sc_phys[instance] = child->mii_phy;
			}

			/*
			 * XXX - we can really do the following ONLY if the
			 * phy indeed has the auto negotiation capability!!
			 */
			ifmedia_set(&sc->sc_media,
			    IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));

			/* Mark our current media setting */
			be_pal_gate(sc, BE_PHY_EXTERNAL);
			instance++;
		}

	}

	if ((v & MGMT_PAL_INT_MDIO) != 0) {
		/*
		 * The be internal phy looks vaguely like MII hardware,
		 * but not enough to be able to use the MII device
		 * layer. Hence, we have to take care of media selection
		 * ourselves.
		 */

		sc->sc_mii_inst = instance;
		sc->sc_phys[instance] = BE_PHY_INTERNAL;

		/* Use `ifm_data' to store BMCR bits */
		ifmedia_add(&sc->sc_media,
		    IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,instance), 0, NULL);
		ifmedia_add(&sc->sc_media,
		    IFM_MAKEWORD(IFM_ETHER,IFM_100_TX,0,instance),
		    BMCR_S100, NULL);
		ifmedia_add(&sc->sc_media,
		    IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance), 0, NULL);

		printf("on-board transceiver at %s: 10baseT, 100baseTX, auto\n",
		    self->dv_xname);

		be_mii_reset(sc, BE_PHY_INTERNAL);
		/* Only set default medium here if there's no external PHY */
		if (instance == 0) {
			be_pal_gate(sc, BE_PHY_INTERNAL);
			ifmedia_set(&sc->sc_media,
			    IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));
		} else
			be_mii_writereg((void *)sc,
			    BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO);
	}

	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
	ifp->if_softc = sc;
	ifp->if_start = bestart;
	ifp->if_ioctl = beioctl;
	ifp->if_watchdog = bewatchdog;
	ifp->if_flags =
	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
	IFQ_SET_READY(&ifp->if_snd);

	/* Attach the interface. */
	if_attach(ifp);
	ether_ifattach(ifp);
}
Exemplo n.º 16
0
struct cpu_info *
alloc_cpuinfo(struct mainbus_attach_args *ma)
{
	paddr_t pa0, pa;
	vaddr_t va, va0;
	vsize_t sz = 8 * PAGE_SIZE;
	int portid;
	struct cpu_info *cpi, *ci;
	extern paddr_t cpu0paddr;

	portid = getpropint(ma->ma_node, "upa-portid", -1);
	if (portid == -1)
		portid = getpropint(ma->ma_node, "portid", -1);
	if (portid == -1)
		portid = getpropint(ma->ma_node, "cpuid", -1);
	if (portid == -1 && ma->ma_nreg > 0)
		portid = (ma->ma_reg[0].ur_paddr >> 32) & 0x0fffffff;
	if (portid == -1)
		panic("alloc_cpuinfo: portid");

	for (cpi = cpus; cpi != NULL; cpi = cpi->ci_next)
		if (cpi->ci_upaid == portid)
			return cpi;

	va = uvm_km_valloc_align(kernel_map, sz, 8 * PAGE_SIZE, 0);
	if (va == 0)
		panic("alloc_cpuinfo: no virtual space");
	va0 = va;

	pa0 = cpu0paddr;
	cpu0paddr += sz;

	for (pa = pa0; pa < cpu0paddr; pa += PAGE_SIZE, va += PAGE_SIZE)
		pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);

	pmap_update(pmap_kernel());

	cpi = (struct cpu_info *)(va0 + CPUINFO_VA - INTSTACK);

	memset((void *)va0, 0, sz);

	/*
	 * Initialize cpuinfo structure.
	 *
	 * Arrange pcb, idle stack and interrupt stack in the same
	 * way as is done for the boot CPU in pmap.c.
	 */
	cpi->ci_next = NULL;
	cpi->ci_curproc = NULL;
	cpi->ci_number = ncpus++;
	cpi->ci_upaid = portid;
	cpi->ci_fpproc = NULL;
#ifdef MULTIPROCESSOR
	cpi->ci_spinup = cpu_hatch;				/* XXX */
#else
	cpi->ci_spinup = NULL;
#endif

	cpi->ci_initstack = cpi;
	cpi->ci_paddr = pa0;
#ifdef SUN4V
	cpi->ci_mmfsa = pa0;
#endif
	cpi->ci_self = cpi;
	cpi->ci_node = ma->ma_node;

	sched_init_cpu(cpi);

	/*
	 * Finally, add itself to the list of active cpus.
	 */
	for (ci = cpus; ci->ci_next != NULL; ci = ci->ci_next)
		;
	ci->ci_next = cpi;
	return (cpi);
}