Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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() */