示例#1
0
int
sti_screen_setup(struct sti_screen *scr, int flags)
{
	struct sti_rom *rom = scr->scr_rom;
	bus_space_tag_t memt = rom->memt;
	bus_space_handle_t romh = rom->romh;
	struct sti_dd *dd = &rom->rom_dd;
	struct sti_cfg *cc = &scr->scr_cfg;
	struct sti_inqconfout cfg;
	struct sti_einqconfout ecfg;
#ifdef STIDEBUG
	char buf[256];
#endif
	int error, i;
	int geometry_kluge = 0;
	u_int fontindex = 0;

	KASSERT(scr != NULL);
	memset(cc, 0, sizeof(*cc));
	cc->ext_cfg = &scr->scr_ecfg;
	memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg));

	if (dd->dd_stimemreq) {
		scr->scr_ecfg.addr =
		    malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT);
		if (!scr->scr_ecfg.addr) {
			aprint_error("cannot allocate %d bytes for STI\n",
			    dd->dd_stimemreq);
			return ENOMEM;
		}
	}

	sti_region_setup(scr);

	if ((error = sti_init(scr, 0))) {
		aprint_error(": cannot initialize (%d)\n", error);
		goto fail;
	}

	memset(&cfg, 0, sizeof(cfg));
	memset(&ecfg, 0, sizeof(ecfg));
	cfg.ext = &ecfg;
	if ((error = sti_inqcfg(scr, &cfg))) {
		aprint_error(": error %d inquiring config\n", error);
		goto fail;
	}

	/*
	 * Older (rev 8.02) boards report wrong offset values,
	 * similar to the displayable area size, at least in m68k mode.
	 * Attempt to detect this and adjust here.
	 */
	if (cfg.owidth == cfg.width &&
	    cfg.oheight == cfg.height)
		geometry_kluge = 1;

	if (geometry_kluge) {
		scr->scr_cfg.oscr_width = cfg.owidth =
		    cfg.fbwidth - cfg.width;
		scr->scr_cfg.oscr_height = cfg.oheight =
		    cfg.fbheight - cfg.height;
	}

	/*
	 * Save a few fields for sti_describe_screen() later
	 */
	scr->fbheight = cfg.fbheight;
	scr->fbwidth = cfg.fbwidth;
	scr->oheight = cfg.oheight;
	scr->owidth = cfg.owidth;
	memcpy(scr->name, cfg.name, sizeof(scr->name));

	if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
		aprint_error(": cannot initialize (%d)\n", error);
		goto fail;
	}
#ifdef STIDEBUG
	snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes);
	DPRINTF(("conf: bpp=%d planes=%d attr=%s\n"
	    "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
	    cfg.planes, buf,
	    ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
	    ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]));
#endif
	scr->scr_bpp = cfg.bppu;

	/*
	 * Although scr->scr_ecfg.current_monitor is not filled by
	 * sti_init() as expected, we can nevertheless walk the monitor
	 * list, if there is any, and if we find a mode matching our
	 * resolution, pick its font index.
	 */
	if (dd->dd_montbl != 0) {
		STI_ENABLE_ROM(rom->rom_softc);

		for (i = 0; i < dd->dd_nmon; i++) {
			u_int offs = dd->dd_montbl + 8 * i;
			uint32_t m[2];
			sti_mon_t mon = (void *)m;
			if (rom->rom_devtype == STI_DEVTYPE1) {
				m[0] = parseword(4 * offs);
				m[1] = parseword(4 * (offs + 4));
			} else {
				bus_space_read_region_stream_4(memt, romh, offs,
				    (uint32_t *)mon, sizeof(*mon) / 4);
			}

			if (mon->width == scr->scr_cfg.scr_width &&
			    mon->height == scr->scr_cfg.scr_height) {
				fontindex = mon->font;
				break;
			}
		}

		STI_DISABLE_ROM(rom->rom_softc);

		DPRINTF(("font index: %d\n", fontindex));
	}

	if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
		aprint_error(": cannot fetch fonts (%d)\n", error);
		goto fail;
	}

	/*
	 * setup screen descriptions:
	 *	figure number of fonts supported;
	 *	allocate wscons structures;
	 *	calculate dimensions.
	 */

	scr->scr_wsd.name = "std";
	scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
	scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
	scr->scr_wsd.textops = &sti_emulops;
	scr->scr_wsd.fontwidth = scr->scr_curfont.width;
	scr->scr_wsd.fontheight = scr->scr_curfont.height;
	scr->scr_wsd.capabilities = WSSCREEN_REVERSE | WSSCREEN_UNDERLINE;

	scr->scr_scrlist[0] = &scr->scr_wsd;
	scr->scr_screenlist.nscreens = 1;
	scr->scr_screenlist.screens = scr->scr_scrlist;

	return 0;

fail:
	/* XXX free resources */
	if (scr->scr_ecfg.addr != NULL) {
		free(scr->scr_ecfg.addr, M_DEVBUF);
		scr->scr_ecfg.addr = NULL;
	}

	return ENXIO;
}
示例#2
0
/*
 * wsdisplay accessops
 */
int
sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
{
	struct sti_screen *scr = (struct sti_screen *)v;
	struct sti_rom *rom = scr->scr_rom;
	struct wsdisplay_fbinfo *wdf;
	struct wsdisplay_cmap *cmapp;
	u_int mode, idx, count;
	int i, ret;

	ret = 0;
	switch (cmd) {
	case WSDISPLAYIO_GMODE:
		*(u_int *)data = scr->scr_wsmode;
		break;

	case WSDISPLAYIO_SMODE:
		mode = *(u_int *)data;
		if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL &&
		    mode == WSDISPLAYIO_MODE_DUMBFB)
			ret = sti_init(scr, 0);
		else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
		    mode == WSDISPLAYIO_MODE_EMUL)
			ret = sti_init(scr, STI_TEXTMODE);
		scr->scr_wsmode = mode;
		break;

	case WSDISPLAYIO_GTYPE:
		*(u_int *)data = WSDISPLAY_TYPE_STI;
		break;

	case WSDISPLAYIO_GINFO:
		wdf = (struct wsdisplay_fbinfo *)data;
		wdf->height = scr->scr_cfg.scr_height;
		wdf->width  = scr->scr_cfg.scr_width;
		wdf->depth  = scr->scr_bpp;
		if (rom->scment == NULL)
			wdf->cmsize = 0;
		else
			wdf->cmsize = STI_NCMAP;
		break;

	case WSDISPLAYIO_LINEBYTES:
		*(u_int *)data = scr->scr_cfg.fb_width;
		break;

	case WSDISPLAYIO_GETCMAP:
		if (rom->scment == NULL)
			return ENOTTY;
		cmapp = (struct wsdisplay_cmap *)data;
		idx = cmapp->index;
		count = cmapp->count;
		if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
			return EINVAL;
		if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
			break;
		if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
			break;
		if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
			break;
		break;

	case WSDISPLAYIO_PUTCMAP:
		if (rom->scment == NULL)
			return ENOTTY;
		cmapp = (struct wsdisplay_cmap *)data;
		idx = cmapp->index;
		count = cmapp->count;
		if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
			return EINVAL;
		if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
			break;
		if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
			break;
		if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
			break;
		for (i = idx + count - 1; i >= idx; i--)
			if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
			    scr->scr_gcmap[i], scr->scr_bcmap[i]))) {

				DPRINTF(("sti_ioctl: "
				    "sti_setcment(%d, %u, %u, %u): %%d\n", i,
				    (u_int)scr->scr_rcmap[i],
				    (u_int)scr->scr_gcmap[i],
				    (u_int)scr->scr_bcmap[i]));

				ret = EINVAL;
				break;
			}
		break;

	case WSDISPLAYIO_SVIDEO:
	case WSDISPLAYIO_GVIDEO:
	case WSDISPLAYIO_GCURPOS:
	case WSDISPLAYIO_SCURPOS:
	case WSDISPLAYIO_GCURMAX:
	case WSDISPLAYIO_GCURSOR:
	case WSDISPLAYIO_SCURSOR:
	default:
		return ENOTTY;	/* not supported yet */
	}

	return ret;
}
示例#3
0
/*
 * Initialize the sti device for ite's needs.
 * We don't bother to check for failures since
 * - we are in tight space already
 * - since romputchar() does not work with sti devices, there is no way we
 *   can report errors (although we could switch to serial...)
 */
void
sti_iteinit(struct ite_data *ip)
{
	int slotno, i;
	size_t codesize, memsize;
	u_int8_t *va, *code;
	u_int addr, eaddr, reglist, tmp;
	struct sti_inqconfout cfg;
	struct sti_einqconfout ecfg;

	bzero(&sti, sizeof sti);
	slotno = (int)ip->fbbase;
	ip->fbbase = va = (u_int8_t *)IIOV(SGC_BASE + (slotno * SGC_DEVSIZE));

	/*
	 * Read the microcode.
	 */

	for (i = 0; i < STI_CODECNT; i++)
		sti.codeptr[i] =
		    parseword1(va, (STI_CODEBASE_M68K << 2) + i * 0x10);

	for (i = STI_END; sti.codeptr[i] == 0; i--);
	codesize = sti.codeptr[i] - sti.codeptr[STI_BEGIN];
	codesize = (codesize + 3) / 4;

	sti.code = (u_int8_t *)alloc(codesize);
	code = sti.code;
	addr = (u_int)va + sti.codeptr[STI_BEGIN];
	eaddr = addr + codesize * 4;
	for (; addr < eaddr; addr += 4)
		*code++ = *(u_int8_t *)addr;

	for (i = STI_CODECNT - 1; i != 0; i--)
		if (sti.codeptr[i] != 0) {
			sti.codeptr[i] -= sti.codeptr[0];
			sti.codeptr[i] /= 4;
		}

	sti.codeptr[0] = 0;
	for (i = STI_END; sti.codeptr[i] == 0; i--);
	sti.codeptr[i] = 0;

	/*
	 * Read the regions list.
	 */

	reglist = parseword1(va, 0x60);
	for (i = 0; i < STI_REGION_MAX; i++) {
		tmp = parseword1(va, (reglist & ~3) + i * 0x10);
		sti.cfg.regions[i] = (u_int)va + ((tmp >> 18) << 12);
		if (tmp & 0x4000)
			break;
	}

	/*
	 * Allocate scratch memory for the microcode if it needs it.
	 */

	sti.cfg.ext_cfg = &sti.ecfg;
	memsize = parseword1(va, 0xa0);
	if (memsize != 0)
		sti.ecfg.addr = alloc(memsize);

	/*
	 * Initialize the display, and get geometry information.
	 */

	sti_init(0);

	bzero(&cfg, sizeof cfg);
	bzero(&ecfg, sizeof ecfg);
	cfg.ext = &ecfg;
	sti_inqcfg(&cfg);

	if (cfg.owidth == cfg.width && cfg.oheight == cfg.height) {
		sti.cfg.oscr_width = cfg.owidth = cfg.fbwidth - cfg.width;
		sti.cfg.oscr_height = cfg.oheight = cfg.fbheight - cfg.height;
	}

	ip->dheight = cfg.height;
	ip->dwidth = cfg.width;
	ip->fbheight = cfg.fbheight;
	ip->fbwidth = cfg.fbwidth;

	/*
	 * Get ready for ite operation!
	 */

	sti_init(1);
	sti_fontinfo(ip);
	sti_clear(ip, 0, 0, ip->rows, ip->cols);	/* necessary? */
}