The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/sti.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: sti.c,v 1.83 2022/07/15 19:29:27 deraadt Exp $        */
    2 
    3 /*
    4  * Copyright (c) 2000-2003 Michael Shalayeff
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
   20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   22  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   26  * THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 /*
   29  * TODO:
   30  *      call sti procs asynchronously;
   31  *      implement console scroll-back;
   32  *      X11 support on more models.
   33  */
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/device.h>
   38 #include <sys/malloc.h>
   39 
   40 #include <uvm/uvm_extern.h>
   41 
   42 #include <machine/bus.h>
   43 
   44 #include <dev/wscons/wsdisplayvar.h>
   45 #include <dev/wscons/wsconsio.h>
   46 
   47 #include <dev/ic/stireg.h>
   48 #include <dev/ic/stivar.h>
   49 
   50 #include "sti.h"
   51 
   52 struct cfdriver sti_cd = {
   53         NULL, "sti", DV_DULL
   54 };
   55 
   56 int     sti_pack_attr(void *, int, int, int, uint32_t *);
   57 int     sti_copycols(void *, int, int, int, int);
   58 int     sti_copyrows(void *, int, int, int);
   59 int     sti_cursor(void *, int, int, int);
   60 int     sti_erasecols(void *, int, int, int, uint32_t);
   61 int     sti_eraserows(void *, int, int, uint32_t);
   62 int     sti_mapchar(void *, int, u_int *);
   63 int     sti_putchar(void *, int, int, u_int, uint32_t);
   64 void    sti_unpack_attr(void *, uint32_t, int *, int *, int *);
   65 
   66 struct wsdisplay_emulops sti_emulops = {
   67         .cursor = sti_cursor,
   68         .mapchar = sti_mapchar,
   69         .putchar = sti_putchar,
   70         .copycols = sti_copycols,
   71         .erasecols = sti_erasecols,
   72         .copyrows = sti_copyrows,
   73         .eraserows = sti_eraserows,
   74         .pack_attr = sti_pack_attr,
   75         .unpack_attr = sti_unpack_attr
   76 };
   77 
   78 int     sti_alloc_screen(void *, const struct wsscreen_descr *, void **, int *,
   79             int *, uint32_t *);
   80 void    sti_free_screen(void *, void *);
   81 int     sti_ioctl(void *, u_long, caddr_t, int, struct proc *);
   82 paddr_t sti_mmap(void *, off_t, int);
   83 int     sti_show_screen(void *, void *, int, void (*)(void *, int, int),
   84             void *);
   85 
   86 const struct wsdisplay_accessops sti_accessops = {
   87         .ioctl = sti_ioctl,
   88         .mmap = sti_mmap,
   89         .alloc_screen = sti_alloc_screen,
   90         .free_screen = sti_free_screen,
   91         .show_screen = sti_show_screen
   92 };
   93 
   94 enum sti_bmove_funcs {
   95         bmf_clear, bmf_copy, bmf_invert, bmf_underline
   96 };
   97 
   98 void    sti_bmove(struct sti_screen *, int, int, int, int, int, int,
   99             enum sti_bmove_funcs);
  100 int     sti_init(struct sti_screen *, int);
  101 #define STI_TEXTMODE    0x01
  102 #define STI_CLEARSCR    0x02
  103 #define STI_FBMODE      0x04
  104 int     sti_inqcfg(struct sti_screen *, struct sti_inqconfout *);
  105 int     sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char);
  106 
  107 struct sti_screen *
  108         sti_attach_screen(struct sti_softc *, int);
  109 void    sti_describe_screen(struct sti_softc *, struct sti_screen *);
  110 void    sti_end_attach_screen(struct sti_softc *, struct sti_screen *, int);
  111 int     sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, u_int32_t,
  112             u_int);
  113 void    sti_region_setup(struct sti_screen *);
  114 int     sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t,
  115             bus_space_handle_t, bus_addr_t *, u_int);
  116 int     sti_screen_setup(struct sti_screen *, int);
  117 
  118 int     ngle_default_putcmap(struct sti_screen *, u_int, u_int);
  119 
  120 void    ngle_artist_setupfb(struct sti_screen *);
  121 void    ngle_elk_setupfb(struct sti_screen *);
  122 void    ngle_timber_setupfb(struct sti_screen *);
  123 int     ngle_putcmap(struct sti_screen *, u_int, u_int);
  124 
  125 #if NSTI_PCI > 0
  126 #define STI_ENABLE_ROM(sc) \
  127 do { \
  128         if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \
  129                 (*(sc)->sc_enable_rom)(sc); \
  130 } while (0)
  131 #define STI_DISABLE_ROM(sc) \
  132 do { \
  133         if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \
  134                 (*(sc)->sc_disable_rom)(sc); \
  135 } while (0)
  136 #else
  137 #define STI_ENABLE_ROM(sc)              do { /* nothing */ } while (0)
  138 #define STI_DISABLE_ROM(sc)             do { /* nothing */ } while (0)
  139 #endif
  140 
  141 /* Macros to read larger than 8 bit values from byte roms */
  142 #define parseshort(o) \
  143         ((bus_space_read_1(memt, romh, (o) + 3) <<  8) | \
  144          (bus_space_read_1(memt, romh, (o) + 7)))
  145 #define parseword(o) \
  146         ((bus_space_read_1(memt, romh, (o) +  3) << 24) | \
  147          (bus_space_read_1(memt, romh, (o) +  7) << 16) | \
  148          (bus_space_read_1(memt, romh, (o) + 11) <<  8) | \
  149          (bus_space_read_1(memt, romh, (o) + 15)))
  150 
  151 int
  152 sti_attach_common(struct sti_softc *sc, bus_space_tag_t iot,
  153     bus_space_tag_t memt, bus_space_handle_t romh, u_int codebase)
  154 {
  155         struct sti_rom *rom;
  156         int rc;
  157 
  158         rom = (struct sti_rom *)malloc(sizeof(*rom), M_DEVBUF,
  159             M_NOWAIT | M_ZERO);
  160         if (rom == NULL) {
  161                 printf("cannot allocate rom data\n");
  162                 return (ENOMEM);
  163         }
  164 
  165         rom->rom_softc = sc;
  166         rc = sti_rom_setup(rom, iot, memt, romh, sc->bases, codebase);
  167         if (rc != 0) {
  168                 free(rom, M_DEVBUF, sizeof *rom);
  169                 return (rc);
  170         }
  171 
  172         sc->sc_rom = rom;
  173 
  174         sti_describe(sc);
  175 
  176         sc->sc_scr = sti_attach_screen(sc,
  177             sc->sc_flags & STI_CONSOLE ?  0 : STI_CLEARSCR);
  178         if (sc->sc_scr == NULL)
  179                 rc = ENOMEM;
  180 
  181         return (rc);
  182 }
  183 
  184 struct sti_screen *
  185 sti_attach_screen(struct sti_softc *sc, int flags)
  186 {
  187         struct sti_screen *scr;
  188         int rc;
  189 
  190         scr = (struct sti_screen *)malloc(sizeof(*scr), M_DEVBUF,
  191             M_NOWAIT | M_ZERO);
  192         if (scr == NULL) {
  193                 printf("cannot allocate screen data\n");
  194                 return (NULL);
  195         }
  196 
  197         scr->scr_rom = sc->sc_rom;
  198         rc = sti_screen_setup(scr, flags);
  199         if (rc != 0) {
  200                 free(scr, M_DEVBUF, sizeof *scr);
  201                 return (NULL);
  202         }
  203 
  204         sti_describe_screen(sc, scr);
  205 
  206         return (scr);
  207 }
  208 
  209 int
  210 sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
  211     bus_space_handle_t romh, bus_addr_t *bases, u_int codebase)
  212 {
  213         struct sti_dd *dd;
  214         int size, i;
  215         vaddr_t va;
  216         paddr_t pa;
  217 
  218         STI_ENABLE_ROM(rom->rom_softc);
  219 
  220         rom->iot = iot;
  221         rom->memt = memt;
  222         rom->romh = romh;
  223         rom->bases = bases;
  224 
  225         /*
  226          * Get ROM header and code function pointers.
  227          */
  228 
  229         dd = &rom->rom_dd;
  230         rom->rom_devtype = bus_space_read_1(memt, romh, 3);
  231         if (rom->rom_devtype == STI_DEVTYPE1) {
  232                 dd->dd_type      = bus_space_read_1(memt, romh, 0x03);
  233                 dd->dd_nmon      = bus_space_read_1(memt, romh, 0x07);
  234                 dd->dd_grrev     = bus_space_read_1(memt, romh, 0x0b);
  235                 dd->dd_lrrev     = bus_space_read_1(memt, romh, 0x0f);
  236                 dd->dd_grid[0]   = parseword(0x10);
  237                 dd->dd_grid[1]   = parseword(0x20);
  238                 dd->dd_fntaddr   = parseword(0x30) & ~3;
  239                 dd->dd_maxst     = parseword(0x40);
  240                 dd->dd_romend    = parseword(0x50) & ~3;
  241                 dd->dd_reglst    = parseword(0x60) & ~3;
  242                 dd->dd_maxreent  = parseshort(0x70);
  243                 dd->dd_maxtimo   = parseshort(0x78);
  244                 dd->dd_montbl    = parseword(0x80) & ~3;
  245                 dd->dd_udaddr    = parseword(0x90) & ~3;
  246                 dd->dd_stimemreq = parseword(0xa0);
  247                 dd->dd_udsize    = parseword(0xb0);
  248                 dd->dd_pwruse    = parseshort(0xc0);
  249                 dd->dd_bussup    = bus_space_read_1(memt, romh, 0xcb);
  250                 dd->dd_ebussup   = bus_space_read_1(memt, romh, 0xcf);
  251                 dd->dd_altcodet  = bus_space_read_1(memt, romh, 0xd3);
  252                 dd->dd_eddst[0]  = bus_space_read_1(memt, romh, 0xd7);
  253                 dd->dd_eddst[1]  = bus_space_read_1(memt, romh, 0xdb);
  254                 dd->dd_eddst[2]  = bus_space_read_1(memt, romh, 0xdf);
  255                 dd->dd_cfbaddr   = parseword(0xe0) & ~3;
  256 
  257                 codebase <<= 2;
  258                 dd->dd_pacode[0x0] = parseword(codebase + 0x000) & ~3;
  259                 dd->dd_pacode[0x1] = parseword(codebase + 0x010) & ~3;
  260                 dd->dd_pacode[0x2] = parseword(codebase + 0x020) & ~3;
  261                 dd->dd_pacode[0x3] = parseword(codebase + 0x030) & ~3;
  262                 dd->dd_pacode[0x4] = parseword(codebase + 0x040) & ~3;
  263                 dd->dd_pacode[0x5] = parseword(codebase + 0x050) & ~3;
  264                 dd->dd_pacode[0x6] = parseword(codebase + 0x060) & ~3;
  265                 dd->dd_pacode[0x7] = parseword(codebase + 0x070) & ~3;
  266                 dd->dd_pacode[0x8] = parseword(codebase + 0x080) & ~3;
  267                 dd->dd_pacode[0x9] = parseword(codebase + 0x090) & ~3;
  268                 dd->dd_pacode[0xa] = parseword(codebase + 0x0a0) & ~3;
  269                 dd->dd_pacode[0xb] = parseword(codebase + 0x0b0) & ~3;
  270                 dd->dd_pacode[0xc] = parseword(codebase + 0x0c0) & ~3;
  271                 dd->dd_pacode[0xd] = parseword(codebase + 0x0d0) & ~3;
  272                 dd->dd_pacode[0xe] = parseword(codebase + 0x0e0) & ~3;
  273                 dd->dd_pacode[0xf] = parseword(codebase + 0x0f0) & ~3;
  274         } else {        /* STI_DEVTYPE4 */
  275                 bus_space_read_raw_region_4(memt, romh, 0, (u_int8_t *)dd,
  276                     sizeof(*dd));
  277                 /* fix pacode... */
  278                 bus_space_read_raw_region_4(memt, romh, codebase,
  279                     (u_int8_t *)dd->dd_pacode, sizeof(dd->dd_pacode));
  280         }
  281 
  282         STI_DISABLE_ROM(rom->rom_softc);
  283 
  284 #ifdef STIDEBUG
  285         printf("dd:\n"
  286             "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n"
  287             "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n"
  288             "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n"
  289             "code=",
  290             dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet,
  291             dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst,
  292             dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo,
  293             dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq,
  294             dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr);
  295         printf("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
  296             dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
  297             dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
  298             dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
  299             dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
  300             dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
  301             dd->dd_pacode[0xf]);
  302 #endif
  303 
  304         /*
  305          * Figure out how much bytes we need for the STI code.
  306          * Note there could be fewer than STI_END entries pointer
  307          * entries populated, especially on older devices.
  308          */
  309 
  310         for (i = STI_END; dd->dd_pacode[i] == 0; i--)
  311                 ;
  312         size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
  313         if (rom->rom_devtype == STI_DEVTYPE1)
  314                 size = (size + 3) / 4;
  315         if (size == 0) {
  316                 printf(": no code for the requested platform\n");
  317                 return (EINVAL);
  318         }
  319 
  320         if (!(rom->rom_code = km_alloc(round_page(size), &kv_any,
  321             &kp_zero, &kd_waitok))) {
  322                 printf(": cannot allocate %u bytes for code\n", size);
  323                 return (ENOMEM);
  324         }
  325 #ifdef STIDEBUG
  326         printf("code=%p[%x]\n", rom->rom_code, size);
  327 #endif
  328 
  329         /*
  330          * Copy code into memory and make it executable.
  331          */
  332 
  333         STI_ENABLE_ROM(rom->rom_softc);
  334 
  335         if (rom->rom_devtype == STI_DEVTYPE1) {
  336                 u_int8_t *p = rom->rom_code;
  337                 u_int32_t addr, eaddr;
  338 
  339                 for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
  340                     addr < eaddr; addr += 4 )
  341                         *p++ = bus_space_read_4(memt, romh, addr) & 0xff;
  342 
  343         } else  /* STI_DEVTYPE4 */
  344                 bus_space_read_raw_region_4(memt, romh,
  345                     dd->dd_pacode[STI_BEGIN], rom->rom_code, size);
  346 
  347         STI_DISABLE_ROM(rom->rom_softc);
  348 
  349         /*
  350          * Remap the ROM code as executable.  This happens to be the
  351          * only place in the OpenBSD kernel where we need to do this.
  352          * Since the kernel (deliberately) doesn't provide a
  353          * high-level interface to map kernel memory as executable we
  354          * use low-level pmap calls for this.
  355          */
  356         for (va = (vaddr_t)rom->rom_code;
  357              va < (vaddr_t)rom->rom_code + round_page(size);
  358              va += PAGE_SIZE) {
  359                 pmap_extract(pmap_kernel(), va, &pa);
  360                 pmap_kenter_pa(va, pa, PROT_READ | PROT_EXEC);
  361         }
  362         pmap_update(pmap_kernel());
  363 
  364         /*
  365          * Setup code function pointers.
  366          */
  367 
  368 #define O(i) \
  369         (dd->dd_pacode[(i)] == 0 ? 0 : \
  370             (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \
  371               (rom->rom_devtype == STI_DEVTYPE1? 4 : 1)))
  372 
  373         rom->init       = (sti_init_t)O(STI_INIT_GRAPH);
  374         rom->mgmt       = (sti_mgmt_t)O(STI_STATE_MGMT);
  375         rom->unpmv      = (sti_unpmv_t)O(STI_FONT_UNPMV);
  376         rom->blkmv      = (sti_blkmv_t)O(STI_BLOCK_MOVE);
  377         rom->test       = (sti_test_t)O(STI_SELF_TEST);
  378         rom->exhdl      = (sti_exhdl_t)O(STI_EXCEP_HDLR);
  379         rom->inqconf    = (sti_inqconf_t)O(STI_INQ_CONF);
  380         rom->scment     = (sti_scment_t)O(STI_SCM_ENT);
  381         rom->dmac       = (sti_dmac_t)O(STI_DMA_CTRL);
  382         rom->flowc      = (sti_flowc_t)O(STI_FLOW_CTRL);
  383         rom->utiming    = (sti_utiming_t)O(STI_UTIMING);
  384         rom->pmgr       = (sti_pmgr_t)O(STI_PROC_MGR);
  385         rom->util       = (sti_util_t)O(STI_UTIL);
  386 
  387 #undef  O
  388 
  389         /*
  390          * Set colormap entry is not implemented until 8.04, so force
  391          * a NULL pointer here.
  392          */
  393         if (dd->dd_grrev < STI_REVISION(8,4)) {
  394                 rom->scment = NULL;
  395         }
  396 
  397         return (0);
  398 }
  399 
  400 /*
  401  * Map all regions.
  402  */
  403 void
  404 sti_region_setup(struct sti_screen *scr)
  405 {
  406         struct sti_rom *rom = scr->scr_rom;
  407         bus_space_tag_t memt = rom->memt;
  408         bus_space_handle_t romh = rom->romh;
  409         bus_addr_t *bases = rom->bases;
  410         struct sti_dd *dd = &rom->rom_dd;
  411         struct sti_cfg *cc = &scr->scr_cfg;
  412         struct sti_region regions[STI_REGION_MAX], *r;
  413         u_int regno, regcnt;
  414         bus_addr_t addr;
  415 
  416 #ifdef STIDEBUG
  417         printf("stiregions @%p:\n", (void *)dd->dd_reglst);
  418 #endif
  419 
  420         /*
  421          * Read the region information.
  422          */
  423 
  424         STI_ENABLE_ROM(rom->rom_softc);
  425 
  426         if (rom->rom_devtype == STI_DEVTYPE1) {
  427                 for (regno = 0; regno < STI_REGION_MAX; regno++)
  428                         *(u_int *)(regions + regno) =
  429                             parseword(dd->dd_reglst + regno * 0x10);
  430         } else {
  431                 bus_space_read_raw_region_4(memt, romh, dd->dd_reglst,
  432                     (u_int8_t *)regions, sizeof regions);
  433         }
  434 
  435         STI_DISABLE_ROM(rom->rom_softc);
  436 
  437         /*
  438          * Count them.
  439          */
  440 
  441         for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++)
  442                 if (r->last)
  443                         break;
  444         regcnt++;
  445 
  446         /*
  447          * Map them.
  448          */
  449 
  450         for (regno = 0, r = regions; regno < regcnt; regno++, r++) {
  451                 if (r->length == 0)
  452                         continue;
  453 
  454                 /*
  455                  * Assume an existing mapping exists.
  456                  */
  457                 addr = bases[regno] + (r->offset << PGSHIFT);
  458 
  459 #ifdef STIDEBUG
  460                 printf("%08x @ 0x%08lx%s%s%s%s\n",
  461                     r->length << PGSHIFT, addr, r->sys_only ? " sys" : "",
  462                     r->cache ? " cache" : "", r->btlb ? " btlb" : "",
  463                     r->last ? " last" : "");
  464 #endif
  465 
  466                 /*
  467                  * Region #0 is always the rom, and it should have been
  468                  * mapped already.
  469                  * XXX This expects a 1:1 mapping...
  470                  */
  471                 if (regno == 0 && romh == bases[0]) {
  472                         cc->regions[0] = addr;
  473                         continue;
  474                 }
  475 
  476                 if (bus_space_map(memt, addr, r->length << PGSHIFT,
  477                     BUS_SPACE_MAP_LINEAR | (r->cache ?
  478                     BUS_SPACE_MAP_CACHEABLE : 0), &rom->regh[regno]) != 0) {
  479                         rom->regh[regno] = romh;        /* XXX */
  480 #ifdef STIDEBUG
  481                         printf("already mapped region\n");
  482 #endif
  483                 } else {
  484                         addr = (bus_addr_t)
  485                             bus_space_vaddr(memt, rom->regh[regno]);
  486                         if (regno == 1) {
  487                                 scr->fbaddr = addr;
  488                                 scr->fblen = r->length << PGSHIFT;
  489                         }
  490                 }
  491 
  492                 cc->regions[regno] = addr;
  493         }
  494 
  495 #ifdef STIDEBUG
  496         /*
  497          * Make sure we'll trap accessing unmapped regions
  498          */
  499         for (regno = 0; regno < STI_REGION_MAX; regno++)
  500                 if (cc->regions[regno] == 0)
  501                     cc->regions[regno] = 0x81234567;
  502 #endif
  503 }
  504 
  505 int
  506 sti_screen_setup(struct sti_screen *scr, int flags)
  507 {
  508         struct sti_rom *rom = scr->scr_rom;
  509         bus_space_tag_t memt = rom->memt;
  510         bus_space_handle_t romh = rom->romh;
  511         struct sti_dd *dd = &rom->rom_dd;
  512         struct sti_cfg *cc = &scr->scr_cfg;
  513         struct sti_inqconfout cfg;
  514         struct sti_einqconfout ecfg;
  515         int error, i;
  516         int geometry_kluge = 0;
  517         u_int fontindex = 0;
  518 
  519         bzero(cc, sizeof (*cc));
  520         cc->ext_cfg = &scr->scr_ecfg;
  521         bzero(cc->ext_cfg, sizeof(*cc->ext_cfg));
  522 
  523         if (dd->dd_stimemreq) {
  524                 scr->scr_ecfg.addr =
  525                     malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT);
  526                 if (!scr->scr_ecfg.addr) {
  527                         printf("cannot allocate %d bytes for STI\n",
  528                             dd->dd_stimemreq);
  529                         return (ENOMEM);
  530                 }
  531         }
  532 
  533         sti_region_setup(scr);
  534 
  535         if ((error = sti_init(scr, 0))) {
  536                 printf(": can not initialize (%d)\n", error);
  537                 goto fail;
  538         }
  539 
  540         bzero(&cfg, sizeof(cfg));
  541         bzero(&ecfg, sizeof(ecfg));
  542         cfg.ext = &ecfg;
  543         if ((error = sti_inqcfg(scr, &cfg))) {
  544                 printf(": error %d inquiring config\n", error);
  545                 goto fail;
  546         }
  547 
  548         /*
  549          * Older (rev 8.02) boards report wrong offset values,
  550          * similar to the displayable area size, at least in m68k mode.
  551          * Attempt to detect this and adjust here.
  552          */
  553         if (cfg.owidth == cfg.width &&
  554             cfg.oheight == cfg.height)
  555                 geometry_kluge = 1;
  556 
  557         if (geometry_kluge) {
  558                 scr->scr_cfg.oscr_width = cfg.owidth =
  559                     cfg.fbwidth - cfg.width;
  560                 scr->scr_cfg.oscr_height = cfg.oheight =
  561                     cfg.fbheight - cfg.height;
  562         }
  563 
  564         /*
  565          * Save a few fields for sti_describe_screen() later
  566          */
  567         scr->fbheight = cfg.fbheight;
  568         scr->fbwidth = cfg.fbwidth;
  569         scr->oheight = cfg.oheight;
  570         scr->owidth = cfg.owidth;
  571         bcopy(cfg.name, scr->name, sizeof(scr->name));
  572 
  573         if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
  574                 printf(": can not initialize (%d)\n", error);
  575                 goto fail;
  576         }
  577 #ifdef STIDEBUG
  578         printf("conf: bpp=%d planes=%d attr=%b\n"
  579             "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
  580             cfg.planes, cfg.attributes, STI_INQCONF_BITS,
  581             ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
  582             ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]);
  583 #endif
  584         scr->scr_bpp = cfg.bppu;
  585 
  586         /*
  587          * Although scr->scr_ecfg.current_monitor is not filled by
  588          * sti_init() as expected, we can nevertheless walk the monitor
  589          * list, if there is any, and if we find a mode matching our
  590          * resolution, pick its font index.
  591          */
  592         if (dd->dd_montbl != 0) {
  593                 STI_ENABLE_ROM(rom->rom_softc);
  594 
  595                 for (i = 0; i < dd->dd_nmon; i++) {
  596                         u_int offs = dd->dd_montbl + 8 * i;
  597                         u_int32_t m[2];
  598                         sti_mon_t mon = (void *)m;
  599                         if (rom->rom_devtype == STI_DEVTYPE1) {
  600                                 m[0] = parseword(4 * offs);
  601                                 m[1] = parseword(4 * (offs + 4));
  602                         } else {
  603                                 bus_space_read_raw_region_4(memt, romh, offs,
  604                                     (u_int8_t *)mon, sizeof(*mon));
  605                         }
  606 
  607                         if (mon->width == scr->scr_cfg.scr_width &&
  608                             mon->height == scr->scr_cfg.scr_height) {
  609                                 fontindex = mon->font;
  610                                 break;
  611                         }
  612                 }
  613 
  614                 STI_DISABLE_ROM(rom->rom_softc);
  615 
  616 #ifdef STIDEBUG
  617                 printf("font index: %d\n", fontindex);
  618 #endif
  619         }
  620 
  621         if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
  622                 printf(": cannot fetch fonts (%d)\n", error);
  623                 goto fail;
  624         }
  625 
  626         /*
  627          * setup screen descriptions:
  628          *      figure number of fonts supported;
  629          *      allocate wscons structures;
  630          *      calculate dimensions.
  631          */
  632 
  633         strlcpy(scr->scr_wsd.name, "std", sizeof(scr->scr_wsd.name));
  634         scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
  635         scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
  636         scr->scr_wsd.textops = &sti_emulops;
  637         scr->scr_wsd.fontwidth = scr->scr_curfont.width;
  638         scr->scr_wsd.fontheight = scr->scr_curfont.height;
  639         scr->scr_wsd.capabilities = WSSCREEN_REVERSE;
  640 
  641         scr->scr_scrlist[0] = &scr->scr_wsd;
  642         scr->scr_screenlist.nscreens = 1;
  643         scr->scr_screenlist.screens =
  644             (const struct wsscreen_descr **)scr->scr_scrlist;
  645 
  646 #ifndef SMALL_KERNEL
  647         /*
  648          * Decide which board-specific routines to use.
  649          */
  650 
  651         switch (dd->dd_grid[0]) {
  652         case STI_DD_CRX:
  653                 scr->setupfb = ngle_elk_setupfb;
  654                 scr->putcmap = ngle_putcmap;
  655 
  656                 scr->reg10_value = 0x13601000;
  657                 if (scr->scr_bpp > 8)
  658                         scr->reg12_value = NGLE_BUFF1_CMAP3;
  659                 else
  660                         scr->reg12_value = NGLE_BUFF1_CMAP0;
  661                 scr->cmap_finish_register = NGLE_REG_1;
  662                 break;
  663 
  664         case STI_DD_TIMBER:
  665                 scr->setupfb = ngle_timber_setupfb;
  666                 scr->putcmap = ngle_putcmap;
  667 
  668                 scr->reg10_value = 0x13602000;
  669                 scr->reg12_value = NGLE_BUFF1_CMAP0;
  670                 scr->cmap_finish_register = NGLE_REG_1;
  671                 break;
  672 
  673         case STI_DD_ARTIST:
  674                 scr->setupfb = ngle_artist_setupfb;
  675                 scr->putcmap = ngle_putcmap;
  676 
  677                 scr->reg10_value = 0x13601000;
  678                 scr->reg12_value = NGLE_ARTIST_CMAP0;
  679                 scr->cmap_finish_register = NGLE_REG_26;
  680                 break;
  681 
  682         case STI_DD_EG:
  683                 scr->setupfb = ngle_artist_setupfb;
  684                 scr->putcmap = ngle_putcmap;
  685 
  686                 scr->reg10_value = 0x13601000;
  687                 if (scr->scr_bpp > 8) {
  688                         scr->reg12_value = NGLE_BUFF1_CMAP3;
  689                         scr->cmap_finish_register = NGLE_REG_1;
  690                 } else {
  691                         scr->reg12_value = NGLE_ARTIST_CMAP0;
  692                         scr->cmap_finish_register = NGLE_REG_26;
  693                 }
  694                 break;
  695 
  696         case STI_DD_GRX:
  697         case STI_DD_CRX24:
  698         case STI_DD_EVRX:
  699         case STI_DD_3X2V:
  700         case STI_DD_DUAL_CRX:
  701         case STI_DD_HCRX:
  702         case STI_DD_LEGO:
  703         case STI_DD_SUMMIT:
  704         case STI_DD_PINNACLE:
  705         default:
  706                 scr->setupfb = NULL;
  707                 scr->putcmap =
  708                     rom->scment == NULL ? NULL : ngle_default_putcmap;
  709                 break;
  710         }
  711 #endif
  712 
  713         return (0);
  714 
  715 fail:
  716         /* XXX free resources */
  717         if (scr->scr_ecfg.addr != NULL) {
  718                 free(scr->scr_ecfg.addr, M_DEVBUF, 0);
  719                 scr->scr_ecfg.addr = NULL;
  720         }
  721 
  722         return (ENXIO);
  723 }
  724 
  725 void
  726 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
  727 {
  728         struct sti_font *fp = &scr->scr_curfont;
  729 
  730         printf("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
  731             sc->sc_dev.dv_xname, scr->name, scr->fbwidth, scr->fbheight,
  732             scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
  733 
  734         printf("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
  735             sc->sc_dev.dv_xname, fp->width, fp->height,
  736             fp->type, fp->bpc, fp->first, fp->last);
  737 }
  738 
  739 void
  740 sti_describe(struct sti_softc *sc)
  741 {
  742         struct sti_rom *rom = sc->sc_rom;
  743         struct sti_dd *dd = &rom->rom_dd;
  744 
  745         printf(": rev %d.%02d;%d, ID 0x%08X%08X\n",
  746             dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
  747             dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
  748 
  749         if (sc->sc_scr != NULL)
  750                 sti_describe_screen(sc, sc->sc_scr);
  751 }
  752 
  753 /*
  754  * Final part of attachment. On hppa where we use the PDC console
  755  * during autoconf, this has to be postponed until autoconf has
  756  * completed.
  757  */
  758 void
  759 sti_end_attach(void *v)
  760 {
  761         struct sti_softc *sc = (struct sti_softc *)v;
  762 
  763         if (sc->sc_scr != NULL)
  764                 sti_end_attach_screen(sc, sc->sc_scr,
  765                     sc->sc_flags & STI_CONSOLE ? 1 : 0);
  766 }
  767 
  768 void
  769 sti_end_attach_screen(struct sti_softc *sc, struct sti_screen *scr, int console)
  770 {
  771         struct wsemuldisplaydev_attach_args waa;
  772 
  773         scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
  774 
  775         waa.console = console;
  776         waa.scrdata = &scr->scr_screenlist;
  777         waa.accessops = &sti_accessops;
  778         waa.accesscookie = scr;
  779         waa.defaultscreens = 0;
  780 
  781         /* attach as console if required */
  782         if (console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
  783                 uint32_t defattr;
  784 
  785                 sti_pack_attr(scr, 0, 0, 0, &defattr);
  786                 wsdisplay_cnattach(&scr->scr_wsd, scr,
  787                     0, scr->scr_wsd.nrows - 1, defattr);
  788                 sc->sc_flags |= STI_ATTACHED;
  789         }
  790 
  791         config_found(&sc->sc_dev, &waa, wsemuldisplaydevprint);
  792 }
  793 
  794 u_int
  795 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
  796 {
  797         int devtype;
  798         u_int romend;
  799 
  800         devtype = bus_space_read_1(memt, romh, 3);
  801         if (devtype == STI_DEVTYPE4) {
  802                 bus_space_read_raw_region_4(memt, romh, 0x18,
  803                     (u_int8_t *)&romend, 4);
  804         } else {
  805                 romend = parseword(0x50);
  806         }
  807 
  808         return (round_page(romend));
  809 }
  810 
  811 int
  812 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
  813     u_int32_t baseaddr, u_int fontindex)
  814 {
  815         struct sti_rom *rom = scr->scr_rom;
  816         bus_space_tag_t memt = rom->memt;
  817         bus_space_handle_t romh = rom->romh;
  818         struct sti_font *fp = &scr->scr_curfont;
  819         u_int32_t addr;
  820         int size;
  821 #ifdef notyet
  822         int uc;
  823         struct {
  824                 struct sti_unpmvflags flags;
  825                 struct sti_unpmvin in;
  826                 struct sti_unpmvout out;
  827         } a;
  828 #endif
  829 
  830         /*
  831          * Get the first PROM font in memory
  832          */
  833 
  834         STI_ENABLE_ROM(rom->rom_softc);
  835 
  836 rescan:
  837         addr = baseaddr;
  838         do {
  839                 if (rom->rom_devtype == STI_DEVTYPE1) {
  840                         fp->first  = parseshort(addr + 0x00);
  841                         fp->last   = parseshort(addr + 0x08);
  842                         fp->width  = bus_space_read_1(memt, romh,
  843                             addr + 0x13);
  844                         fp->height = bus_space_read_1(memt, romh,
  845                             addr + 0x17);
  846                         fp->type   = bus_space_read_1(memt, romh,
  847                             addr + 0x1b);
  848                         fp->bpc    = bus_space_read_1(memt, romh,
  849                             addr + 0x1f);
  850                         fp->next   = parseword(addr + 0x20);
  851                         fp->uheight= bus_space_read_1(memt, romh,
  852                             addr + 0x33);
  853                         fp->uoffset= bus_space_read_1(memt, romh,
  854                             addr + 0x37);
  855                 } else { /* STI_DEVTYPE4 */
  856                         bus_space_read_raw_region_4(memt, romh, addr,
  857                             (u_int8_t *)fp, sizeof(struct sti_font));
  858                 }
  859 
  860 #ifdef STIDEBUG
  861                 STI_DISABLE_ROM(rom->rom_softc);
  862                 printf("font@%p: %d-%d, %dx%d, type %d, next %x\n",
  863                     (void *)addr, fp->first, fp->last, fp->width, fp->height,
  864                     fp->type, fp->next);
  865                 STI_ENABLE_ROM(rom->rom_softc);
  866 #endif
  867 
  868                 if (fontindex == 0) {
  869                         size = sizeof(struct sti_font) +
  870                             (fp->last - fp->first + 1) * fp->bpc;
  871                         if (rom->rom_devtype == STI_DEVTYPE1)
  872                                 size *= 4;
  873                         scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT);
  874                         if (scr->scr_romfont == NULL)
  875                                 return (ENOMEM);
  876 
  877                         bus_space_read_raw_region_4(memt, romh, addr,
  878                             (u_int8_t *)scr->scr_romfont, size);
  879 
  880                         break;
  881                 }
  882 
  883                 addr = baseaddr + fp->next;
  884                 fontindex--;
  885         } while (fp->next != 0);
  886 
  887         /*
  888          * If our font index was bogus, we did not find the expected font.
  889          * In this case, pick the first one and be done with it.
  890          */
  891         if (fp->next == 0 && scr->scr_romfont == NULL) {
  892                 fontindex = 0;
  893                 goto rescan;
  894         }
  895 
  896         STI_DISABLE_ROM(rom->rom_softc);
  897 
  898 #ifdef notyet
  899         /*
  900          * If there is enough room in the off-screen framebuffer memory,
  901          * display all the characters there in order to display them
  902          * faster with blkmv operations rather than unpmv later on.
  903          */
  904         if (size <= cfg->fbheight *
  905             (cfg->fbwidth - cfg->width - cfg->owidth)) {
  906                 bzero(&a, sizeof(a));
  907                 a.flags.flags = STI_UNPMVF_WAIT;
  908                 a.in.fg_colour = STI_COLOUR_WHITE;
  909                 a.in.bg_colour = STI_COLOUR_BLACK;
  910                 a.in.font_addr = scr->scr_romfont;
  911 
  912                 scr->scr_fontmaxcol = cfg->fbheight / fp->height;
  913                 scr->scr_fontbase = cfg->width + cfg->owidth;
  914                 for (uc = fp->first; uc <= fp->last; uc++) {
  915                         a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
  916                             fp->width + scr->scr_fontbase;
  917                         a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
  918                             fp->height;
  919                         a.in.index = uc;
  920 
  921                         (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
  922                         if (a.out.errno) {
  923 #ifdef STIDEBUG
  924                                 printf("sti_unpmv %d returned %d\n",
  925                                     uc, a.out.errno);
  926 #endif
  927                                 return (0);
  928                         }
  929                 }
  930 
  931                 free(scr->scr_romfont, M_DEVBUF, 0);
  932                 scr->scr_romfont = NULL;
  933         }
  934 #endif
  935 
  936         return (0);
  937 }
  938 
  939 /*
  940  * Wrappers around STI code pointers
  941  */
  942 
  943 int
  944 sti_init(struct sti_screen *scr, int mode)
  945 {
  946         struct sti_rom *rom = scr->scr_rom;
  947         struct {
  948                 struct sti_initflags flags;
  949                 struct sti_initin in;
  950                 struct sti_einitin ein;
  951                 struct sti_initout out;
  952         } a;
  953 
  954         bzero(&a, sizeof(a));
  955 
  956         a.flags.flags = STI_INITF_WAIT | STI_INITF_EBET;
  957         if (mode & STI_TEXTMODE) {
  958                 a.flags.flags |= STI_INITF_TEXT /* | STI_INITF_PNTS */ |
  959                     STI_INITF_ICMT | STI_INITF_CMB;
  960                 if (mode & STI_CLEARSCR)
  961                         a.flags.flags |= STI_INITF_CLEAR;
  962         } else if (mode & STI_FBMODE) {
  963                 a.flags.flags |= STI_INITF_NTEXT /* | STI_INITF_PTS */;
  964         }
  965 
  966         a.in.text_planes = 1;
  967         a.in.ext_in = &a.ein;
  968 #ifdef STIDEBUG
  969         printf("sti_init,%p(%x, %p, %p, %p)\n",
  970             rom->init, a.flags.flags, &a.in, &a.out, &scr->scr_cfg);
  971 #endif
  972         (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
  973         if (a.out.text_planes != a.in.text_planes)
  974                 return (-1);    /* not colliding with sti errno values */
  975         return (a.out.errno);
  976 }
  977 
  978 int
  979 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
  980 {
  981         struct sti_rom *rom = scr->scr_rom;
  982         struct {
  983                 struct sti_inqconfflags flags;
  984                 struct sti_inqconfin in;
  985         } a;
  986 
  987         bzero(&a, sizeof(a));
  988 
  989         a.flags.flags = STI_INQCONFF_WAIT;
  990         (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
  991 
  992         return out->errno;
  993 }
  994 
  995 void
  996 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
  997     enum sti_bmove_funcs f)
  998 {
  999         struct sti_rom *rom = scr->scr_rom;
 1000         struct {
 1001                 struct sti_blkmvflags flags;
 1002                 struct sti_blkmvin in;
 1003                 struct sti_blkmvout out;
 1004         } a;
 1005 
 1006         bzero(&a, sizeof(a));
 1007 
 1008         a.flags.flags = STI_BLKMVF_WAIT;
 1009         switch (f) {
 1010         case bmf_clear:
 1011                 a.flags.flags |= STI_BLKMVF_CLR;
 1012                 a.in.bg_colour = STI_COLOUR_BLACK;
 1013                 break;
 1014         case bmf_underline:
 1015         case bmf_copy:
 1016                 a.in.fg_colour = STI_COLOUR_WHITE;
 1017                 a.in.bg_colour = STI_COLOUR_BLACK;
 1018                 break;
 1019         case bmf_invert:
 1020                 a.flags.flags |= STI_BLKMVF_COLR;
 1021                 a.in.fg_colour = STI_COLOUR_BLACK;
 1022                 a.in.bg_colour = STI_COLOUR_WHITE;
 1023                 break;
 1024         }
 1025         a.in.srcx = x1;
 1026         a.in.srcy = y1;
 1027         a.in.dstx = x2;
 1028         a.in.dsty = y2;
 1029         a.in.height = h;
 1030         a.in.width = w;
 1031 
 1032         (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
 1033 #ifdef STIDEBUG
 1034         if (a.out.errno)
 1035                 printf("sti_blkmv returned %d\n", a.out.errno);
 1036 #endif
 1037 }
 1038 
 1039 int
 1040 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
 1041 {
 1042         struct sti_rom *rom = scr->scr_rom;
 1043         struct {
 1044                 struct sti_scmentflags flags;
 1045                 struct sti_scmentin in;
 1046                 struct sti_scmentout out;
 1047         } a;
 1048 
 1049         bzero(&a, sizeof(a));
 1050 
 1051         a.flags.flags = STI_SCMENTF_WAIT;
 1052         a.in.entry = i;
 1053         a.in.value = (r << 16) | (g << 8) | b;
 1054 
 1055         (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
 1056 #ifdef STIDEBUG
 1057         if (a.out.errno)
 1058                 printf("sti_setcment(%d, %u, %u, %u): %d\n",
 1059                     i, r, g, b, a.out.errno);
 1060 #endif
 1061 
 1062         return a.out.errno;
 1063 }
 1064 
 1065 /*
 1066  * wsdisplay accessops
 1067  */
 1068 
 1069 int
 1070 sti_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
 1071 {
 1072         struct sti_screen *scr = (struct sti_screen *)v;
 1073         struct wsdisplay_fbinfo *wdf;
 1074         struct wsdisplay_cmap *cmapp;
 1075         u_int mode, idx, count;
 1076         int ret;
 1077 
 1078         ret = 0;
 1079         switch (cmd) {
 1080         case WSDISPLAYIO_SMODE:
 1081                 mode = *(u_int *)data;
 1082                 switch (mode) {
 1083                 case WSDISPLAYIO_MODE_EMUL:
 1084                         if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL)
 1085                                 ret = sti_init(scr, STI_TEXTMODE);
 1086                         break;
 1087                 case WSDISPLAYIO_MODE_DUMBFB:
 1088                         if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) {
 1089                                 if (scr->setupfb != NULL)
 1090                                         scr->setupfb(scr);
 1091                                 else
 1092 #if 0
 1093                                         ret = sti_init(scr, STI_FBMODE);
 1094 #else
 1095                                         ret = EINVAL;
 1096 #endif
 1097                         }
 1098                         break;
 1099                 case WSDISPLAYIO_MODE_MAPPED:
 1100                 default:
 1101                         ret = EINVAL;
 1102                         break;
 1103                 }
 1104                 if (ret == 0)
 1105                         scr->scr_wsmode = mode;
 1106                 break;
 1107 
 1108         case WSDISPLAYIO_GTYPE:
 1109                 *(u_int *)data = WSDISPLAY_TYPE_STI;
 1110                 break;
 1111 
 1112         case WSDISPLAYIO_GINFO:
 1113                 wdf = (struct wsdisplay_fbinfo *)data;
 1114                 wdf->height = scr->scr_cfg.scr_height;
 1115                 wdf->width  = scr->scr_cfg.scr_width;
 1116                 wdf->depth  = scr->scr_bpp;
 1117                 if (scr->scr_bpp > 8)
 1118                         wdf->stride = scr->scr_cfg.fb_width * 4;
 1119                 else
 1120                         wdf->stride = scr->scr_cfg.fb_width;
 1121                 wdf->offset = 0;
 1122                 if (scr->putcmap == NULL || scr->scr_bpp > 8)
 1123                         wdf->cmsize = 0;
 1124                 else
 1125                         wdf->cmsize = STI_NCMAP;
 1126                 break;
 1127 
 1128         case WSDISPLAYIO_LINEBYTES:
 1129                 if (scr->scr_bpp > 8)
 1130                         *(u_int *)data = scr->scr_cfg.fb_width * 4;
 1131                 else
 1132                         *(u_int *)data = scr->scr_cfg.fb_width;
 1133                 break;
 1134 
 1135         case WSDISPLAYIO_GETSUPPORTEDDEPTH:
 1136                 if (scr->scr_bpp > 8)
 1137                         *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
 1138                 else
 1139                         *(u_int *)data = WSDISPLAYIO_DEPTH_8;
 1140                 break;
 1141 
 1142         case WSDISPLAYIO_GETCMAP:
 1143                 if (scr->putcmap == NULL || scr->scr_bpp > 8)
 1144                         return ENODEV;
 1145                 cmapp = (struct wsdisplay_cmap *)data;
 1146                 idx = cmapp->index;
 1147                 count = cmapp->count;
 1148                 if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
 1149                         return EINVAL;
 1150                 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
 1151                         break;
 1152                 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
 1153                         break;
 1154                 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
 1155                         break;
 1156                 break;
 1157 
 1158         case WSDISPLAYIO_PUTCMAP:
 1159                 if (scr->putcmap == NULL || scr->scr_bpp > 8)
 1160                         return ENODEV;
 1161                 cmapp = (struct wsdisplay_cmap *)data;
 1162                 idx = cmapp->index;
 1163                 count = cmapp->count;
 1164                 if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
 1165                         return EINVAL;
 1166                 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
 1167                         break;
 1168                 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
 1169                         break;
 1170                 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
 1171                         break;
 1172                 ret = scr->putcmap(scr, idx, count);
 1173                 break;
 1174 
 1175         case WSDISPLAYIO_SVIDEO:
 1176         case WSDISPLAYIO_GVIDEO:
 1177                 break;
 1178 
 1179         default:
 1180                 return (-1);            /* not supported yet */
 1181         }
 1182 
 1183         return (ret);
 1184 }
 1185 
 1186 paddr_t
 1187 sti_mmap(void *v, off_t offset, int prot)
 1188 {
 1189         struct sti_screen *scr = (struct sti_screen *)v;
 1190 #if 0
 1191         struct sti_rom *rom = scr->scr_rom;
 1192 #endif
 1193         paddr_t pa;
 1194 
 1195         if ((offset & PAGE_MASK) != 0)
 1196                 return -1;
 1197 
 1198         if (offset < 0 || offset >= scr->fblen)
 1199                 return -1;
 1200 
 1201 #if 0 /* XXX not all platforms provide bus_space_mmap() yet */
 1202         pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot,
 1203             BUS_SPACE_MAP_LINEAR);
 1204 #else
 1205         pa = scr->fbaddr + offset;
 1206 #endif
 1207 
 1208         return pa;
 1209 }
 1210 
 1211 int
 1212 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
 1213     int *cxp, int *cyp, uint32_t *defattr)
 1214 {
 1215         struct sti_screen *scr = (struct sti_screen *)v;
 1216 
 1217         if (scr->scr_nscreens > 0)
 1218                 return ENOMEM;
 1219 
 1220         *cookiep = scr;
 1221         *cxp = 0;
 1222         *cyp = 0;
 1223         sti_pack_attr(scr, 0, 0, 0, defattr);
 1224         scr->scr_nscreens++;
 1225         return 0;
 1226 }
 1227 
 1228 void
 1229 sti_free_screen(void *v, void *cookie)
 1230 {
 1231         struct sti_screen *scr = (struct sti_screen *)v;
 1232 
 1233         scr->scr_nscreens--;
 1234 }
 1235 
 1236 int
 1237 sti_show_screen(void *v, void *cookie, int waitok,
 1238     void (*cb)(void *, int, int), void *cbarg)
 1239 {
 1240 #if 0
 1241         struct sti_screen *scr = (struct sti_screen *)v;
 1242 #endif
 1243 
 1244         return 0;
 1245 }
 1246 
 1247 /*
 1248  * wsdisplay emulops
 1249  */
 1250 
 1251 int
 1252 sti_cursor(void *v, int on, int row, int col)
 1253 {
 1254         struct sti_screen *scr = (struct sti_screen *)v;
 1255         struct sti_font *fp = &scr->scr_curfont;
 1256 
 1257         sti_bmove(scr,
 1258             col * fp->width, row * fp->height,
 1259             col * fp->width, row * fp->height,
 1260             fp->height, fp->width, bmf_invert);
 1261 
 1262         return 0;
 1263 }
 1264 
 1265 /*
 1266  * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
 1267  */
 1268 static const u_int8_t
 1269 sti_unitoroman[0x100 - 0xa0] = {
 1270         0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc,    0, 0xbd,
 1271         0xab,    0, 0xf9, 0xfb,    0, 0xf6,    0, 0xb0,
 1272         
 1273         0xb3, 0xfe,    0,    0, 0xa8, 0xf3, 0xf4, 0xf2,
 1274            0,    0, 0xfa, 0xfd, 0xf7, 0xf8,    0, 0xb9,
 1275 
 1276         0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
 1277         0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
 1278 
 1279         0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda,    0,
 1280         0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
 1281 
 1282         0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
 1283         0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
 1284 
 1285         0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce,    0,
 1286         0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
 1287 };
 1288 
 1289 int
 1290 sti_mapchar(void *v, int uni, u_int *index)
 1291 {
 1292         struct sti_screen *scr = (struct sti_screen *)v;
 1293         struct sti_font *fp = &scr->scr_curfont;
 1294         int c;
 1295 
 1296         switch (fp->type) {
 1297         case STI_FONT_HPROMAN8:
 1298                 if (uni >= 0x80 && uni < 0xa0)
 1299                         c = -1;
 1300                 else if (uni >= 0xa0 && uni < 0x100) {
 1301                         c = (int)sti_unitoroman[uni - 0xa0];
 1302                         if (c == 0)
 1303                                 c = -1;
 1304                 } else
 1305                         c = uni;
 1306                 break;
 1307         default:
 1308                 c = uni;
 1309                 break;
 1310         }
 1311 
 1312         if (c == -1 || c < fp->first || c > fp->last) {
 1313                 *index = '?';
 1314                 return (0);
 1315         }
 1316 
 1317         *index = c;
 1318         return (5);
 1319 }
 1320 
 1321 int
 1322 sti_putchar(void *v, int row, int col, u_int uc, uint32_t attr)
 1323 {
 1324         struct sti_screen *scr = (struct sti_screen *)v;
 1325         struct sti_rom *rom = scr->scr_rom;
 1326         struct sti_font *fp = &scr->scr_curfont;
 1327         int bg, fg;
 1328 
 1329         sti_unpack_attr(scr, attr, &fg, &bg, NULL);
 1330 
 1331         if (scr->scr_romfont != NULL) {
 1332                 /*
 1333                  * Font is in memory, use unpmv
 1334                  */
 1335                 struct {
 1336                         struct sti_unpmvflags flags;
 1337                         struct sti_unpmvin in;
 1338                         struct sti_unpmvout out;
 1339                 } a;
 1340 
 1341                 bzero(&a, sizeof(a));
 1342 
 1343                 a.flags.flags = STI_UNPMVF_WAIT;
 1344                 a.in.fg_colour = fg;
 1345                 a.in.bg_colour = bg;
 1346 
 1347                 a.in.x = col * fp->width;
 1348                 a.in.y = row * fp->height;
 1349                 a.in.font_addr = scr->scr_romfont;
 1350                 a.in.index = uc;
 1351 
 1352                 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
 1353         } else {
 1354                 /*
 1355                  * Font is in frame buffer, use blkmv
 1356                  */
 1357                 struct {
 1358                         struct sti_blkmvflags flags;
 1359                         struct sti_blkmvin in;
 1360                         struct sti_blkmvout out;
 1361                 } a;
 1362 
 1363                 bzero(&a, sizeof(a));
 1364 
 1365                 a.flags.flags = STI_BLKMVF_WAIT;
 1366                 a.in.fg_colour = fg;
 1367                 a.in.bg_colour = bg;
 1368 
 1369                 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
 1370                     fp->width + scr->scr_fontbase;
 1371                 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
 1372                     fp->height;
 1373                 a.in.dstx = col * fp->width;
 1374                 a.in.dsty = row * fp->height;
 1375                 a.in.height = fp->height;
 1376                 a.in.width = fp->width;
 1377 
 1378                 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
 1379         }
 1380 
 1381         return 0;
 1382 }
 1383 
 1384 int
 1385 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
 1386 {
 1387         struct sti_screen *scr = (struct sti_screen *)v;
 1388         struct sti_font *fp = &scr->scr_curfont;
 1389 
 1390         sti_bmove(scr,
 1391             srccol * fp->width, row * fp->height,
 1392             dstcol * fp->width, row * fp->height,
 1393             fp->height, ncols * fp->width, bmf_copy);
 1394 
 1395         return 0;
 1396 }
 1397 
 1398 int
 1399 sti_erasecols(void *v, int row, int startcol, int ncols, uint32_t attr)
 1400 {
 1401         struct sti_screen *scr = (struct sti_screen *)v;
 1402         struct sti_font *fp = &scr->scr_curfont;
 1403 
 1404         sti_bmove(scr,
 1405             startcol * fp->width, row * fp->height,
 1406             startcol * fp->width, row * fp->height,
 1407             fp->height, ncols * fp->width, bmf_clear);
 1408 
 1409         return 0;
 1410 }
 1411 
 1412 int
 1413 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
 1414 {
 1415         struct sti_screen *scr = (struct sti_screen *)v;
 1416         struct sti_font *fp = &scr->scr_curfont;
 1417 
 1418         sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
 1419             nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
 1420 
 1421         return 0;
 1422 }
 1423 
 1424 int
 1425 sti_eraserows(void *v, int srcrow, int nrows, uint32_t attr)
 1426 {
 1427         struct sti_screen *scr = (struct sti_screen *)v;
 1428         struct sti_font *fp = &scr->scr_curfont;
 1429 
 1430         sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
 1431             nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
 1432 
 1433         return 0;
 1434 }
 1435 
 1436 int
 1437 sti_pack_attr(void *v, int fg, int bg, int flags, uint32_t *pattr)
 1438 {
 1439 #if 0
 1440         struct sti_screen *scr = (struct sti_screen *)v;
 1441 #endif
 1442 
 1443         *pattr = flags & WSATTR_REVERSE;
 1444         return 0;
 1445 }
 1446 
 1447 void
 1448 sti_unpack_attr(void *v, uint32_t attr, int *fg, int *bg, int *ul)
 1449 {
 1450 #if 0
 1451         struct sti_screen *scr = (struct sti_screen *)v;
 1452 #endif
 1453 
 1454         if (attr & WSATTR_REVERSE) {
 1455                 *fg = STI_COLOUR_BLACK;
 1456                 *bg = STI_COLOUR_WHITE;
 1457         } else {
 1458                 *fg = STI_COLOUR_WHITE;
 1459                 *bg = STI_COLOUR_BLACK;
 1460         }
 1461         if (ul != NULL)
 1462                 *ul = 0;
 1463 }
 1464 
 1465 int
 1466 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count)
 1467 {
 1468         int i, ret;
 1469 
 1470         for (i = idx + count - 1; i >= (int)idx; i--)
 1471                 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
 1472                     scr->scr_gcmap[i], scr->scr_bcmap[i])))
 1473                         return EINVAL;
 1474 
 1475         return 0;
 1476 }
 1477 
 1478 #ifndef SMALL_KERNEL
 1479 
 1480 void    ngle_setup_hw(bus_space_tag_t, bus_space_handle_t);
 1481 void    ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t);
 1482 void    ngle_setup_attr_planes(struct sti_screen *scr);
 1483 void    ngle_setup_bt458(struct sti_screen *scr);
 1484 
 1485 #define ngle_bt458_write(memt, memh, r, v) \
 1486         bus_space_write_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
 1487 
 1488 void
 1489 ngle_artist_setupfb(struct sti_screen *scr)
 1490 {
 1491         struct sti_rom *rom = scr->scr_rom;
 1492         bus_space_tag_t memt = rom->memt;
 1493         bus_space_handle_t memh = rom->regh[2];
 1494 
 1495         ngle_setup_bt458(scr);
 1496 
 1497         ngle_setup_hw(memt, memh);
 1498         ngle_setup_fb(memt, memh, scr->reg10_value);
 1499 
 1500         ngle_setup_attr_planes(scr);
 1501 
 1502         ngle_setup_hw(memt, memh);
 1503         bus_space_write_4(memt, memh, NGLE_REG_21,
 1504             bus_space_read_4(memt, memh, NGLE_REG_21) | 0x0a000000);
 1505         bus_space_write_4(memt, memh, NGLE_REG_27,
 1506             bus_space_read_4(memt, memh, NGLE_REG_27) | 0x00800000);
 1507 }
 1508 
 1509 void
 1510 ngle_elk_setupfb(struct sti_screen *scr)
 1511 {
 1512         struct sti_rom *rom = scr->scr_rom;
 1513         bus_space_tag_t memt = rom->memt;
 1514         bus_space_handle_t memh = rom->regh[2];
 1515 
 1516         ngle_setup_bt458(scr);
 1517 
 1518         ngle_setup_hw(memt, memh);
 1519         ngle_setup_fb(memt, memh, scr->reg10_value);
 1520 
 1521         ngle_setup_attr_planes(scr);
 1522 
 1523         ngle_setup_hw(memt, memh);
 1524         /* enable overlay planes in Bt458 command register */
 1525         ngle_bt458_write(memt, memh, 0x0c, 0x06);
 1526         ngle_bt458_write(memt, memh, 0x0e, 0x43);
 1527 }
 1528 
 1529 void
 1530 ngle_timber_setupfb(struct sti_screen *scr)
 1531 {
 1532         struct sti_rom *rom = scr->scr_rom;
 1533         bus_space_tag_t memt = rom->memt;
 1534         bus_space_handle_t memh = rom->regh[2];
 1535 
 1536         ngle_setup_bt458(scr);
 1537 
 1538         ngle_setup_hw(memt, memh);
 1539         /* enable overlay planes in Bt458 command register */
 1540         ngle_bt458_write(memt, memh, 0x0c, 0x06);
 1541         ngle_bt458_write(memt, memh, 0x0e, 0x43);
 1542 }
 1543 
 1544 void
 1545 ngle_setup_bt458(struct sti_screen *scr)
 1546 {
 1547         struct sti_rom *rom = scr->scr_rom;
 1548         bus_space_tag_t memt = rom->memt;
 1549         bus_space_handle_t memh = rom->regh[2];
 1550 
 1551         ngle_setup_hw(memt, memh);
 1552         /* set Bt458 read mask register to all planes */
 1553         ngle_bt458_write(memt, memh, 0x08, 0x04);
 1554         ngle_bt458_write(memt, memh, 0x0a, 0xff);
 1555 }
 1556 
 1557 void
 1558 ngle_setup_attr_planes(struct sti_screen *scr)
 1559 {
 1560         struct sti_rom *rom = scr->scr_rom;
 1561         bus_space_tag_t memt = rom->memt;
 1562         bus_space_handle_t memh = rom->regh[2];
 1563 
 1564         ngle_setup_hw(memt, memh);
 1565         bus_space_write_4(memt, memh, NGLE_REG_11, 0x2ea0d000);
 1566         bus_space_write_4(memt, memh, NGLE_REG_14, 0x23000302);
 1567         bus_space_write_4(memt, memh, NGLE_REG_12, scr->reg12_value);
 1568         bus_space_write_4(memt, memh, NGLE_REG_8, 0xffffffff);
 1569 
 1570         bus_space_write_4(memt, memh, NGLE_REG_6, 0x00000000);
 1571         bus_space_write_4(memt, memh, NGLE_REG_9,
 1572             (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height);
 1573         bus_space_write_4(memt, memh, NGLE_REG_6, 0x05000000);
 1574         bus_space_write_4(memt, memh, NGLE_REG_9, 0x00040001);
 1575 
 1576         ngle_setup_hw(memt, memh);
 1577         bus_space_write_4(memt, memh, NGLE_REG_12, 0x00000000);
 1578 
 1579         ngle_setup_fb(memt, memh, scr->reg10_value);
 1580 }
 1581 
 1582 int
 1583 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count)
 1584 {
 1585         struct sti_rom *rom = scr->scr_rom;
 1586         bus_space_tag_t memt = rom->memt;
 1587         bus_space_handle_t memh = rom->regh[2];
 1588         uint8_t *r, *g, *b;
 1589         uint32_t cmap_finish;
 1590 
 1591         if (scr->scr_bpp > 8)
 1592                 cmap_finish = 0x83000100;
 1593         else
 1594                 cmap_finish = 0x80000100;
 1595 
 1596         r = scr->scr_rcmap + idx;
 1597         g = scr->scr_gcmap + idx;
 1598         b = scr->scr_bcmap + idx;
 1599 
 1600         ngle_setup_hw(memt, memh);
 1601         bus_space_write_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
 1602         bus_space_write_4(memt, memh, NGLE_REG_14, 0x03000300);
 1603         bus_space_write_4(memt, memh, NGLE_REG_13, 0xffffffff);
 1604 
 1605         while (count-- != 0) {
 1606                 ngle_setup_hw(memt, memh);
 1607                 bus_space_write_4(memt, memh, NGLE_REG_3, 0x400 | (idx << 2));
 1608                 bus_space_write_4(memt, memh, NGLE_REG_4,
 1609                     (*r << 16) | (*g << 8) | *b);
 1610 
 1611                 idx++;
 1612                 r++, g++, b++;
 1613         }
 1614 
 1615         bus_space_write_4(memt, memh, NGLE_REG_2, 0x400);
 1616         bus_space_write_4(memt, memh, scr->cmap_finish_register, cmap_finish);
 1617         ngle_setup_fb(memt, memh, scr->reg10_value);
 1618 
 1619 
 1620         return 0;
 1621 }
 1622 
 1623 void
 1624 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh)
 1625 {
 1626         uint8_t stat;
 1627 
 1628         do {
 1629                 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
 1630                 if (stat == 0)
 1631                         stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
 1632         } while (stat != 0);
 1633 }
 1634 
 1635 void
 1636 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10)
 1637 {
 1638         ngle_setup_hw(memt, memh);
 1639         bus_space_write_4(memt, memh, NGLE_REG_10, reg10);
 1640         bus_space_write_4(memt, memh, NGLE_REG_14, 0x83000300);
 1641         ngle_setup_hw(memt, memh);
 1642         bus_space_write_1(memt, memh, NGLE_REG_16b1, 1);
 1643 }
 1644 #endif  /* SMALL_KERNEL */

Cache object: 33cb77b13c60be8654f11407830eff95


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.