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; }
/* * 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; }
/* * 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? */ }