int sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt, bus_space_handle_t romh, bus_addr_t *bases, u_int codebase) { struct sti_dd *dd; int error, size, i; KASSERT(rom != NULL); STI_ENABLE_ROM(rom->rom_softc); rom->iot = iot; rom->memt = memt; rom->romh = romh; rom->bases = bases; /* * Get ROM header and code function pointers. */ dd = &rom->rom_dd; rom->rom_devtype = bus_space_read_1(memt, romh, 3); if (rom->rom_devtype == STI_DEVTYPE1) { dd->dd_type = bus_space_read_1(memt, romh, 0x03); dd->dd_nmon = bus_space_read_1(memt, romh, 0x07); dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b); dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f); dd->dd_grid[0] = parseword(0x10); dd->dd_grid[1] = parseword(0x20); dd->dd_fntaddr = parseword(0x30) & ~3; dd->dd_maxst = parseword(0x40); dd->dd_romend = parseword(0x50) & ~3; dd->dd_reglst = parseword(0x60) & ~3; dd->dd_maxreent= parseshort(0x70); dd->dd_maxtimo = parseshort(0x78); dd->dd_montbl = parseword(0x80) & ~3; dd->dd_udaddr = parseword(0x90) & ~3; dd->dd_stimemreq=parseword(0xa0); dd->dd_udsize = parseword(0xb0); dd->dd_pwruse = parseshort(0xc0); dd->dd_bussup = bus_space_read_1(memt, romh, 0xcb); dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf); dd->dd_altcodet= bus_space_read_1(memt, romh, 0xd3); dd->dd_eddst[0]= bus_space_read_1(memt, romh, 0xd7); dd->dd_eddst[1]= bus_space_read_1(memt, romh, 0xdb); dd->dd_eddst[2]= bus_space_read_1(memt, romh, 0xdf); dd->dd_cfbaddr = parseword(0xe0) & ~3; codebase <<= 2; dd->dd_pacode[0x0] = parseword(codebase + 0x00) & ~3; dd->dd_pacode[0x1] = parseword(codebase + 0x10) & ~3; dd->dd_pacode[0x2] = parseword(codebase + 0x20) & ~3; dd->dd_pacode[0x3] = parseword(codebase + 0x30) & ~3; dd->dd_pacode[0x4] = parseword(codebase + 0x40) & ~3; dd->dd_pacode[0x5] = parseword(codebase + 0x50) & ~3; dd->dd_pacode[0x6] = parseword(codebase + 0x60) & ~3; dd->dd_pacode[0x7] = parseword(codebase + 0x70) & ~3; dd->dd_pacode[0x8] = parseword(codebase + 0x80) & ~3; dd->dd_pacode[0x9] = parseword(codebase + 0x90) & ~3; dd->dd_pacode[0xa] = parseword(codebase + 0xa0) & ~3; dd->dd_pacode[0xb] = parseword(codebase + 0xb0) & ~3; dd->dd_pacode[0xc] = parseword(codebase + 0xc0) & ~3; dd->dd_pacode[0xd] = parseword(codebase + 0xd0) & ~3; dd->dd_pacode[0xe] = parseword(codebase + 0xe0) & ~3; dd->dd_pacode[0xf] = parseword(codebase + 0xf0) & ~3; } else { /* STI_DEVTYPE4 */ bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd, sizeof(*dd) / 4); /* fix pacode... */ bus_space_read_region_stream_4(memt, romh, codebase, (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4); } STI_DISABLE_ROM(rom->rom_softc); DPRINTF(("dd:\n" "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n" "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n" "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n" "code=", dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet, dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst, dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo, dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq, dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr)); DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2], dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5], dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8], dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb], dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe], dd->dd_pacode[0xf])); /* * Figure out how many bytes we need for the STI code. * Note there could be fewer than STI_END pointer entries * populated, especially on older devices. */ for (i = STI_END; !dd->dd_pacode[i]; i--) ; size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN]; if (rom->rom_devtype == STI_DEVTYPE1) size = (size + 3) / 4; if (size == 0) { aprint_error(": no code for the requested platform\n"); return EINVAL; } DPRINTF(("code size %x/%x\n", size, round_page(size))); if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0, UVM_KMF_WIRED))) { aprint_error(": cannot allocate %u bytes for code\n", size); return ENOMEM; } /* * Copy code into memory and make it executable. */ STI_ENABLE_ROM(rom->rom_softc); if (rom->rom_devtype == STI_DEVTYPE1) { uint8_t *p; uint32_t addr, eaddr; p = (uint8_t *)rom->rom_code; for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4; addr < eaddr; addr += 4 ) { *p++ = bus_space_read_4(memt, romh, addr) & 0xff; } } else { /* STI_DEVTYPE4 */ bus_space_read_region_stream_4(memt, romh, dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code, size / 4); } STI_DISABLE_ROM(rom->rom_softc); if ((error = uvm_map_protect(kernel_map, rom->rom_code, rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) { aprint_error(": uvm_map_protect failed (%d)\n", error); uvm_km_free(kernel_map, rom->rom_code, round_page(size), UVM_KMF_WIRED); return error; } /* * Setup code function pointers. */ #define O(i) \ (dd->dd_pacode[(i)] == 0 ? 0 : \ (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \ (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1))) rom->init = (sti_init_t) O(STI_INIT_GRAPH); rom->mgmt = (sti_mgmt_t) O(STI_STATE_MGMT); rom->unpmv = (sti_unpmv_t) O(STI_FONT_UNPMV); rom->blkmv = (sti_blkmv_t) O(STI_BLOCK_MOVE); rom->test = (sti_test_t) O(STI_SELF_TEST); rom->exhdl = (sti_exhdl_t) O(STI_EXCEP_HDLR); rom->inqconf = (sti_inqconf_t)O(STI_INQ_CONF); rom->scment = (sti_scment_t)O(STI_SCM_ENT); rom->dmac = (sti_dmac_t) O(STI_DMA_CTRL); rom->flowc = (sti_flowc_t) O(STI_FLOW_CTRL); rom->utiming = (sti_utiming_t)O(STI_UTIMING); rom->pmgr = (sti_pmgr_t) O(STI_PROC_MGR); rom->util = (sti_util_t) O(STI_UTIL); #undef O /* * Set colormap entry is not implemented until 8.04, so force * a NULL pointer here. */ if (dd->dd_grrev < STI_REVISION(8, 4)) { rom->scment = NULL; } return 0; }
int sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg, uint32_t baseaddr, u_int fontindex) { struct sti_rom *rom = scr->scr_rom; bus_space_tag_t memt = rom->memt; bus_space_handle_t romh = rom->romh; struct sti_font *fp = &scr->scr_curfont; uint32_t addr; int size; #ifdef notyet int uc; struct { struct sti_unpmvflags flags; struct sti_unpmvin in; struct sti_unpmvout out; } a; #endif /* * Get the first PROM font in memory */ STI_ENABLE_ROM(rom->rom_softc); rescan: addr = baseaddr; do { if (rom->rom_devtype == STI_DEVTYPE1) { fp->first = parseshort(addr + 0x00); fp->last = parseshort(addr + 0x08); fp->width = bus_space_read_1(memt, romh, addr + 0x13); fp->height = bus_space_read_1(memt, romh, addr + 0x17); fp->type = bus_space_read_1(memt, romh, addr + 0x1b); fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f); fp->next = parseword(addr + 0x20); fp->uheight= bus_space_read_1(memt, romh, addr + 0x33); fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37); } else { /* STI_DEVTYPE4 */ bus_space_read_region_stream_4(memt, romh, addr, (uint32_t *)fp, sizeof(struct sti_font) / 4); } #ifdef STIDEBUG STI_DISABLE_ROM(rom->rom_softc); DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width, fp->height, fp->type, fp->bpc, fp->first, fp->last)); STI_ENABLE_ROM(rom->rom_softc); #endif if (fontindex == 0) { size = sizeof(struct sti_font) + (fp->last - fp->first + 1) * fp->bpc; if (rom->rom_devtype == STI_DEVTYPE1) size *= 4; scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT); if (scr->scr_romfont == NULL) return ENOMEM; bus_space_read_region_stream_4(memt, romh, addr, (uint32_t *)scr->scr_romfont, size / 4); break; } addr = baseaddr + fp->next; fontindex--; } while (fp->next != 0); /* * If our font index was bogus, we did not find the expected font. * In this case, pick the first one and be done with it. */ if (fp->next == 0 && scr->scr_romfont == NULL) { fontindex = 0; goto rescan; } STI_DISABLE_ROM(rom->rom_softc); #ifdef notyet /* * If there is enough room in the off-screen framebuffer memory, * display all the characters there in order to display them * faster with blkmv operations rather than unpmv later on. */ if (size <= cfg->fbheight * (cfg->fbwidth - cfg->width - cfg->owidth)) { memset(&a, 0, sizeof(a)); a.flags.flags = STI_UNPMVF_WAIT; a.in.fg_colour = STI_COLOUR_WHITE; a.in.bg_colour = STI_COLOUR_BLACK; a.in.font_addr = scr->scr_romfont; scr->scr_fontmaxcol = cfg->fbheight / fp->height; scr->scr_fontbase = cfg->width + cfg->owidth; for (uc = fp->first; uc <= fp->last; uc++) { a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) * fp->width + scr->scr_fontbase; a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) * fp->height; a.in.index = uc; (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); if (a.out.errno) { aprint_error_dev(sc->sc_dev, "unpmv %d " "returned %d\n", uc, a.out.errno); return 0; } } free(scr->scr_romfont, M_DEVBUF); scr->scr_romfont = NULL; } #endif return 0; }
/* * External function entry point. */ int getopt(int argc, char *const *argv, const char *optstring) { char c; char *cp; int longopt; char *longoptarg; /* * Has the end of the options been encountered? The following * implements the SUS requirements: * * If, when getopt() is called: * argv[optind] is a null pointer * *argv[optind] is not the character '-' * argv[optind] points to the string "-" * getopt() returns -1 without changing optind. If * argv[optind] points to the string "--" * getopt() returns -1 after incrementing optind. */ if (_sp == 1) { if (optind >= argc || argv[optind][0] != '-' || argv[optind] == NULL || argv[optind][1] == '\0') return (EOF); else if (strcmp(argv[optind], "--") == NULL) { optind++; return (EOF); } } /* * Getting this far indicates that an option has been encountered. * Note that the syntax of optstring applies special meanings to * the characters ':' and '(', so they are not permissible as * option letters. A special meaning is also applied to the ')' * character, but its meaning can be determined from context. * Note that the specification only requires that the alnum * characters be accepted. * * If the second character of the argument is a '-' this must be * a long-option, otherwise it must be a short option. Scan for * the option in optstring by the appropriate algorithm. Either * scan will return a pointer to the short-option character in * optstring if the option is found and NULL otherwise. * * For an unrecognized long-option, optopt will equal 0, but * since long-options can't aggregate the failing option can * be identified by argv[optind-1]. */ optopt = c = (unsigned char)argv[optind][_sp]; optarg = NULL; longopt = (_sp == 1 && c == '-'); if (!(longopt ? ((cp = parselong(optstring, argv[optind]+2, &longoptarg)) != NULL) : ((cp = parseshort(optstring, c)) != NULL))) { /* LINTED: variable format specifier */ ERR(_libc_gettext("%s: illegal option -- %s\n"), c, (longopt ? optind : 0)); /* * Note: When the long option is unrecognized, optopt * will be '-' here, which matches the specification. */ if (argv[optind][++_sp] == '\0' || longopt) { optind++; _sp = 1; } return ('?'); } optopt = c = *cp; /* * A valid option has been identified. If it should have an * option-argument, process that now. SUS defines the setting * of optarg as follows: * * 1. If the option was the last character in the string pointed to * by an element of argv, then optarg contains the next element * of argv, and optind is incremented by 2. If the resulting * value of optind is not less than argc, this indicates a * missing option-argument, and getopt() returns an error * indication. * * 2. Otherwise, optarg points to the string following the option * character in that element of argv, and optind is incremented * by 1. * * The second clause allows -abcd (where b requires an option-argument) * to be interpreted as "-a -b cd". * * Note that the option-argument can legally be an empty string, * such as: * command --option= operand * which explicitly sets the value of --option to nil */ if (*(cp + 1) == ':') { /* The option takes an argument */ if (!longopt && argv[optind][_sp+1] != '\0') { optarg = &argv[optind++][_sp+1]; } else if (longopt && longoptarg) { /* * The option argument was explicitly set to * the empty string on the command line (--option=) */ optind++; optarg = longoptarg; } else if (++optind >= argc) { /* LINTED: variable format specifier */ ERR(_libc_gettext("%s: option requires an argument" \ " -- %s\n"), c, (longopt ? optind - 1 : 0)); _sp = 1; optarg = NULL; return (optstring[0] == ':' ? ':' : '?'); } else optarg = argv[optind++]; _sp = 1; } else { /* The option does NOT take an argument */ if (longopt && (longoptarg != NULL)) { /* User supplied an arg to an option that takes none */ /* LINTED: variable format specifier */ ERR(_libc_gettext( "%s: option doesn't take an argument -- %s\n"), 0, (longopt ? optind : 0)); optarg = longoptarg = NULL; c = '?'; } if (longopt || argv[optind][++_sp] == '\0') { _sp = 1; optind++; } optarg = NULL; } return (c); } /* getopt() */