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