Esempio n. 1
0
void
fbwscons_init(struct sunfb *sf, int flags)
{
	struct rasops_info *ri = &sf->sf_ro;
	int cols, rows;

	/* ri_hw and ri_bits must have already been setup by caller */
	ri->ri_flg = RI_CENTER | RI_FULLCLEAR | flags;
	ri->ri_depth = sf->sf_depth;
	ri->ri_stride = sf->sf_linebytes;
	ri->ri_width = sf->sf_width;
	ri->ri_height = sf->sf_height;

	rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34);
	cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80);

	rasops_init(ri, rows, cols);

	if (sf->sf_depth == 8) {
		/*
		 * If we are running with an indexed palette, compensate
		 * the swap of black and white through ri_devcmap.
		 */
		ri->ri_devcmap[WSCOL_SUN_BLACK] = 0;
		ri->ri_devcmap[WSCOL_SUN_WHITE] = 0xffffffff;
	} else if (sf->sf_depth > 8) {
		/*
		 * If we are running on a direct color frame buffer,
		 * make the ``normal'' white the same as the highlighted
		 * white.
		 */
		ri->ri_devcmap[WSCOL_WHITE] = ri->ri_devcmap[WSCOL_WHITE + 8];
	}
}
Esempio n. 2
0
void
fbwscons_init(struct sunfb *sf, int flags)
{
	struct rasops_info *ri = &sf->sf_ro;
	int cols, rows;

	/* ri_hw and ri_bits must have already been setup by caller */
	ri->ri_flg = RI_CENTER | RI_FULLCLEAR | flags;
	ri->ri_depth = sf->sf_depth;
	ri->ri_stride = sf->sf_linebytes;
	ri->ri_width = sf->sf_width;
	ri->ri_height = sf->sf_height;

#if defined(SUN4C) || defined(SUN4M)
	if (CPU_ISSUN4COR4M) {
		rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34);
		cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80);
	}
#endif
#if defined(SUN4)
	if (CPU_ISSUN4) {
		struct eeprom *ep = (struct eeprom *)eeprom_va;

		if (ep != NULL) {
			rows = (u_short)ep->eeTtyRows;
			cols = (u_short)ep->eeTtyCols;
			/* deal with broken nvram contents... */
			if (rows <= 0)
				rows = 34;
			if (cols <= 0)
				cols = 80;
		} else {
			rows = 34;
			cols = 80;
		}
	}
#endif

	rasops_init(ri, rows, cols);

	if (sf->sf_depth == 8) {
		/*
		 * If we are running with an indexed palette, compensate
		 * the swap of black and white through ri_devcmap.
		 */
		ri->ri_devcmap[WSCOL_SUN_BLACK] = 0;
		ri->ri_devcmap[WSCOL_SUN_WHITE] = 0xffffffff;
	} else if (sf->sf_depth > 8) {
		/*
		 * If we are running on a direct color frame buffer,
		 * make the ``normal'' white the same as the hilighted
		 * white.
		 */
		ri->ri_devcmap[WSCOL_WHITE] = ri->ri_devcmap[WSCOL_WHITE + 8];
	}
}
Esempio n. 3
0
void
apio_attach(struct device *parent, struct device *self, void *aux)
{
	struct apio_softc *sc = (void *)self;
	struct sbus_attach_args *sa = aux;
	struct apio_attach_args aaa;
	char *model;

	sc->sc_bt = sa->sa_bustag;

	model = getpropstring(sa->sa_node, "model");
	if (model == NULL) {
		printf(": empty model, unsupported\n");
		return;
	}
	if (strcmp(model, "210sj") != 0) {
		printf(": unsupported model %s\n", model);
		return;
	}

	if (sa->sa_nreg < 3) {
		printf(": %d registers expected, got %d\n",
		    3, sa->sa_nreg);
		return;
	}

	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,
	    0, 0, &sc->sc_csr_h)) {
		printf(": couldn't map csr\n");
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
	    sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size,
	    0, 0, &sc->sc_clk_h)) {
		printf(": couldn't map clk\n");
		return;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[2].sbr_slot,
	    sa->sa_reg[2].sbr_offset, sa->sa_reg[2].sbr_size,
	    0, 0, &sc->sc_lpt_h)) {
		printf(": couldn't map clk\n");
		return;
	}

	printf(": %s\n", model);

	aaa.aaa_name = "lpt";
	aaa.aaa_iot = sc->sc_bt;
	aaa.aaa_ioh = sc->sc_lpt_h;
	aaa.aaa_clkh = sc->sc_clk_h;
	aaa.aaa_inten = ASIO_CSR_SJ_PAR_INTEN;
	aaa.aaa_pri = sa->sa_intr[0].sbi_pri;
	sc->sc_port = config_found(self, &aaa, apio_print);
}
Esempio n. 4
0
int
gfxp_match(struct device *parent, void *cf, void *aux)
{
	struct pci_attach_args *pa = aux;
	int node;
	char *name;

	node = PCITAG_NODE(pa->pa_tag);
	name = getpropstring(node, "name");
	if (strcmp(name, "TECH-SOURCE,gfxp") == 0 ||
	    strcmp(name, "TSI,gfxp") == 0)
		return (10);

	return (0);
}
Esempio n. 5
0
int
led_match(struct device *parent, void *cf, void *aux)
{
	struct ebus_attach_args *ea = aux;
	char *str;

	if (strcmp("env-monitor", ea->ea_name) != 0)
		return (0);

	str = getpropstring(ea->ea_node, "compatible");
	if (strcmp(str, "epic") == 0)
		return (1);

	return (0);
}
Esempio n. 6
0
void
uperf_sbus_attach(struct device *parent, struct device *self, void *aux)
{
	struct sbus_attach_args *sa = aux;
	struct uperf_sbus_softc *sc = (struct uperf_sbus_softc *)self;
	char *model;
	u_int32_t id;

	sc->sc_bus_t = sa->sa_bustag;
	sc->sc_usc.usc_cookie = sc;
	sc->sc_usc.usc_getcntsrc = uperf_sbus_getcntsrc;
	sc->sc_usc.usc_setcntsrc = uperf_sbus_setcntsrc;
	sc->sc_usc.usc_clrcnt = uperf_sbus_clrcnt;
	sc->sc_usc.usc_getcnt = uperf_sbus_getcnt;
	sc->sc_usc.usc_srcs = uperf_sbus_srcs;

	if (sa->sa_nreg != 1) {
		printf(": expected 1 register, got %d\n", sa->sa_nreg);
		return;
	}

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

	id = uperf_sbus_read_reg(sc, USC_ID);
	model = getpropstring(sa->sa_node, "model");
	if (model == NULL || strlen(model) == 0)
		model = "unknown";

	printf(": model %s (%x/%x) ports %d\n", model,
	    (id & USC_ID_IMPL_M) >> USC_ID_IMPL_S,
	    (id & USC_ID_VERS_M) >> USC_ID_VERS_S,
	    (id & USC_ID_UPANUM_M) >> USC_ID_UPANUM_S);

#ifdef DDB
	db_register_xir(uperf_sbus_xir, sc);
#endif
}
Esempio n. 7
0
void
tcxattach(struct device *parent, struct device *self, void *args)
{
	struct tcx_softc *sc = (struct tcx_softc *)self;
	struct confargs *ca = args;
	int node, pri;
	int isconsole = 0;
	char *nam = NULL;
	vaddr_t thc_offset;

	pri = ca->ca_ra.ra_intr[0].int_pri;
	printf(" pri %d: ", pri);

	node = ca->ca_ra.ra_node;
	isconsole = node == fbnode;

	if (ca->ca_ra.ra_nreg < TCX_NREG) {
		printf("expected %d registers, got %d\n",
		    TCX_NREG, ca->ca_ra.ra_nreg);
		return;
	}

	nam = getpropstring(node, "model");
	if (*nam != '\0')
		printf("%s, ", nam);

	/*
	 * Copy the register address spaces needed for mmap operation.
	 */
	sc->sc_phys[0] = ca->ca_ra.ra_reg[TCX_REG_DFB8];
	sc->sc_phys[1] = ca->ca_ra.ra_reg[TCX_REG_DFB24];

	/*
	 * Can't trust the PROM range len here, it is only 4 bytes on the
	 * 8-bit model. Not that it matters much anyway since we map in
	 * pages.
	 */
	sc->sc_bt = (volatile struct bt_regs *)
	    mapiodev(&ca->ca_ra.ra_reg[TCX_REG_CMAP], 0, sizeof *sc->sc_bt);

	/*
	 * For some reason S24 PROM sets up TEC and THC ranges at the
	 * right addresses (701000 and 301000), while 8 bit TCX doesn't
	 * (and uses 70000 and 30000) - be sure to only compensate on 8 bit
	 * models.
	 */
	if (((vaddr_t)ca->ca_ra.ra_reg[TCX_REG_THC].rr_paddr & 0x1000) != 0)
		thc_offset = 0;
	else
		thc_offset = 0x1000;
	sc->sc_thc = (volatile struct tcx_thc *)
	    mapiodev(&ca->ca_ra.ra_reg[TCX_REG_THC],
	        thc_offset, sizeof *sc->sc_thc);

	/*
	 * Find out frame buffer geometry, so that we know how much
	 * memory to map.
	 */
	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);

	sc->sc_dfb8 = mapiodev(&ca->ca_ra.ra_reg[TCX_REG_DFB8], 0,
	    round_page(sc->sc_sunfb.sf_fbsize));

	/*
	 * If the frame buffer advertizes itself as the 8 bit model, or
	 * if the PROM ranges are too small, limit ourselves to 8 bit
	 * operations.
	 *
	 * Further code needing to know which capabilities the frame buffer
	 * has will rely on sc_cplane being non-zero if 24 bit operation
	 * is possible.
	 */
	if (!node_has_property(node, "tcx-8-bit") &&
	    ca->ca_ra.ra_reg[TCX_REG_RDFB32].rr_len >=
	      sc->sc_sunfb.sf_fbsize * 4) {
		sc->sc_cplane =
		    (paddr_t)ca->ca_ra.ra_reg[TCX_REG_RDFB32].rr_paddr;
	}

	printf("%dx%dx%d\n",
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height,
	    sc->sc_cplane == 0 ? 8 : 24);

	/*
	 * Set up mappings for the acceleration code. This may fail.
	 */
	tcx_accel_init(sc, ca);

	/* reset cursor & frame buffer controls */
	tcx_reset(sc, 8);

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

	sc->sc_sunfb.sf_ro.ri_hw = sc;
	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_dfb8;

	fbwscons_init(&sc->sc_sunfb, isconsole);
	fbwscons_setcolormap(&sc->sc_sunfb, tcx_setcolor);

	/*
	 * Now plug accelerated console routines, if possible.
	 */
	tcx_accel_plug(sc, ca);

	sc->sc_ih.ih_fun = tcx_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb, -1);
		shutdownhook_establish(tcx_prom, sc);
	}

	fbwscons_attach(&sc->sc_sunfb, &tcx_accessops, isconsole);
}
Esempio n. 8
0
void
cgtwelveattach(struct device *parent, struct device *self, void *args)
{
	struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self;
	struct confargs *ca = args;
	int node;
	int isconsole = 0;
	char *ps;

	node = ca->ca_ra.ra_node;

	printf(": %s", getpropstring(node, "model"));
	ps = getpropstring(node, "dev_id");
	if (*ps != '\0')
		printf(" (%s)", ps);
	printf("\n");

	isconsole = node == fbnode;

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

	/*
	 * Map registers
	 */
	sc->sc_dpu = (struct cgtwelve_dpu *)mapiodev(ca->ca_ra.ra_reg,
	    CG12_OFF_DPU, sizeof(struct cgtwelve_dpu));
	sc->sc_apu = (struct cgtwelve_apu *)mapiodev(ca->ca_ra.ra_reg,
	    CG12_OFF_APU, sizeof(struct cgtwelve_apu));
	sc->sc_ramdac = (struct cgtwelve_dac *)mapiodev(ca->ca_ra.ra_reg,
	    CG12_OFF_DAC, sizeof(struct cgtwelve_dac));

	/*
	 * The console is using the 1-bit overlay plane, while the prom
	 * will correctly report 32 bit depth.
	 */
	fb_setsize(&sc->sc_sunfb, 1, CG12_WIDTH, CG12_HEIGHT,
	    node, ca->ca_bustype);
	sc->sc_sunfb.sf_depth = 1;
	sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8;
	sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height *
	    sc->sc_sunfb.sf_linebytes;

	sc->sc_highres = sc->sc_sunfb.sf_width == CG12_WIDTH_HR;

	/*
	 * Map planes
	 */
	sc->sc_overlay = mapiodev(ca->ca_ra.ra_reg,
	    sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0,
	    round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR :
	        CG12_SIZE_OVERLAY));
	sc->sc_inten = mapiodev(ca->ca_ra.ra_reg,
	    sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN,
	    round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR :
	        CG12_SIZE_COLOR24));

	/* reset cursor & frame buffer controls */
	sc->sc_sunfb.sf_depth = 0;	/* force action */
	cgtwelve_reset(sc, 1);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)sc->sc_overlay;
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb, -1);
		shutdownhook_establish(cgtwelve_prom, sc);
	}

	printf("%s: %dx%d", self->dv_xname,
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
	ps = getpropstring(node, "ucoderev");
	if (*ps != '\0')
		printf(", microcode rev. %s", ps);
	printf("\n");

	fbwscons_attach(&sc->sc_sunfb, &cgtwelve_accessops, isconsole);
}
Esempio n. 9
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);
}
Esempio n. 10
0
void    
cgthreeattach(struct device *parent, struct device *self, void *aux)
{
	struct cgthree_softc *sc = (struct cgthree_softc *)self;
	struct sbus_attach_args *sa = aux;
	int node, console;
	const char *nam;

	node = sa->sa_node;
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset);

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

	if (sa->sa_nreg != 1) {
		printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
		goto fail;
	}

	/*
	 * Map just CTRL and video RAM.
	 */
	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGTHREE_CTRL_OFFSET,
	    CGTHREE_CTRL_SIZE, 0, 0, &sc->sc_ctrl_regs) != 0) {
		printf(": cannot map ctrl registers\n");
		goto fail_ctrl;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGTHREE_VID_OFFSET,
	    sc->sc_sunfb.sf_fbsize, BUS_SPACE_MAP_LINEAR,
	    0, &sc->sc_vid_regs) != 0) {
		printf(": cannot map vid registers\n");
		goto fail_vid;
	}

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

	console = cgthree_is_console(node);

	cgthree_reset(sc);
	cgthree_burner(sc, 1, 0);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bustag,
	    sc->sc_vid_regs);
	sc->sc_sunfb.sf_ro.ri_hw = sc;

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

	/*
	 * If the framebuffer width is under 1024x768, which is the case for
	 * some clones on laptops, as well as with the VS10-EK, switch from
	 * the PROM font to the more adequate 8x16 font here.
	 * However, we need to adjust two things in this case:
	 * - the display row should be overrided from the current PROM metrics,
	 *   to prevent us from overwriting the last few lines of text.
	 * - if the 80x34 screen would make a large margin appear around it,
	 *   choose to clear the screen rather than keeping old prom output in
	 *   the margins.
	 * XXX there should be a rasops "clear margins" feature
	 */
	fbwscons_init(&sc->sc_sunfb, console &&
	    (sc->sc_sunfb.sf_width >= 1024) ? 0 : RI_CLEAR);

	fbwscons_setcolormap(&sc->sc_sunfb, cgthree_setcolor);

	if (console) {
		fbwscons_console_init(&sc->sc_sunfb,
		    sc->sc_sunfb.sf_width >= 1024 ? -1 : 0);
	}

	fbwscons_attach(&sc->sc_sunfb, &cgthree_accessops, console);

	return;

fail_vid:
	bus_space_unmap(sa->sa_bustag, sc->sc_ctrl_regs, CGTHREE_CTRL_SIZE);
fail_ctrl:
fail:
;
}
Esempio n. 11
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);
}
Esempio n. 12
0
void
gfxp_attach(struct device *parent, struct device *self, void *aux)
{
	struct gfxp_softc *sc = (struct gfxp_softc *)self;
	struct pci_attach_args *pa = aux;
	struct rasops_info *ri;
	int node, console, flags;
	char *model;

	sc->sc_pcitag = pa->pa_tag;

	node = PCITAG_NODE(pa->pa_tag);
	console = gfxp_is_console(node);

	printf("\n");

	model = getpropstring(node, "model");
	printf("%s: %s", self->dv_xname, model);

	if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, PM2_PCI_MEM_LE,
	    PCI_MAPREG_TYPE_MEM, &sc->sc_membase_le, &sc->sc_memsize_le, NULL))
		sc->sc_memsize_le = 0;

	if (pci_mapreg_map(pa, PM2_PCI_MEM_BE, PCI_MAPREG_TYPE_MEM,
	    BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh,
	    &sc->sc_membase_be, &sc->sc_memsize_be, 0)) {
		printf("\n%s: can't map video memory\n", self->dv_xname);
		return;
	}

	if (pci_mapreg_map(pa, PM2_PCI_MMIO, PCI_MAPREG_TYPE_MEM, 0,
	    &sc->sc_mmiot, &sc->sc_mmioh, &sc->sc_mmiobase,
	    &sc->sc_mmiosize, 0)) {
		bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_memsize_be);
		printf("\n%s: can't map mmio\n", self->dv_xname);
		return;
	}

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

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

	ri = &sc->sc_sunfb.sf_ro;
	ri->ri_bits = bus_space_vaddr(sc->sc_memt, sc->sc_memh);
	ri->ri_hw = sc;

	flags = RI_BSWAP;
	if (sc->sc_sunfb.sf_depth == 32) {
		ri->ri_rnum = 8;
		ri->ri_rpos = 16;
		ri->ri_gnum = 8;
		ri->ri_gpos = 8;
		ri->ri_bnum = 8;
		ri->ri_bpos = 0;
		flags &= ~RI_BSWAP;
	}

	fbwscons_init(&sc->sc_sunfb, flags, console);
	fbwscons_setcolormap(&sc->sc_sunfb, gfxp_setcolor);
	sc->sc_mode = WSDISPLAYIO_MODE_EMUL;

	gfxp_init(sc);
	ri->ri_ops.copyrows = gfxp_copyrows;
	ri->ri_ops.copycols = gfxp_copycols;
	ri->ri_ops.eraserows = gfxp_eraserows;
	ri->ri_ops.erasecols = gfxp_erasecols;

	if (console)
		fbwscons_console_init(&sc->sc_sunfb, -1);
	fbwscons_attach(&sc->sc_sunfb, &gfxp_accessops, console);
}
Esempio n. 13
0
File: agten.c Progetto: 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);
}
Esempio n. 14
0
void
bwtwoattach(struct device *parent, struct device *self, void *args)
{
	struct bwtwo_softc *sc = (struct bwtwo_softc *)self;
	struct confargs *ca = args;
	int node = ca->ca_ra.ra_node;
	int isconsole = 0;
	int sbus = 1;
	char *nam;

	printf(": ");

	/*
	 * Map the control register.
	 */
#if defined(SUN4)
	if (CPU_ISSUN4 && ca->ca_bustype == BUS_OBIO &&
	    fb_pfour_id(ca->ca_ra.ra_vaddr) != PFOUR_NOTPFOUR) {
		SET(sc->sc_sunfb.sf_flags, FB_PFOUR);
		sc->sc_sunfb.sf_pfour = (volatile u_int32_t *)
		    mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t));
	} else
#endif
	{
		sc->sc_reg = (volatile struct fbcontrol *)
		    mapiodev(ca->ca_ra.ra_reg, BWREG_REG,
			     sizeof(struct fbcontrol));
	}

	/* Set up default pixel offset.  May be changed below. */
	sc->sc_pixeloffset = BWREG_MEM;

	switch (ca->ca_bustype) {
	case BUS_OBIO:
		if (CPU_ISSUN4M)	/* 4m has framebuffer on obio */
			goto obp_name;

		sbus = node = 0;
#if defined(SUN4)
		if (ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR)) {
			nam = "p4";
			sc->sc_pixeloffset = PFOUR_BW_OFF;
		} else
#endif
			nam = NULL;
		break;

	case BUS_VME32:
	case BUS_VME16:
		sbus = node = 0;
		nam = NULL;
		break;

	case BUS_SBUS:
obp_name:
#if defined(SUN4C) || defined(SUN4M)
		nam = getpropstring(node, "model");
#endif
		break;
	}

	if (nam != NULL && *nam != '\0')
		printf("%s, ", nam);

#if defined(SUN4)
	if (CPU_ISSUN4) {
		struct eeprom *eep = (struct eeprom *)eeprom_va;
		int constype = ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR) ?
		    EE_CONS_P4OPT : EE_CONS_BW;
		/*
		 * Assume this is the console if there's no eeprom info
		 * to be found.
		 */
		if (eep == NULL || eep->eeConsole == constype)
			isconsole = 1;
		else
		/*
		 * On sun4 systems without on-board framebuffers (such as
		 * the 4/3xx models), the PROM will accept the EE_CONS_BW
		 * setting although the framebuffer is a P4.
		 * Accept this setting as well.
		 */
		if (eep->eeConsole == EE_CONS_BW)
			isconsole = 1;
	}
#endif

	if (CPU_ISSUN4COR4M)
		isconsole = node == fbnode;

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

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

	fb_setsize(&sc->sc_sunfb, 1, 1152, 900, node, ca->ca_bustype);
	printf("%dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);

	sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg,
	    sc->sc_pixeloffset, round_page(sc->sc_sunfb.sf_fbsize));
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);

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

	fbwscons_attach(&sc->sc_sunfb, &bwtwo_accessops, isconsole);
}
Esempio n. 15
0
void    
cgsixattach(struct device *parent, struct device *self, void *aux)
{
	struct cgsix_softc *sc = (struct cgsix_softc *)self;
	struct sbus_attach_args *sa = aux;
	int node, console;
	u_int32_t fhc, rev;
	const char *nam;

	node = sa->sa_node;
	sc->sc_bustag = sa->sa_bustag;
	sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset);

	if (sa->sa_nreg != 1) {
		printf(": expected %d registers, got %d\n", 1, sa->sa_nreg);
		goto fail;
	}

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

	/*
	 * Map just BT, FHC, FBC, THC, and video RAM.
	 */
	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_BT_OFFSET,
	    CGSIX_BT_SIZE, 0, 0, &sc->sc_bt_regs) != 0) {
		printf(": cannot map bt registers\n");
		goto fail_bt;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_FHC_OFFSET,
	    CGSIX_FHC_SIZE, 0, 0, &sc->sc_fhc_regs) != 0) {
		printf(": cannot map fhc registers\n");
		goto fail_fhc;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_THC_OFFSET,
	    CGSIX_THC_SIZE, 0, 0, &sc->sc_thc_regs) != 0) {
		printf(": cannot map thc registers\n");
		goto fail_thc;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_VID_OFFSET,
	    sc->sc_sunfb.sf_fbsize, BUS_SPACE_MAP_LINEAR,
	    0, &sc->sc_vid_regs) != 0) {
		printf(": cannot map vid registers\n");
		goto fail_vid;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_TEC_OFFSET,
	    CGSIX_TEC_SIZE, 0, 0, &sc->sc_tec_regs) != 0) {
		printf(": cannot map tec registers\n");
		goto fail_tec;
	}

	if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
	    sa->sa_reg[0].sbr_offset + CGSIX_FBC_OFFSET,
	    CGSIX_FBC_SIZE, 0, 0, &sc->sc_fbc_regs) != 0) {
		printf(": cannot map fbc registers\n");
		goto fail_fbc;
	}

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

	/* if prom didn't initialize us, do it the hard way */
	if (OF_getproplen(node, "width") != sizeof(u_int32_t))
		cgsix_hardreset(sc);

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

	console = cgsix_is_console(node);

	fhc = FHC_READ(sc);
	rev = (fhc & FHC_REV_MASK) >> FHC_REV_SHIFT;
	cgsix_reset(sc, rev);

	cgsix_burner(sc, 1, 0);

	sc->sc_sunfb.sf_ro.ri_bits = (void *)bus_space_vaddr(sc->sc_bustag,
	    sc->sc_vid_regs);
	sc->sc_sunfb.sf_ro.ri_hw = sc;

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

	fbwscons_init(&sc->sc_sunfb, 0, console);
	fbwscons_setcolormap(&sc->sc_sunfb, cgsix_setcolor);

	/*
	 * Old rev. cg6 cards do not like the current acceleration code.
	 *
	 * Some hints from Sun point out at timing and cache problems, which
	 * will be investigated later.
	 */
	if (rev < 5)
		sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags |= CG6_CFFLAG_NOACCEL;

	if ((sc->sc_sunfb.sf_dev.dv_cfdata->cf_flags & CG6_CFFLAG_NOACCEL)
	    == 0) {
		sc->sc_sunfb.sf_ro.ri_ops.copyrows = cgsix_ras_copyrows;
		sc->sc_sunfb.sf_ro.ri_ops.copycols = cgsix_ras_copycols;
		sc->sc_sunfb.sf_ro.ri_ops.eraserows = cgsix_ras_eraserows;
		sc->sc_sunfb.sf_ro.ri_ops.erasecols = cgsix_ras_erasecols;
		sc->sc_sunfb.sf_ro.ri_do_cursor = cgsix_ras_do_cursor;
		cgsix_ras_init(sc);
	}

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

	fbwscons_attach(&sc->sc_sunfb, &cgsix_accessops, console);

	return;

fail_fbc:
	bus_space_unmap(sa->sa_bustag, sc->sc_tec_regs, CGSIX_TEC_SIZE);
fail_tec:
	bus_space_unmap(sa->sa_bustag, sc->sc_vid_regs, sc->sc_sunfb.sf_fbsize);
fail_vid:
	bus_space_unmap(sa->sa_bustag, sc->sc_thc_regs, CGSIX_THC_SIZE);
fail_thc:
	bus_space_unmap(sa->sa_bustag, sc->sc_fhc_regs, CGSIX_FHC_SIZE);
fail_fhc:
	bus_space_unmap(sa->sa_bustag, sc->sc_bt_regs, CGSIX_BT_SIZE);
fail_bt:
fail:
	return;
}
Esempio n. 16
0
void
magma_attach(struct device *parent, struct device *dev, void *aux)
{
    struct sbus_attach_args *sa = aux;
    struct magma_softc *sc = (struct magma_softc *)dev;
    const struct magma_board_info *card;
    char magma_prom[40], *clockstr;
    int chip, cd_clock;

    getpropstringA(sa->sa_node, "magma_prom", magma_prom);
    for (card = supported_cards; card->mb_name != NULL; card++) {
        if (strcmp(sa->sa_name, card->mb_sbusname) != 0)
            continue;
        if (strcmp(magma_prom, card->mb_name) == 0)
            break;
    }
    if (card->mb_name == NULL) {
        printf(": %s (unsupported)\n", magma_prom);
        return;
    }

    sc->sc_bustag = sa->sa_bustag;

    clockstr = getpropstring(sa->sa_node, "clock");
    if (strlen(clockstr) == 0)
        cd_clock = 25;
    else {
        cd_clock = 0;
        while (*clockstr != '\0')
            cd_clock = cd_clock * 10 + *clockstr++ - '0';
    }

    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,
                     0, 0, &sc->sc_iohandle) != 0) {
        printf(": can't map registers\n");
        return;
    }

    if (sa->sa_nintr < 1) {
        printf(": can't find interrupt\n");
        return;
    }
    sc->sc_ih = bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_TTY, 0,
                                   magma_hard, sc, dev->dv_xname);
    if (sc->sc_ih == NULL) {
        printf(": couldn't establish interrupt, pri %d\n",
               INTLEV(sa->sa_pri));
        bus_space_unmap(sc->sc_bustag, sc->sc_iohandle,
                        sa->sa_reg[0].sbr_size);
        return;
    }

    sc->sc_sih = softintr_establish(IPL_TTY, magma_soft, sc);
    if (sc->sc_sih == NULL) {
        printf(": can't get soft intr\n");
        bus_space_unmap(sc->sc_bustag, sc->sc_iohandle,
                        sa->sa_reg[0].sbr_size);
        return;
    }

    printf(": %s\n", card->mb_realname);

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

    /* the SVCACK* lines are daisychained */
    if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                            card->mb_svcackr, 1, &sc->sc_svcackrh)) {
        printf(": failed to map svcackr\n");
        return;
    }
    if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                            card->mb_svcackt, 1, &sc->sc_svcackth)) {
        printf(": failed to map svcackt\n");
        return;
    }
    if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                            card->mb_svcackm, 1, &sc->sc_svcackmh)) {
        printf(": failed to map svcackm\n");
        return;
    }

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

        cd->cd_clock = cd_clock;

        if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                                card->mb_cd1400[chip], CD1400_REGMAPSIZE, &cd->cd_regh)) {
            printf(": failed to map cd1400 regs\n");
            return;
        }
        cd->cd_regt = sc->sc_bustag;

        /* getpropstring(sa->sa_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 0x%x rev %x clock %dMHz\n",
                 sc->ms_dev.dv_xname, 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];

        if (bus_space_subregion(sc->sc_bustag, sc->sc_iohandle,
                                card->mb_cd1190[chip], CD1190_REGMAPSIZE, &cd->cd_regh)) {
            printf(": failed to map cd1190 regs\n");
            return;
        }
        cd->cd_regt = sc->sc_bustag;
        dprintf(("%s attach CD1190 %d addr 0x%x (failed)\n",
                 sc->ms_dev.dv_xname, chip, cd->cd_reg));
        /* XXX don't know anything about these chips yet */
    }

    /* configure the children */
    (void)config_found(dev, mtty_match, NULL);
    (void)config_found(dev, mbpp_match, NULL);
}
Esempio n. 17
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);
}
Esempio n. 18
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);
}
Esempio n. 19
0
void
fbwscons_init(struct sunfb *sf, int flags, int isconsole)
{
	struct rasops_info *ri = &sf->sf_ro;
	int cols, rows, fw, fh, wt, wl;

	/* ri_hw and ri_bits must have already been setup by caller */
	ri->ri_flg = RI_FULLCLEAR | flags;
	ri->ri_depth = sf->sf_depth;
	ri->ri_stride = sf->sf_linebytes;
	ri->ri_width = sf->sf_width;
	ri->ri_height = sf->sf_height;

	rows = a2int(getpropstring(optionsnode, "screen-#rows"), 34);
	cols = a2int(getpropstring(optionsnode, "screen-#columns"), 80);

	/*
	 * If the framebuffer width is under 960 pixels, rasops will
	 * switch from the 12x22 font to the more adequate 8x16 font
	 * here.
	 * If we are the console device, we need to adjust two things:
	 * - the display row should be overrided from the current PROM
	 *   metrics, since it will not match the PROM reality anymore.
	 * - the screen needs to be cleared.
	 *
	 * However, to accommodate laptops with specific small fonts,
	 * it is necessary to compare the resolution with the actual
	 * font metrics.
	 */

	if (isconsole) {
		if (fb_get_console_metrics(&fw, &fh, &wt, &wl) != 0) {
			/*
			 * Assume a 12x22 prom font and a centered
			 * 80x34 console window.
			 */
			fw = 12; fh = 22;
			wt = wl = 0;
		} else {
			/*
			 * Make sure window-top and window-left
			 * values are consistent with the font metrics.
			 */
			if (wt <= 0 || wt > sf->sf_height - rows * fh ||
			    wl <= 0 || wl > sf->sf_width - cols * fw)
				wt = wl = 0;
		}
		if (wt == 0 /* || wl == 0 */) {
			ri->ri_flg |= RI_CENTER;

			/*
			 * Since the console window might not be
			 * centered (e.g. on a 1280x1024 vigra
			 * VS-12 frame buffer), have rasops
			 * clear the margins even if the screen is
			 * not cleared.
			 */
			ri->ri_flg |= RI_CLEARMARGINS;
		}

		if (ri->ri_wsfcookie != 0) {
			/* driver handles font issues. do nothing. */
		} else {
			/*
			 * If the PROM uses a different font than the
			 * one we are expecting it to use, or if the
			 * display is shorter than 960 pixels wide,
			 * we'll force a screen clear.
			 */
			if (fw != 12 || sf->sf_width < 12 * 80)
				ri->ri_flg |= RI_CLEAR | RI_CENTER;
		}
	} else {
		ri->ri_flg |= RI_CLEAR | RI_CENTER;
	}

	/* ifb(4) doesn't set ri_bits at the moment */
	if (ri->ri_bits == NULL)
		ri->ri_flg &= ~(RI_CLEAR | RI_CLEARMARGINS);

	rasops_init(ri, rows, cols);

	/*
	 * If this is the console display and there is no font change,
	 * adjust our terminal window to the position of the PROM
	 * window - in case it is not exactly centered.
	 */
	if ((ri->ri_flg & RI_CENTER) == 0) {
		/* code above made sure wt and wl are initialized */
		ri->ri_bits += wt * ri->ri_stride;
		if (ri->ri_depth >= 8)	/* for 15bpp to compute ok */
			ri->ri_bits += wl * ri->ri_pelbytes;
		else
			ri->ri_bits += (wl * ri->ri_depth) >> 3;

		ri->ri_xorigin = wl;
		ri->ri_yorigin = wt;
	}
Esempio n. 20
0
void
cgthreeattach(struct device *parent, struct device *self, void *args)
{
	struct cgthree_softc *sc = (struct cgthree_softc *)self;
	struct confargs *ca = args;
	int node, pri, isrdi = 0, i;
	volatile struct bt_regs *bt;
	int isconsole;
	char *nam;

	pri = ca->ca_ra.ra_intr[0].int_pri;
	printf(" pri %d: ", pri);

	node = ca->ca_ra.ra_node;

	if (strcmp(ca->ca_ra.ra_name, "cgRDI") == 0) {
		isrdi = 1;
		nam = "cgRDI";
	} else
		nam = getpropstring(node, "model");

	if (nam != NULL && *nam != '\0')
		printf("%s, ", nam);

	isconsole = node == fbnode;

	sc->sc_fbc = (volatile struct fbcontrol *)
	    mapiodev(ca->ca_ra.ra_reg, CG3REG_REG,
		     sizeof(struct fbcontrol));

	/* Transfer video magic to board, if it's not running */
	if (isrdi == 0 && (sc->sc_fbc->fbc_ctrl & FBC_TIMING) == 0)
		for (i = 0; i < sizeof(cg3_videoctrl)/sizeof(cg3_videoctrl[0]);
		     i++) {
			volatile struct fbcontrol *fbc = sc->sc_fbc;
			if (cg3_videoctrl[i].sense == 0xff ||
			    (fbc->fbc_status & FBS_MSENSE) ==
			     cg3_videoctrl[i].sense) {
				int j;
#ifdef DEBUG
				printf(" (setting video ctrl)");
#endif
				for (j = 0; j < 12; j++)
					fbc->fbc_vcontrol[j] =
						cg3_videoctrl[i].vctrl[j];
				fbc->fbc_ctrl |= FBC_TIMING;
				break;
			}
		}

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

	sc->sc_ih.ih_fun = cgthree_intr;
	sc->sc_ih.ih_arg = sc;
	intr_establish(pri, &sc->sc_ih, IPL_FB, self->dv_xname);

	/* enable video */
	cgthree_burner(sc, 1, 0);
	bt = &sc->sc_fbc->fbc_dac;
	BT_INIT(bt, 0);

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
	sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg, CG3REG_MEM,
	    round_page(sc->sc_sunfb.sf_fbsize));
	sc->sc_sunfb.sf_ro.ri_hw = sc;

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

	/*
	 * If the framebuffer width is under 1024x768, which is the case for
	 * some clones on laptops, as well as with the VS10-EK, switch from
	 * the PROM font to the more adequate 8x16 font here.
	 * However, we need to adjust two things in this case:
	 * - the display row should be overrided from the current PROM metrics,
	 *   to prevent us from overwriting the last few lines of text.
	 * - if the 80x34 screen would make a large margin appear around it,
	 *   choose to clear the screen rather than keeping old prom output in
	 *   the margins.
	 * XXX there should be a rasops "clear margins" feature
	 */
	fbwscons_init(&sc->sc_sunfb, isconsole &&
	    (sc->sc_sunfb.sf_width >= 1024) ? 0 : RI_CLEAR);
	fbwscons_setcolormap(&sc->sc_sunfb, cgthree_setcolor);

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb,
		    sc->sc_sunfb.sf_width >= 1024 ? -1 : 0);
	}

	fbwscons_attach(&sc->sc_sunfb, &cgthree_accessops, isconsole);
}
Esempio n. 21
0
void
presto_attach(struct device *parent, struct device *self, void *args)
{
	struct presto_softc *sc = (struct presto_softc *)self;
	struct confargs *ca = args;
	char *model, *submodel;
	u_int8_t status;

	/* Get card parameters */
	model = getpropstring(ca->ca_ra.ra_node, "model");
	if (*model == '\0')
		submodel = "fictitious";
	else {
		submodel = memchr(model, ',', strlen(model));
		if (submodel != NULL)
			submodel++;
		else
			submodel = model;
	}
	strncpy(sc->sc_model, submodel, 16);
	sc->sc_memsize = ca->ca_ra.ra_len;

	printf(": %s\n%s: %d MB NVRAM, ", model,
	    sc->sc_dev.dv_xname, sc->sc_memsize >> 20);

	/* Map memory */
	sc->sc_mem = (void *)mapiodev(ca->ca_ra.ra_reg, 0, sc->sc_memsize);

	/*
	 * Clear the ``disconnect battery'' bit.
	 */
	*(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS) = 0x00;

	/*
	 * Clear the ``unflushed data'' status. This way, if the card is
	 * reused under SunOS, the system will not try to flush whatever
	 * data the user put in the nvram...
	 */
	*(u_int8_t *)(sc->sc_mem + PSERVE_DATASTATUS) = 0x00;

	/*
	 * Decode battery status
	 */
	status = *(u_int8_t *)(sc->sc_mem + PSERVE_BATTERYSTATUS);
	printf("battery status %x ", status);
	if (ISSET(status, PSBAT_FAULT)) {
		printf("(non-working)");
	} else if (ISSET(status, PSBAT_CONNECTED)) {
		if (ISSET(status, PSBAT_CHARGING))
			printf("(charging)");
		else
			printf("(ok)");
	} else
		printf("(disabled)");
	printf("\n");

#ifdef DEBUG
	printf("%s: status codes %02.2x, %02.2x, %02.2x, %02.2x\n",
	    sc->sc_dev.dv_xname,
	    *(u_int8_t *)(sc->sc_mem + 0x03), *(u_int8_t *)(sc->sc_mem + 0x07),
	    *(u_int8_t *)(sc->sc_mem + 0x0b), *(u_int8_t *)(sc->sc_mem + 0x0f));
#endif

	sc->sc_dk.dk_driver = &presto_dk;
	sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
	disk_attach(&sc->sc_dk);

	/* read the disk label immediately */
	presto_getdisklabel(sc);
}
Esempio n. 22
0
/*
 * Attach and initialize a cgtwelve.
 */
void
cgtwelveattach(struct device *parent, struct device *self, void *args)
{
	struct cgtwelve_softc *sc = (struct cgtwelve_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, isconsole = 0;
	char *ps;

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

	printf(": %s", getpropstring(node, "model"));
	ps = getpropstring(node, "dev_id");
	if (*ps != '\0')
		printf(" (%s)", ps);
	printf("\n");

	isconsole = node == fbnode;

	if (sa->sa_nreg == 0) {
		printf("%s: no SBus registers!\n", self->dv_xname);
		return;
	}

	sc->sc_bustag = bt;

	/*
	 * Map registers
	 */
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    CG12_OFF_DPU, sizeof(struct cgtwelve_dpu),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map DPU registers\n", self->dv_xname);
		return;
	}
	sc->sc_dpu = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    CG12_OFF_APU, sizeof(struct cgtwelve_apu),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map APU registers\n", self->dv_xname);
		return;
	}
	sc->sc_apu = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    CG12_OFF_DAC, sizeof(struct cgtwelve_dac),
	    BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map RAMDAC registers\n", self->dv_xname);
		return;
	}
	sc->sc_ramdac = bus_space_vaddr(bt, bh);

	/*
	 * The console is using the 1-bit overlay plane, while the prom
	 * will correctly report 32 bit depth.
	 */
	fb_setsize(&sc->sc_sunfb, 1, CG12_WIDTH, CG12_HEIGHT,
	    node, 0);
	sc->sc_sunfb.sf_depth = 1;
	sc->sc_sunfb.sf_linebytes = sc->sc_sunfb.sf_width / 8;
	sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height *
	    sc->sc_sunfb.sf_linebytes;

	sc->sc_highres = sc->sc_sunfb.sf_width == CG12_WIDTH_HR;

	/*
	 * Map planes
	 */
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    (sc->sc_highres ? CG12_OFF_OVERLAY0_HR : CG12_OFF_OVERLAY0),
	    round_page(sc->sc_highres ? CG12_SIZE_OVERLAY_HR :
	        CG12_SIZE_OVERLAY), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map overlay plane\n", self->dv_xname);
		return;
	}
	sc->sc_overlay = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset +
	    (sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN),
	    round_page(sc->sc_highres ? CG12_SIZE_COLOR24_HR :
	        CG12_SIZE_COLOR24), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
		printf("%s: can't map color plane\n", self->dv_xname);
		return;
	}
	sc->sc_inten = bus_space_vaddr(bt, bh);
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset +
	    (sc->sc_highres ? CG12_OFF_INTEN_HR : CG12_OFF_INTEN));

	/* reset cursor & frame buffer controls */
	sc->sc_sunfb.sf_depth = 0;	/* force action */
	cgtwelve_reset(sc, 1);

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

	if (isconsole) {
		fbwscons_console_init(&sc->sc_sunfb, -1);
		shutdownhook_establish(cgtwelve_prom, sc);
	}

	printf("%s: %dx%d", self->dv_xname,
	    sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
	ps = getpropstring(node, "ucoderev");
	if (*ps != '\0')
		printf(", microcode rev. %s", ps);
	printf("\n");

	fbwscons_attach(&sc->sc_sunfb, &cgtwelve_accessops, isconsole);
}
Esempio n. 23
0
/*
 * Attach and initialize a vigra display, as well as a child wsdisplay.
 */
void
vigraattach(struct device *parent, struct device *self, void *args)
{
	struct vigra_softc *sc = (struct vigra_softc *)self;
	struct sbus_attach_args *sa = args;
	bus_space_tag_t bt;
	bus_space_handle_t bh;
	int node, row, isconsole = 0;
	char *nam;

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

	isconsole = node == fbnode;

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

	/*
	 * Check whether we are using an G300 or an G335 chip.
	 * The VS10 and VS12 use the G300, while the VS11 uses a G335.
	 */
	sc->sc_g300 = strncmp(nam, "VIGRA,vs11", strlen("VIGRA,vs11"));

	sc->sc_bustag = bt;
	if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_CSR].sbr_slot,
	    sa->sa_reg[VIGRA_REG_CSR].sbr_offset,
	    sa->sa_reg[VIGRA_REG_CSR].sbr_size, BUS_SPACE_MAP_LINEAR, 0,
	    &bh) != 0) {
		printf("\n%s: can't map control registers\n", self->dv_xname);
		return;
	}
	sc->sc_regs = bus_space_vaddr(bt, bh);
	if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_RAMDAC].sbr_slot,
	    sa->sa_reg[VIGRA_REG_RAMDAC].sbr_offset,
	    sa->sa_reg[VIGRA_REG_RAMDAC].sbr_size, BUS_SPACE_MAP_LINEAR, 0,
	    &bh) != 0) {
		printf("\n%s: can't map ramdac registers\n", self->dv_xname);
		return;
	}
	sc->sc_ramdac = bus_space_vaddr(bt, bh);

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

	fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
	if (sbus_bus_map(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot,
	    sa->sa_reg[VIGRA_REG_VRAM].sbr_offset,
	    round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 0,
	    &bh) != 0) {
		printf("\n%s: can't map video memory\n", self->dv_xname);
		return;
	}
	sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
	sc->sc_sunfb.sf_ro.ri_hw = sc;
	sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[VIGRA_REG_VRAM].sbr_slot,
	    sa->sa_reg[VIGRA_REG_VRAM].sbr_offset);

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

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

	/*
	 * If the framebuffer width is under 1024x768, we will switch from the
	 * PROM font to the more adequate 8x16 font here.
	 * However, we need to adjust two things in this case:
	 * - the display row should be overrided from the current PROM metrics,
	 *   to prevent us from overwriting the last few lines of text.
	 * - if the 80x34 screen would make a large margin appear around it,
	 *   choose to clear the screen rather than keeping old prom output in
	 *   the margins.
	 * XXX there should be a rasops "clear margins" feature
	 *
	 * Also, in 1280x1024 resolution, the PROM display is not centered
	 * vertically (why? no other frame buffer does this in such a mode!),
	 * so be lazy and clear the screen here too anyways...
	 */
	fbwscons_init(&sc->sc_sunfb, isconsole && (sc->sc_sunfb.sf_width != 800
	    && sc->sc_sunfb.sf_width != 1280) ? 0 : RI_CLEAR);
	fbwscons_setcolormap(&sc->sc_sunfb, vigra_setcolor);

	if (isconsole) {
		switch (sc->sc_sunfb.sf_width) {
		case 640:
			row = sc->sc_sunfb.sf_ro.ri_rows - 1;
			break;
		case 800:
		case 1280:
			row = 0;	/* screen has been cleared above */
			break;
		default:
			row = -1;
			break;
		}

		fbwscons_console_init(&sc->sc_sunfb, row);
	}

	fbwscons_attach(&sc->sc_sunfb, &vigra_accessops, isconsole);
}