[BACK]Return to tga.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/tga.c, Revision 1.1

1.1     ! nbrk        1: /* $OpenBSD: tga.c,v 1.29 2006/12/17 22:18:16 miod Exp $ */
        !             2: /* $NetBSD: tga.c,v 1.40 2002/03/13 15:05:18 ad Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Author: Chris G. Demetriou
        !             9:  *
        !            10:  * Permission to use, copy, modify and distribute this software and
        !            11:  * its documentation is hereby granted, provided that both the copyright
        !            12:  * notice and this permission notice appear in all copies of the
        !            13:  * software, derivative works or modified versions, and any portions
        !            14:  * thereof, and that both notices appear in supporting documentation.
        !            15:  *
        !            16:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            17:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
        !            18:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            19:  *
        !            20:  * Carnegie Mellon requests users of this software to return to
        !            21:  *
        !            22:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            23:  *  School of Computer Science
        !            24:  *  Carnegie Mellon University
        !            25:  *  Pittsburgh PA 15213-3890
        !            26:  *
        !            27:  * any improvements or extensions that they make and grant Carnegie the
        !            28:  * rights to redistribute these changes.
        !            29:  */
        !            30:
        !            31: #include <sys/param.h>
        !            32: #include <sys/systm.h>
        !            33: #include <sys/kernel.h>
        !            34: #include <sys/device.h>
        !            35: #include <sys/conf.h>
        !            36: #include <sys/malloc.h>
        !            37: #include <sys/buf.h>
        !            38: #include <sys/ioctl.h>
        !            39:
        !            40: #include <machine/bus.h>
        !            41: #include <machine/intr.h>
        !            42:
        !            43: #include <dev/pci/pcireg.h>
        !            44: #include <dev/pci/pcivar.h>
        !            45: #include <dev/pci/pcidevs.h>
        !            46: #include <dev/pci/tgareg.h>
        !            47: #include <dev/pci/tgavar.h>
        !            48: #include <dev/ic/bt485reg.h>
        !            49: #include <dev/ic/bt485var.h>
        !            50: #include <dev/ic/bt463reg.h>
        !            51: #include <dev/ic/bt463var.h>
        !            52: #include <dev/ic/ibm561var.h>
        !            53:
        !            54: #include <dev/wscons/wsconsio.h>
        !            55: #include <dev/rasops/rasops.h>
        !            56: #include <dev/wsfont/wsfont.h>
        !            57:
        !            58: #if defined(__alpha__) || defined(__mips__)
        !            59: #include <uvm/uvm_extern.h>
        !            60: #endif
        !            61:
        !            62: #ifdef __alpha__
        !            63: #include <machine/pte.h>
        !            64: #endif
        !            65: #ifdef __mips__
        !            66: #include <mips/pte.h>
        !            67: #endif
        !            68:
        !            69: int    tgamatch(struct device *, struct cfdata *, void *);
        !            70: void   tgaattach(struct device *, struct device *, void *);
        !            71: int    tgaprint(void *, const char *);
        !            72:
        !            73: struct cfdriver tga_cd = {
        !            74:        NULL, "tga", DV_DULL
        !            75: };
        !            76:
        !            77: struct cfattach tga_ca = {
        !            78:        sizeof(struct tga_softc), (cfmatch_t)tgamatch, tgaattach,
        !            79: };
        !            80:
        !            81: int    tga_identify(struct tga_devconfig *);
        !            82: const struct tga_conf *tga_getconf(int);
        !            83: void   tga_getdevconfig(bus_space_tag_t memt, pci_chipset_tag_t pc,
        !            84:            pcitag_t tag, struct tga_devconfig *dc);
        !            85: unsigned tga_getdotclock(struct tga_devconfig *dc);
        !            86:
        !            87: struct tga_devconfig tga_console_dc;
        !            88:
        !            89: int    tga_ioctl(void *, u_long, caddr_t, int, struct proc *);
        !            90: paddr_t        tga_mmap(void *, off_t, int);
        !            91: void   tga_copyrows(void *, int, int, int);
        !            92: void   tga_copycols(void *, int, int, int, int);
        !            93: int    tga_alloc_screen(void *, const struct wsscreen_descr *,
        !            94:            void **, int *, int *, long *);
        !            95: void   tga_free_screen(void *, void *);
        !            96: int    tga_show_screen(void *, void *, int,
        !            97:                           void (*) (void *, int, int), void *);
        !            98: void   tga_burner(void *, u_int, u_int);
        !            99: int    tga_rop(struct rasops_info *, int, int, int, int,
        !           100:        struct rasops_info *, int, int);
        !           101: int    tga_rop_vtov(struct rasops_info *, int, int, int,
        !           102:        int, struct rasops_info *, int, int );
        !           103: void   tga_putchar(void *c, int row, int col, u_int uc, long attr);
        !           104: void   tga_eraserows(void *, int, int, long);
        !           105: void   tga_erasecols(void *, int, int, int, long);
        !           106: void   tga2_init(struct tga_devconfig *);
        !           107:
        !           108: void   tga_config_interrupts(struct device *);
        !           109:
        !           110: /* RAMDAC interface functions */
        !           111: int     tga_sched_update(void *, void (*)(void *));
        !           112: void    tga_ramdac_wr(void *, u_int, u_int8_t);
        !           113: u_int8_t tga_ramdac_rd(void *, u_int);
        !           114: void    tga_bt463_wr(void *, u_int, u_int8_t);
        !           115: u_int8_t tga_bt463_rd(void *, u_int);
        !           116: void    tga2_ramdac_wr(void *, u_int, u_int8_t);
        !           117: u_int8_t tga2_ramdac_rd(void *, u_int);
        !           118:
        !           119: /* Interrupt handler */
        !           120: int    tga_intr(void *);
        !           121:
        !           122: /* The NULL entries will get filled in by rasops_init().
        !           123:  * XXX and the non-NULL ones will be overwritten; reset after calling it.
        !           124:  */
        !           125: struct wsdisplay_emulops tga_emulops = {
        !           126:        NULL,
        !           127:        NULL,
        !           128:        tga_putchar,
        !           129:        tga_copycols,
        !           130:        tga_erasecols,
        !           131:        tga_copyrows,
        !           132:        tga_eraserows,
        !           133:        NULL,
        !           134:        NULL
        !           135: };
        !           136:
        !           137: struct wsscreen_descr tga_stdscreen = {
        !           138:        "std",
        !           139:        0, 0,   /* will be filled in -- XXX shouldn't, it's global */
        !           140:        &tga_emulops,
        !           141:        0, 0,
        !           142:        WSSCREEN_UNDERLINE | WSSCREEN_HILIT |
        !           143:            WSSCREEN_WSCOLORS | WSSCREEN_REVERSE
        !           144: };
        !           145:
        !           146: const struct wsscreen_descr *_tga_scrlist[] = {
        !           147:        &tga_stdscreen,
        !           148:        /* XXX other formats, graphics screen? */
        !           149: };
        !           150:
        !           151: struct wsscreen_list tga_screenlist = {
        !           152:        sizeof(_tga_scrlist) / sizeof(struct wsscreen_descr *), _tga_scrlist
        !           153: };
        !           154:
        !           155: struct wsdisplay_accessops tga_accessops = {
        !           156:        tga_ioctl,
        !           157:        tga_mmap,
        !           158:        tga_alloc_screen,
        !           159:        tga_free_screen,
        !           160:        tga_show_screen,
        !           161:        NULL,                   /* load_font */
        !           162:        NULL,                   /* scrollback */
        !           163:        NULL,                   /* getchar */
        !           164:        tga_burner,
        !           165: };
        !           166:
        !           167: void   tga_blank(struct tga_devconfig *);
        !           168: void   tga_unblank(struct tga_devconfig *);
        !           169:
        !           170: #ifdef TGA_DEBUG
        !           171: #define DPRINTF(...)      printf (__VA_ARGS__)
        !           172: #define DPRINTFN(n, ...)   if (tgadebug > (n)) printf (__VA_ARGS__)
        !           173: int tgadebug = 0;
        !           174: #else
        !           175: #define DPRINTF(...)
        !           176: #define DPRINTFN(n,...)
        !           177: #endif
        !           178:
        !           179: const struct pci_matchid tga_devices[] = {
        !           180:        { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21030 },
        !           181:        { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_PBXGB },
        !           182: };
        !           183:
        !           184: int
        !           185: tgamatch(parent, match, aux)
        !           186:        struct device *parent;
        !           187:        struct cfdata *match;
        !           188:        void *aux;
        !           189: {
        !           190:        if (pci_matchbyid((struct pci_attach_args *)aux, tga_devices,
        !           191:            sizeof(tga_devices) / sizeof(tga_devices[0])))
        !           192:                return (10);    /* need to return more than vga_pci here! */
        !           193:
        !           194:        return (0);
        !           195: }
        !           196:
        !           197: void
        !           198: tga_getdevconfig(memt, pc, tag, dc)
        !           199:        bus_space_tag_t memt;
        !           200:        pci_chipset_tag_t pc;
        !           201:        pcitag_t tag;
        !           202:        struct tga_devconfig *dc;
        !           203: {
        !           204:        const struct tga_conf *tgac;
        !           205:        struct rasops_info *rip;
        !           206:        int cookie;
        !           207:        bus_size_t pcisize;
        !           208:        int i;
        !           209:
        !           210:        dc->dc_memt = memt;
        !           211:
        !           212:        dc->dc_pcitag = tag;
        !           213:
        !           214:        DPRINTF("tga_getdevconfig: Getting map info\n");
        !           215:        /* XXX magic number */
        !           216:        if (pci_mapreg_info(pc, tag, 0x10,
        !           217:            PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
        !           218:            &dc->dc_pcipaddr, &pcisize, NULL))
        !           219:                return;
        !           220:
        !           221:        DPRINTF("tga_getdevconfig: preparing to map\n");
        !           222: #ifdef __OpenBSD__
        !           223:        if (bus_space_map(memt, dc->dc_pcipaddr, pcisize, 1, &dc->dc_memh))
        !           224:                return;
        !           225:        dc->dc_vaddr = dc->dc_memh;
        !           226: #else
        !           227:        if (bus_space_map(memt, dc->dc_pcipaddr, pcisize,
        !           228:            BUS_SPACE_MAP_PREFETCHABLE | BUS_SPACE_MAP_LINEAR, &dc->dc_memh))
        !           229:                return;
        !           230:        dc->dc_vaddr = (vaddr_t) bus_space_vaddr(memt, dc->dc_memh);
        !           231: #endif
        !           232:        DPRINTF("tga_getdevconfig: mapped\n");
        !           233:
        !           234: #ifdef __alpha__
        !           235:        dc->dc_paddr = ALPHA_K0SEG_TO_PHYS(dc->dc_vaddr);       /* XXX */
        !           236: #endif
        !           237: #ifdef arc
        !           238:        bus_space_paddr(memt, dc->dc_memh, &dc->dc_paddr);
        !           239: #endif
        !           240:        DPRINTF("tga_getdevconfig: allocating subregion\n");
        !           241:        bus_space_subregion(dc->dc_memt, dc->dc_memh,
        !           242:                            TGA_MEM_CREGS, TGA_CREGS_SIZE,
        !           243:                            &dc->dc_regs);
        !           244:
        !           245:        DPRINTF("tga_getdevconfig: going to identify\n");
        !           246:        dc->dc_tga_type = tga_identify(dc);
        !           247:
        !           248:        DPRINTF("tga_getdevconfig: preparing to get config\n");
        !           249:        tgac = dc->dc_tgaconf = tga_getconf(dc->dc_tga_type);
        !           250:        if (tgac == NULL)
        !           251:                return;
        !           252:
        !           253: #if 0
        !           254:        /* XXX on the Alpha, pcisize = 4 * cspace_size. */
        !           255:        if (tgac->tgac_cspace_size != pcisize)                  /* sanity */
        !           256:                panic("tga_getdevconfig: memory size mismatch?");
        !           257: #endif
        !           258:
        !           259:        DPRINTF("tga_getdevconfig: get revno\n");
        !           260:        switch (TGARREG(dc, TGA_REG_GREV) & 0xff) {
        !           261:        case 0x01:
        !           262:        case 0x02:
        !           263:        case 0x03:
        !           264:        case 0x04:
        !           265:                dc->dc_tga2 = 0;
        !           266:                break;
        !           267:        case 0x20:
        !           268:        case 0x21:
        !           269:        case 0x22:
        !           270:                dc->dc_tga2 = 1;
        !           271:                break;
        !           272:        default:
        !           273:                panic("tga_getdevconfig: TGA Revision not recognized");
        !           274:        }
        !           275:
        !           276:        if (dc->dc_tga2) {
        !           277:                tga2_init(dc);
        !           278:        }
        !           279:
        !           280:        i = TGARREG(dc, TGA_REG_VHCR) & 0x1ff;
        !           281:        DPRINTF("tga_getdevconfig: TGA_REG_VHCR & 0x1ff = %d\n", i);
        !           282:        switch (i) {            /* XXX */
        !           283:        case 0:
        !           284:                dc->dc_wid = 8192;
        !           285:                break;
        !           286:
        !           287:        case 1:
        !           288:                dc->dc_wid = 8196;
        !           289:                break;
        !           290:
        !           291:        default:
        !           292:                dc->dc_wid = (TGARREG(dc, TGA_REG_VHCR) & 0x1ff) * 4; /* XXX */
        !           293:                break;
        !           294:        }
        !           295:
        !           296:        DPRINTF("tga_getdevconfig: dc->dc_wid = %d\n", dc->dc_wid);
        !           297:        /*
        !           298:         * XXX XXX Turning off "odd" shouldn't be necessary,
        !           299:         * XXX XXX but I can't make X work with the weird size.
        !           300:         */
        !           301:        DPRINTF("tga_getdevconfig: beginning magic incantation\n");
        !           302:        if ((TGARREG(dc, TGA_REG_VHCR) & 0x00000001) != 0 &&    /* XXX */
        !           303:            (TGARREG(dc, TGA_REG_VHCR) & 0x80000000) != 0) {    /* XXX */
        !           304:                TGAWREG(dc, TGA_REG_VHCR,
        !           305:                    (TGARREG(dc, TGA_REG_VHCR) & ~0x80000001));
        !           306:                dc->dc_wid -= 4;
        !           307:        }
        !           308:
        !           309:        dc->dc_rowbytes = dc->dc_wid * (dc->dc_tgaconf->tgac_phys_depth / 8);
        !           310:        dc->dc_ht = (TGARREG(dc, TGA_REG_VVCR) & 0x7ff);        /* XXX */
        !           311:        DPRINTF("tga_getdevconfig: rowbytes = %d, tgac_phys_depth = %d\n"
        !           312:                "                  dc_wid = %d, dc_ht = %d\n",
        !           313:                dc->dc_rowbytes, dc->dc_tgaconf->tgac_phys_depth,
        !           314:                dc->dc_wid, dc->dc_ht);
        !           315:
        !           316:        /* XXX this seems to be what DEC does */
        !           317:        DPRINTF("tga_getdevconfig: more magic\n");
        !           318:        TGAWREG(dc, TGA_REG_CCBR, 0);
        !           319:        TGAWREG(dc, TGA_REG_VVBR, 1);
        !           320:        dc->dc_videobase = dc->dc_vaddr + tgac->tgac_dbuf[0] +
        !           321:            1 * tgac->tgac_vvbr_units;
        !           322:        dc->dc_blanked = 1;
        !           323:        tga_unblank(dc);
        !           324:
        !           325:        DPRINTF("tga_getdevconfig: dc_videobase = 0x%016llx\n"
        !           326:                "                  dc_vaddr = 0x%016llx\n"
        !           327:                "                  tgac_dbuf[0] = %d\n"
        !           328:                "                  tgac_vvbr_units = %d\n",
        !           329:                dc->dc_videobase, dc->dc_vaddr, tgac->tgac_dbuf[0],
        !           330:                tgac->tgac_vvbr_units);
        !           331:
        !           332:        /*
        !           333:         * Set all bits in the pixel mask, to enable writes to all pixels.
        !           334:         * It seems that the console firmware clears some of them
        !           335:         * under some circumstances, which causes cute vertical stripes.
        !           336:         */
        !           337:        DPRINTF("tga_getdevconfig: set pixel mask\n");
        !           338:        TGAWREG(dc, TGA_REG_GPXR_P, 0xffffffff);
        !           339:
        !           340:        /* clear the screen */
        !           341:        DPRINTF("tga_getdevconfig: clear screen\n");
        !           342:        for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
        !           343:                *(u_int32_t *)(dc->dc_videobase + i) = 0;
        !           344:
        !           345:        DPRINTF("tga_getdevconfig: raster ops\n");
        !           346:        /* Initialize rasops descriptor */
        !           347:        rip = &dc->dc_rinfo;
        !           348:        rip->ri_flg = RI_CENTER;
        !           349:        rip->ri_depth = tgac->tgac_phys_depth;
        !           350:        rip->ri_bits = (void *)dc->dc_videobase;
        !           351:        rip->ri_width = dc->dc_wid;
        !           352:        rip->ri_height = dc->dc_ht;
        !           353:        rip->ri_stride = dc->dc_rowbytes;
        !           354:        rip->ri_hw = dc;
        !           355:
        !           356:        if (tgac->tgac_phys_depth == 32) {
        !           357:                rip->ri_rnum = 8;
        !           358:                rip->ri_gnum = 8;
        !           359:                rip->ri_bnum = 8;
        !           360:                rip->ri_rpos = 16;
        !           361:                rip->ri_gpos = 8;
        !           362:                rip->ri_bpos = 0;
        !           363:        }
        !           364:
        !           365:        DPRINTF("tga_getdevconfig: wsfont_init\n");
        !           366:        wsfont_init();
        !           367:        if (rip->ri_width > 80*12)
        !           368:                /* High res screen, choose a big font */
        !           369:                cookie = wsfont_find(NULL, 12, 0, 0);
        !           370:        else
        !           371:                /*  lower res, choose a 8 pixel wide font */
        !           372:                cookie = wsfont_find(NULL, 8, 0, 0);
        !           373:        if (cookie <= 0)
        !           374:                cookie = wsfont_find(NULL, 0, 0, 0);
        !           375:        if (cookie <= 0) {
        !           376:                printf("tga: no appropriate fonts.\n");
        !           377:                return;
        !           378:        }
        !           379:
        !           380:        /* the accelerated tga_putchar() needs LSbit left */
        !           381:        if (wsfont_lock(cookie, &rip->ri_font,
        !           382:            WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
        !           383:                printf("tga: couldn't lock font\n");
        !           384:                return;
        !           385:        }
        !           386:        rip->ri_wsfcookie = cookie;
        !           387:        /* fill screen size */
        !           388:        rasops_init(rip, rip->ri_height / rip->ri_font->fontheight,
        !           389:            rip->ri_width / rip->ri_font->fontwidth);
        !           390:
        !           391:        /* add our accelerated functions */
        !           392:        /* XXX shouldn't have to do this; rasops should leave non-NULL
        !           393:         * XXX entries alone.
        !           394:         */
        !           395:        rip->ri_ops.copyrows = tga_copyrows;
        !           396:        rip->ri_ops.eraserows = tga_eraserows;
        !           397:        rip->ri_ops.erasecols = tga_erasecols;
        !           398:        rip->ri_ops.copycols = tga_copycols;
        !           399:        rip->ri_ops.putchar = tga_putchar;
        !           400:
        !           401:        tga_stdscreen.nrows = rip->ri_rows;
        !           402:        tga_stdscreen.ncols = rip->ri_cols;
        !           403:        tga_stdscreen.textops = &rip->ri_ops;
        !           404:        tga_stdscreen.capabilities = rip->ri_caps;
        !           405:
        !           406:        dc->dc_intrenabled = 0;
        !           407: }
        !           408:
        !           409: void
        !           410: tgaattach(parent, self, aux)
        !           411:        struct device *parent, *self;
        !           412:        void *aux;
        !           413: {
        !           414:        struct pci_attach_args *pa = aux;
        !           415:        struct tga_softc *sc = (struct tga_softc *)self;
        !           416:        struct wsemuldisplaydev_attach_args aa;
        !           417:        pci_intr_handle_t intrh;
        !           418:        const char *intrstr;
        !           419:        u_int8_t rev;
        !           420:        int console;
        !           421:
        !           422: #if defined(__alpha__) || defined(arc)
        !           423:        console = (pa->pa_tag == tga_console_dc.dc_pcitag);
        !           424: #else
        !           425:        console = 0;
        !           426: #endif
        !           427:        if (console) {
        !           428:                sc->sc_dc = &tga_console_dc;
        !           429:                sc->nscreens = 1;
        !           430:        } else {
        !           431:                sc->sc_dc = (struct tga_devconfig *)
        !           432:                    malloc(sizeof(struct tga_devconfig), M_DEVBUF, M_NOWAIT);
        !           433:                if (sc->sc_dc == NULL)
        !           434:                        return;
        !           435:                bzero(sc->sc_dc, sizeof(struct tga_devconfig));
        !           436:                tga_getdevconfig(pa->pa_memt, pa->pa_pc, pa->pa_tag,
        !           437:                    sc->sc_dc);
        !           438:        }
        !           439:        if (sc->sc_dc->dc_vaddr == NULL) {
        !           440:                printf(": couldn't map memory space; punt!\n");
        !           441:                return;
        !           442:        }
        !           443:
        !           444:        /* XXX say what's going on. */
        !           445:        intrstr = NULL;
        !           446:        if (pci_intr_map(pa, &intrh)) {
        !           447:                printf(": couldn't map interrupt");
        !           448:                return;
        !           449:        }
        !           450:        intrstr = pci_intr_string(pa->pa_pc, intrh);
        !           451:        sc->sc_intr = pci_intr_establish(pa->pa_pc, intrh, IPL_TTY, tga_intr,
        !           452:            sc->sc_dc, sc->sc_dev.dv_xname);
        !           453:        if (sc->sc_intr == NULL) {
        !           454:                printf(": couldn't establish interrupt");
        !           455:                if (intrstr != NULL)
        !           456:                        printf("at %s", intrstr);
        !           457:                printf("\n");
        !           458:                return;
        !           459:        }
        !           460:
        !           461:        rev = PCI_REVISION(pa->pa_class);
        !           462:        switch (rev) {
        !           463:        case 0x1:
        !           464:        case 0x2:
        !           465:        case 0x3:
        !           466:                printf(": DC21030 step %c", 'A' + rev - 1);
        !           467:                break;
        !           468:        case 0x20:
        !           469:                printf(": TGA2 abstract software model");
        !           470:                break;
        !           471:        case 0x21:
        !           472:        case 0x22:
        !           473:                printf(": TGA2 pass %d", rev - 0x20);
        !           474:                break;
        !           475:
        !           476:        default:
        !           477:                printf("unknown stepping (0x%x)", rev);
        !           478:                break;
        !           479:        }
        !           480:        printf(", ");
        !           481:
        !           482:        /*
        !           483:         * Get RAMDAC function vectors and call the RAMDAC functions
        !           484:         * to allocate its private storage and pass that back to us.
        !           485:         */
        !           486:
        !           487:        DPRINTF("tgaattach: Get RAMDAC functions\n");
        !           488:        sc->sc_dc->dc_ramdac_funcs = sc->sc_dc->dc_tgaconf->ramdac_funcs();
        !           489:        if (!sc->sc_dc->dc_tga2) {
        !           490:            DPRINTF("tgaattach: !sc->sc_dc->dc_tga2\n");
        !           491:            DPRINTF("tgaattach: sc->sc_dc->dc_tgaconf->ramdac_funcs %s "
        !           492:                    "bt485_funcs\n",
        !           493:                    (sc->sc_dc->dc_tgaconf->ramdac_funcs == bt485_funcs)
        !           494:                    ? "==" : "!=");
        !           495:            if (sc->sc_dc->dc_tgaconf->ramdac_funcs == bt485_funcs)
        !           496:                  sc->sc_dc->dc_ramdac_cookie =
        !           497:                        sc->sc_dc->dc_ramdac_funcs->ramdac_register(sc->sc_dc,
        !           498:                    tga_sched_update, tga_ramdac_wr, tga_ramdac_rd);
        !           499:                else
        !           500:                  sc->sc_dc->dc_ramdac_cookie =
        !           501:                        sc->sc_dc->dc_ramdac_funcs->ramdac_register(sc->sc_dc,
        !           502:                    tga_sched_update, tga_bt463_wr, tga_bt463_rd);
        !           503:        } else {
        !           504:                DPRINTF("tgaattach: sc->sc_dc->dc_tga2\n");
        !           505:                sc->sc_dc->dc_ramdac_cookie =
        !           506:                        sc->sc_dc->dc_ramdac_funcs->ramdac_register(sc->sc_dc,
        !           507:                        tga_sched_update, tga2_ramdac_wr, tga2_ramdac_rd);
        !           508:
        !           509:                /* XXX this is a bit of a hack, setting the dotclock here */
        !           510:                if (sc->sc_dc->dc_tgaconf->ramdac_funcs != bt485_funcs)
        !           511:                        (*sc->sc_dc->dc_ramdac_funcs->ramdac_set_dotclock)
        !           512:                                (sc->sc_dc->dc_ramdac_cookie,
        !           513:                                 tga_getdotclock(sc->sc_dc));
        !           514:        }
        !           515:        DPRINTF("tgaattach: sc->sc_dc->dc_ramdac_cookie = 0x%016llx\n",
        !           516:                sc->sc_dc->dc_ramdac_cookie);
        !           517:        /*
        !           518:         * Initialize the RAMDAC.  Initialization includes disabling
        !           519:         * cursor, setting a sane colormap, etc.
        !           520:         */
        !           521:        DPRINTF("tgaattach: Initializing RAMDAC.\n");
        !           522:        (*sc->sc_dc->dc_ramdac_funcs->ramdac_init)(sc->sc_dc->dc_ramdac_cookie);
        !           523:        TGAWREG(sc->sc_dc, TGA_REG_SISR, 0x00000001); /* XXX */
        !           524:
        !           525:        if (sc->sc_dc->dc_tgaconf == NULL) {
        !           526:                printf("unknown board configuration\n");
        !           527:                return;
        !           528:        }
        !           529:        printf("board type %s\n", sc->sc_dc->dc_tgaconf->tgac_name);
        !           530:        printf("%s: %d x %d, %dbpp, %s RAMDAC\n", sc->sc_dev.dv_xname,
        !           531:            sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
        !           532:            sc->sc_dc->dc_tgaconf->tgac_phys_depth,
        !           533:            sc->sc_dc->dc_ramdac_funcs->ramdac_name);
        !           534:
        !           535:        if (intrstr != NULL)
        !           536:                printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname,
        !           537:                    intrstr);
        !           538:
        !           539:        aa.console = console;
        !           540:        aa.scrdata = &tga_screenlist;
        !           541:        aa.accessops = &tga_accessops;
        !           542:        aa.accesscookie = sc;
        !           543:        aa.defaultscreens = 0;
        !           544:
        !           545:        config_found(self, &aa, wsemuldisplaydevprint);
        !           546:
        !           547: #ifdef __NetBSD__
        !           548:        config_interrupts(self, tga_config_interrupts);
        !           549: #else
        !           550:        tga_config_interrupts(self);
        !           551: #endif
        !           552: }
        !           553:
        !           554: void
        !           555: tga_config_interrupts (d)
        !           556:        struct device *d;
        !           557: {
        !           558:        struct tga_softc *sc = (struct tga_softc *)d;
        !           559:        sc->sc_dc->dc_intrenabled = 1;
        !           560: }
        !           561:
        !           562:
        !           563: int
        !           564: tga_ioctl(v, cmd, data, flag, p)
        !           565:        void *v;
        !           566:        u_long cmd;
        !           567:        caddr_t data;
        !           568:        int flag;
        !           569:        struct proc *p;
        !           570: {
        !           571:        struct tga_softc *sc = v;
        !           572:        struct tga_devconfig *dc = sc->sc_dc;
        !           573:        struct ramdac_funcs *dcrf = dc->dc_ramdac_funcs;
        !           574:        struct ramdac_cookie *dcrc = dc->dc_ramdac_cookie;
        !           575:
        !           576:        switch (cmd) {
        !           577:        case WSDISPLAYIO_GTYPE:
        !           578:                *(u_int *)data = WSDISPLAY_TYPE_TGA;
        !           579:                break;
        !           580:
        !           581:        case WSDISPLAYIO_SMODE:
        !           582:                sc->sc_mode = *(u_int *)data;
        !           583:                switch (sc->sc_mode) {
        !           584:                case WSDISPLAYIO_MODE_DUMBFB:
        !           585:                        /* in dump fb mode start the framebuffer at 0 */
        !           586:                        TGAWREG(dc, TGA_REG_VVBR, 0);
        !           587:                        break;
        !           588:                default:
        !           589:                        /* XXX it this useful, except for not breaking Xtga? */
        !           590:                        TGAWREG(dc, TGA_REG_VVBR, 1);
        !           591:                        break;
        !           592:                }
        !           593:                break;
        !           594:
        !           595:        case WSDISPLAYIO_GINFO:
        !           596: #define        wsd_fbip ((struct wsdisplay_fbinfo *)data)
        !           597:                wsd_fbip->height = sc->sc_dc->dc_ht;
        !           598:                wsd_fbip->width = sc->sc_dc->dc_wid;
        !           599:                wsd_fbip->depth = sc->sc_dc->dc_tgaconf->tgac_phys_depth;
        !           600:                wsd_fbip->cmsize = 1024;                /* XXX ??? */
        !           601: #undef wsd_fbip
        !           602:                break;
        !           603:
        !           604:        case WSDISPLAYIO_LINEBYTES:
        !           605:                *(u_int *)data = sc->sc_dc->dc_rowbytes;
        !           606:                break;
        !           607:
        !           608:        case WSDISPLAYIO_GETCMAP:
        !           609:                return (*dcrf->ramdac_get_cmap)(dcrc,
        !           610:                    (struct wsdisplay_cmap *)data);
        !           611:        case WSDISPLAYIO_PUTCMAP:
        !           612:                return (*dcrf->ramdac_set_cmap)(dcrc,
        !           613:                    (struct wsdisplay_cmap *)data);
        !           614:
        !           615:        case WSDISPLAYIO_SVIDEO:
        !           616:        case WSDISPLAYIO_GVIDEO:
        !           617:                break;
        !           618:
        !           619:        case WSDISPLAYIO_GCURPOS:
        !           620:                return (*dcrf->ramdac_get_curpos)(dcrc,
        !           621:                    (struct wsdisplay_curpos *)data);
        !           622:
        !           623:        case WSDISPLAYIO_SCURPOS:
        !           624:                return (*dcrf->ramdac_set_curpos)(dcrc,
        !           625:                    (struct wsdisplay_curpos *)data);
        !           626:
        !           627:        case WSDISPLAYIO_GCURMAX:
        !           628:                return (*dcrf->ramdac_get_curmax)(dcrc,
        !           629:                    (struct wsdisplay_curpos *)data);
        !           630:
        !           631:        case WSDISPLAYIO_GCURSOR:
        !           632:                return (*dcrf->ramdac_get_cursor)(dcrc,
        !           633:                    (struct wsdisplay_cursor *)data);
        !           634:
        !           635:        case WSDISPLAYIO_SCURSOR:
        !           636:                return (*dcrf->ramdac_set_cursor)(dcrc,
        !           637:                    (struct wsdisplay_cursor *)data);
        !           638:
        !           639:        default:
        !           640:                return (-1);
        !           641:        }
        !           642:
        !           643:        return (0);
        !           644: }
        !           645:
        !           646: int
        !           647: tga_sched_update(v, f)
        !           648:        void    *v;
        !           649:        void    (*f)(void *);
        !           650: {
        !           651:        struct tga_devconfig *dc = v;
        !           652:
        !           653:        if (dc->dc_intrenabled) {
        !           654:                /* Arrange for f to be called at the next end-of-frame interrupt */
        !           655:                dc->dc_ramdac_intr = f;
        !           656:                TGAWREG(dc, TGA_REG_SISR, 0x00010000);
        !           657:        } else {
        !           658:                /* Spin until the end-of-frame, then call f */
        !           659:                TGAWREG(dc, TGA_REG_SISR, 0x00010001);
        !           660:                TGAREGWB(dc, TGA_REG_SISR, 1);
        !           661:                while ((TGARREG(dc, TGA_REG_SISR) & 0x00000001) == 0)
        !           662:                        ;
        !           663:                f(dc->dc_ramdac_cookie);
        !           664:                TGAWREG(dc, TGA_REG_SISR, 0x00000001);
        !           665:                TGAREGWB(dc, TGA_REG_SISR, 1);
        !           666:        }
        !           667:
        !           668:        return 0;
        !           669: }
        !           670:
        !           671: int
        !           672: tga_intr(v)
        !           673:        void *v;
        !           674: {
        !           675:        struct tga_devconfig *dc = v;
        !           676:        struct ramdac_cookie *dcrc= dc->dc_ramdac_cookie;
        !           677:
        !           678:        u_int32_t reg;
        !           679:
        !           680:        reg = TGARREG(dc, TGA_REG_SISR);
        !           681:        if (( reg & 0x00010001) != 0x00010001) {
        !           682:                /* Odd. We never set any of the other interrupt enables. */
        !           683:                if ((reg & 0x1f) != 0) {
        !           684:                        /* Clear the mysterious pending interrupts. */
        !           685:                        TGAWREG(dc, TGA_REG_SISR, (reg & 0x1f));
        !           686:                        TGAREGWB(dc, TGA_REG_SISR, 1);
        !           687:                        /* This was our interrupt, even if we're puzzled as to why
        !           688:                         * we got it.  Don't make the interrupt handler think it
        !           689:                         * was a stray.
        !           690:                         */
        !           691:                        return -1;
        !           692:                } else {
        !           693:                        return 0;
        !           694:                }
        !           695:        }
        !           696:        /* if we have something to do, do it */
        !           697:        if (dc->dc_ramdac_intr) {
        !           698:                dc->dc_ramdac_intr(dcrc);
        !           699:                dc->dc_ramdac_intr = NULL;
        !           700:        }
        !           701:        TGAWREG(dc, TGA_REG_SISR, 0x00000001);
        !           702:        TGAREGWB(dc, TGA_REG_SISR, 1);
        !           703:        return (1);
        !           704: }
        !           705:
        !           706: paddr_t
        !           707: tga_mmap(v, offset, prot)
        !           708:        void *v;
        !           709:        off_t offset;
        !           710:        int prot;
        !           711: {
        !           712:        struct tga_softc *sc = v;
        !           713:        struct tga_devconfig *dc = sc->sc_dc;
        !           714:
        !           715:        if (offset >= dc->dc_tgaconf->tgac_cspace_size || offset < 0)
        !           716:                return -1;
        !           717:
        !           718:        if (sc->sc_mode == WSDISPLAYIO_MODE_DUMBFB) {
        !           719:                /*
        !           720:                 * The framebuffer starts at the upper half of tga mem
        !           721:                 */
        !           722:                offset += dc->dc_tgaconf->tgac_cspace_size / 2;
        !           723:        }
        !           724: #if defined(__alpha__) || defined(__mips__)
        !           725:        return atop(sc->sc_dc->dc_paddr + offset);
        !           726: #else
        !           727:        return (-1);
        !           728: #endif
        !           729: }
        !           730:
        !           731: int
        !           732: tga_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
        !           733:        void *v;
        !           734:        const struct wsscreen_descr *type;
        !           735:        void **cookiep;
        !           736:        int *curxp, *curyp;
        !           737:        long *attrp;
        !           738: {
        !           739:        struct tga_softc *sc = v;
        !           740:        long defattr;
        !           741:
        !           742:        if (sc->nscreens > 0)
        !           743:                return (ENOMEM);
        !           744:
        !           745:        *cookiep = &sc->sc_dc->dc_rinfo; /* one and only for now */
        !           746:        *curxp = 0;
        !           747:        *curyp = 0;
        !           748:        sc->sc_dc->dc_rinfo.ri_ops.alloc_attr(&sc->sc_dc->dc_rinfo,
        !           749:                0, 0, 0, &defattr);
        !           750:        *attrp = defattr;
        !           751:        sc->nscreens++;
        !           752:        return (0);
        !           753: }
        !           754:
        !           755: void
        !           756: tga_free_screen(v, cookie)
        !           757:        void *v;
        !           758:        void *cookie;
        !           759: {
        !           760:        struct tga_softc *sc = v;
        !           761:
        !           762:        if (sc->sc_dc == &tga_console_dc)
        !           763:                panic("tga_free_screen: console");
        !           764:
        !           765:        sc->nscreens--;
        !           766: }
        !           767:
        !           768: int
        !           769: tga_show_screen(v, cookie, waitok, cb, cbarg)
        !           770:        void *v;
        !           771:        void *cookie;
        !           772:        int waitok;
        !           773:        void (*cb)(void *, int, int);
        !           774:        void *cbarg;
        !           775: {
        !           776:
        !           777:        return (0);
        !           778: }
        !           779:
        !           780: int
        !           781: tga_cnattach(iot, memt, pc, bus, device, function)
        !           782:        bus_space_tag_t iot, memt;
        !           783:        pci_chipset_tag_t pc;
        !           784:        int bus, device, function;
        !           785: {
        !           786:        struct tga_devconfig *dcp = &tga_console_dc;
        !           787:        long defattr;
        !           788:
        !           789:        tga_getdevconfig(memt, pc,
        !           790:            pci_make_tag(pc, bus, device, function), dcp);
        !           791:
        !           792:        /* sanity checks */
        !           793:        if (dcp->dc_vaddr == NULL)
        !           794:                panic("tga_console(%d, %d): couldn't map memory space",
        !           795:                    device, function);
        !           796:        if (dcp->dc_tgaconf == NULL)
        !           797:                panic("tga_console(%d, %d): unknown board configuration",
        !           798:                    device, function);
        !           799:
        !           800:        /*
        !           801:         * Initialize the RAMDAC but DO NOT allocate any private storage.
        !           802:         * Initialization includes disabling cursor, setting a sane
        !           803:         * colormap, etc.  It will be reinitialized in tgaattach().
        !           804:         */
        !           805:        if (dcp->dc_tga2) {
        !           806:                if (dcp->dc_tgaconf->ramdac_funcs == bt485_funcs)
        !           807:                        bt485_cninit(dcp, tga_sched_update, tga2_ramdac_wr,
        !           808:                                     tga2_ramdac_rd);
        !           809:                else
        !           810:                        ibm561_cninit(dcp, tga_sched_update, tga2_ramdac_wr,
        !           811:                                      tga2_ramdac_rd, tga_getdotclock(dcp));
        !           812:        } else {
        !           813:                if (dcp->dc_tgaconf->ramdac_funcs == bt485_funcs)
        !           814:                        bt485_cninit(dcp, tga_sched_update, tga_ramdac_wr,
        !           815:                                tga_ramdac_rd);
        !           816:                else {
        !           817:                        bt463_cninit(dcp, tga_sched_update, tga_bt463_wr,
        !           818:                                tga_bt463_rd);
        !           819:                }
        !           820:        }
        !           821:        dcp->dc_rinfo.ri_ops.alloc_attr(&dcp->dc_rinfo, 0, 0, 0, &defattr);
        !           822:        wsdisplay_cnattach(&tga_stdscreen, &dcp->dc_rinfo, 0, 0, defattr);
        !           823:
        !           824:        return(0);
        !           825: }
        !           826:
        !           827: /*
        !           828:  * Functions to blank and unblank the display.
        !           829:  */
        !           830: void
        !           831: tga_burner(v, on, flags)
        !           832:        void *v;
        !           833:        u_int on, flags;
        !           834: {
        !           835:        struct tga_softc *sc = v;
        !           836:
        !           837:        if (on) {
        !           838:                tga_unblank(sc->sc_dc);
        !           839:        } else {
        !           840:                tga_blank(sc->sc_dc);
        !           841:        }
        !           842: }
        !           843:
        !           844: void
        !           845: tga_blank(dc)
        !           846:        struct tga_devconfig *dc;
        !           847: {
        !           848:
        !           849:        if (!dc->dc_blanked) {
        !           850:                dc->dc_blanked = 1;
        !           851:                /* XXX */
        !           852:                TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) | VVR_BLANK);
        !           853:        }
        !           854: }
        !           855:
        !           856: void
        !           857: tga_unblank(dc)
        !           858:        struct tga_devconfig *dc;
        !           859: {
        !           860:
        !           861:        if (dc->dc_blanked) {
        !           862:                dc->dc_blanked = 0;
        !           863:                /* XXX */
        !           864:                TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) & ~VVR_BLANK);
        !           865:        }
        !           866: }
        !           867:
        !           868: /*
        !           869:  * Functions to manipulate the built-in cursor handing hardware.
        !           870:  */
        !           871: int
        !           872: tga_builtin_set_cursor(dc, cursorp)
        !           873:        struct tga_devconfig *dc;
        !           874:        struct wsdisplay_cursor *cursorp;
        !           875: {
        !           876:        struct ramdac_funcs *dcrf = dc->dc_ramdac_funcs;
        !           877:        struct ramdac_cookie *dcrc = dc->dc_ramdac_cookie;
        !           878:        u_int count, v;
        !           879:        int error;
        !           880:
        !           881:        v = cursorp->which;
        !           882:        if (v & WSDISPLAY_CURSOR_DOCMAP) {
        !           883:                error = dcrf->ramdac_check_curcmap(dcrc, cursorp);
        !           884:                if (error)
        !           885:                        return (error);
        !           886:        }
        !           887:        if (v & WSDISPLAY_CURSOR_DOSHAPE) {
        !           888:                if ((u_int)cursorp->size.x != 64 ||
        !           889:                    (u_int)cursorp->size.y > 64)
        !           890:                        return (EINVAL);
        !           891:        }
        !           892:        if (v & WSDISPLAY_CURSOR_DOHOT)         /* not supported */
        !           893:                return EINVAL;
        !           894:
        !           895:        /* parameters are OK; do it */
        !           896:        if (v & WSDISPLAY_CURSOR_DOCUR) {
        !           897:                if (cursorp->enable)
        !           898:                        /* XXX */
        !           899:                        TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) | 0x04);
        !           900:                else
        !           901:                        /* XXX */
        !           902:                        TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) & ~0x04);
        !           903:        }
        !           904:        if (v & WSDISPLAY_CURSOR_DOPOS) {
        !           905:                TGAWREG(dc, TGA_REG_CXYR,
        !           906:                    ((cursorp->pos.y & 0xfff) << 12) | (cursorp->pos.x & 0xfff));
        !           907:        }
        !           908:        if (v & WSDISPLAY_CURSOR_DOCMAP) {
        !           909:                /* can't fail. */
        !           910:                dcrf->ramdac_set_curcmap(dcrc, cursorp);
        !           911:        }
        !           912:        if (v & WSDISPLAY_CURSOR_DOSHAPE) {
        !           913:                /* The cursor is 2 bits deep, and there is no mask */
        !           914:                count = (cursorp->size.y * 64 * 2) / NBBY;
        !           915:                TGAWREG(dc, TGA_REG_CCBR,
        !           916:                    (TGARREG(dc, TGA_REG_CCBR) & ~0xfc00) | (cursorp->size.y << 10));
        !           917:                if ((error = copyin(cursorp->image,(char *)(dc->dc_vaddr +
        !           918:                    (TGARREG(dc, TGA_REG_CCBR) & 0x3ff)), count)) != 0)
        !           919:                        return (error);
        !           920:        }
        !           921:        return (0);
        !           922: }
        !           923:
        !           924: int
        !           925: tga_builtin_get_cursor(dc, cursorp)
        !           926:        struct tga_devconfig *dc;
        !           927:        struct wsdisplay_cursor *cursorp;
        !           928: {
        !           929:        struct ramdac_funcs *dcrf = dc->dc_ramdac_funcs;
        !           930:        struct ramdac_cookie *dcrc = dc->dc_ramdac_cookie;
        !           931:        int error;
        !           932:        u_int count;
        !           933:
        !           934:        cursorp->which = WSDISPLAY_CURSOR_DOALL &
        !           935:            ~(WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOCMAP);
        !           936:        cursorp->enable = (TGARREG(dc, TGA_REG_VVVR) & 0x04) != 0;
        !           937:        cursorp->pos.x = TGARREG(dc, TGA_REG_CXYR) & 0xfff;
        !           938:        cursorp->pos.y = (TGARREG(dc, TGA_REG_CXYR) >> 12) & 0xfff;
        !           939:        cursorp->size.x = 64;
        !           940:        cursorp->size.y = (TGARREG(dc, TGA_REG_CCBR) >> 10) & 0x3f;
        !           941:
        !           942:        if (cursorp->image != NULL) {
        !           943:                count = (cursorp->size.y * 64 * 2) / NBBY;
        !           944:                error = copyout((char *)(dc->dc_vaddr +
        !           945:                      (TGARREG(dc, TGA_REG_CCBR) & 0x3ff)),
        !           946:                    cursorp->image, count);
        !           947:                if (error)
        !           948:                        return (error);
        !           949:                /* No mask */
        !           950:        }
        !           951:        error = dcrf->ramdac_get_curcmap(dcrc, cursorp);
        !           952:        return (error);
        !           953: }
        !           954:
        !           955: int
        !           956: tga_builtin_set_curpos(dc, curposp)
        !           957:        struct tga_devconfig *dc;
        !           958:        struct wsdisplay_curpos *curposp;
        !           959: {
        !           960:
        !           961:        TGAWREG(dc, TGA_REG_CXYR,
        !           962:            ((curposp->y & 0xfff) << 12) | (curposp->x & 0xfff));
        !           963:        return (0);
        !           964: }
        !           965:
        !           966: int
        !           967: tga_builtin_get_curpos(dc, curposp)
        !           968:        struct tga_devconfig *dc;
        !           969:        struct wsdisplay_curpos *curposp;
        !           970: {
        !           971:
        !           972:        curposp->x = TGARREG(dc, TGA_REG_CXYR) & 0xfff;
        !           973:        curposp->y = (TGARREG(dc, TGA_REG_CXYR) >> 12) & 0xfff;
        !           974:        return (0);
        !           975: }
        !           976:
        !           977: int
        !           978: tga_builtin_get_curmax(dc, curposp)
        !           979:        struct tga_devconfig *dc;
        !           980:        struct wsdisplay_curpos *curposp;
        !           981: {
        !           982:
        !           983:        curposp->x = curposp->y = 64;
        !           984:        return (0);
        !           985: }
        !           986:
        !           987: /*
        !           988:  * Copy columns (characters) in a row (line).
        !           989:  */
        !           990: void
        !           991: tga_copycols(id, row, srccol, dstcol, ncols)
        !           992:        void *id;
        !           993:        int row, srccol, dstcol, ncols;
        !           994: {
        !           995:        struct rasops_info *ri = id;
        !           996:        int y, srcx, dstx, nx;
        !           997:
        !           998:        y = ri->ri_font->fontheight * row;
        !           999:        srcx = ri->ri_font->fontwidth * srccol;
        !          1000:        dstx = ri->ri_font->fontwidth * dstcol;
        !          1001:        nx = ri->ri_font->fontwidth * ncols;
        !          1002:
        !          1003:        tga_rop(ri, dstx, y, nx, ri->ri_font->fontheight, ri, srcx, y);
        !          1004: }
        !          1005:
        !          1006: /*
        !          1007:  * Copy rows (lines).
        !          1008:  */
        !          1009: void
        !          1010: tga_copyrows(id, srcrow, dstrow, nrows)
        !          1011:        void *id;
        !          1012:        int srcrow, dstrow, nrows;
        !          1013: {
        !          1014:        struct rasops_info *ri = id;
        !          1015:        int srcy, dsty, ny;
        !          1016:
        !          1017:        srcy = ri->ri_font->fontheight * srcrow;
        !          1018:        dsty = ri->ri_font->fontheight * dstrow;
        !          1019:        ny = ri->ri_font->fontheight * nrows;
        !          1020:
        !          1021:        tga_rop(ri, 0, dsty, ri->ri_emuwidth, ny, ri, 0, srcy);
        !          1022: }
        !          1023:
        !          1024: /*
        !          1025:  *  Generic TGA raster op.
        !          1026:  *   This covers all possible raster ops, and
        !          1027:  *   clips the sizes and all of that.
        !          1028:  */
        !          1029: int
        !          1030: tga_rop(dst, dx, dy, w, h, src, sx, sy)
        !          1031:        struct rasops_info *dst;
        !          1032:        int dx, dy, w, h;
        !          1033:        struct rasops_info *src;
        !          1034:        int sx, sy;
        !          1035: {
        !          1036:        if (dst == NULL || src == NULL)
        !          1037:                return -1;
        !          1038:
        !          1039:        /* Clip against src */
        !          1040:        if (sx < 0) {
        !          1041:                w += sx;
        !          1042:                sx = 0;
        !          1043:        }
        !          1044:        if (sy < 0) {
        !          1045:                h += sy;
        !          1046:                sy = 0;
        !          1047:        }
        !          1048:        if (sx + w > src->ri_emuwidth)
        !          1049:                w = src->ri_emuwidth - sx;
        !          1050:        if (sy + h > src->ri_emuheight)
        !          1051:                h = src->ri_emuheight - sy;
        !          1052:
        !          1053:        /* Clip against dst.  We modify src regardless of using it,
        !          1054:         * since it really doesn't matter.
        !          1055:         */
        !          1056:        if (dx < 0) {
        !          1057:                w += dx;
        !          1058:                sx -= dx;
        !          1059:                dx = 0;
        !          1060:        }
        !          1061:        if (dy < 0) {
        !          1062:                h += dy;
        !          1063:                sy -= dy;
        !          1064:                dy = 0;
        !          1065:        }
        !          1066:        if (dx + w > dst->ri_emuwidth)
        !          1067:                w = dst->ri_emuwidth - dx;
        !          1068:        if (dy + h > dst->ri_emuheight)
        !          1069:                h = dst->ri_emuheight - dy;
        !          1070:        if (w <= 0 || h <= 0)
        !          1071:                return 0;       /* Vacuously true; */
        !          1072:
        !          1073:        return tga_rop_vtov(dst, dx, dy, w, h, src, sx, sy);
        !          1074: }
        !          1075:
        !          1076:
        !          1077:
        !          1078: /*
        !          1079:  * Video to Video raster ops.
        !          1080:  * This function deals with all raster ops that have a src and dst
        !          1081:  * that are on the card.
        !          1082:  */
        !          1083: int
        !          1084: tga_rop_vtov(dst, dx, dy, w, h, src, sx, sy)
        !          1085:        struct rasops_info *dst;
        !          1086:        int dx, dy, w, h;
        !          1087:        struct rasops_info *src;
        !          1088:        int sx, sy;
        !          1089: {
        !          1090:        struct tga_devconfig *dc = (struct tga_devconfig *)dst->ri_hw;
        !          1091:        int srcb, dstb, tga_srcb, tga_dstb;
        !          1092:        int x, y, wb;
        !          1093:        int xstart, xend, xdir;
        !          1094:        int ystart, yend, ydir, yinc;
        !          1095:        int xleft, lastx, lastleft;
        !          1096:        int offset = 1 * dc->dc_tgaconf->tgac_vvbr_units;
        !          1097:
        !          1098:        /*
        !          1099:         * I don't yet want to deal with unaligned guys, really.  And we don't
        !          1100:         * deal with copies from one card to another.
        !          1101:         */
        !          1102:        if (dx % 8 != 0 || sx % 8 != 0 || src != dst) {
        !          1103:                /* XXX Punt! */
        !          1104:                /* XXX should never happen, since it's only being used to
        !          1105:                 * XXX copy 8-pixel-wide characters.
        !          1106:                 */
        !          1107:                return -1;
        !          1108:        }
        !          1109:
        !          1110:         wb = w * (dst->ri_depth / 8);
        !          1111:        if (sy >= dy) {
        !          1112:                ystart = 0;
        !          1113:                yend = h;
        !          1114:                ydir = 1;
        !          1115:        } else {
        !          1116:                ystart = h;
        !          1117:                yend = 0;
        !          1118:                ydir = -1;
        !          1119:        }
        !          1120:        if (sx >= dx) {      /* moving to the left */
        !          1121:                xstart = 0;
        !          1122:                xend = w * (dst->ri_depth / 8) - 4;
        !          1123:                xdir = 1;
        !          1124:        } else {             /* moving to the right */
        !          1125:                xstart = wb - ( wb >= 4*64 ? 4*64 : wb >= 64 ? 64 : 4 );
        !          1126:                xend = 0;
        !          1127:                xdir = -1;
        !          1128:        }
        !          1129: #define XINC4   4
        !          1130: #define XINC64  64
        !          1131: #define XINC256 (64*4)
        !          1132:        yinc = ydir * dst->ri_stride;
        !          1133:        ystart *= dst->ri_stride;
        !          1134:        yend *= dst->ri_stride;
        !          1135:
        !          1136:        srcb = sy * src->ri_stride + sx * (src->ri_depth/8);
        !          1137:        dstb = dy * dst->ri_stride + dx * (dst->ri_depth/8);
        !          1138:        tga_srcb = offset + (sy + src->ri_yorigin) * src->ri_stride +
        !          1139:                (sx + src->ri_xorigin) * (src->ri_depth/8);
        !          1140:        tga_dstb = offset + (dy + dst->ri_yorigin) * dst->ri_stride +
        !          1141:                (dx + dst->ri_xorigin) * (dst->ri_depth/8);
        !          1142:
        !          1143:        TGAWALREG(dc, TGA_REG_GMOR, 3, 0x0007); /* Copy mode */
        !          1144:        TGAWALREG(dc, TGA_REG_GOPR, 3, 0x0003); /* SRC */
        !          1145:
        !          1146:        /*
        !          1147:         * we have 3 sizes of pixels to move in X direction:
        !          1148:         * 4 * 64   (unrolled TGA ops)
        !          1149:         *     64   (single TGA op)
        !          1150:         *      4   (CPU, using long word)
        !          1151:         */
        !          1152:
        !          1153:        if (xdir == 1) {   /* move to the left */
        !          1154:
        !          1155:                for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
        !          1156:
        !          1157:                        /* 4*64 byte chunks */
        !          1158:                        for (xleft = wb, x = xstart;
        !          1159:                             x <= xend && xleft >= 4*64;
        !          1160:                             x += XINC256, xleft -= XINC256) {
        !          1161:
        !          1162:                                /* XXX XXX Eight writes to different addresses should fill
        !          1163:                                 * XXX XXX up the write buffers on 21064 and 21164 chips,
        !          1164:                                 * XXX XXX but later CPUs might have larger write buffers which
        !          1165:                                 * XXX XXX require further unrolling of this loop, or the
        !          1166:                                 * XXX XXX insertion of memory barriers.
        !          1167:                                 */
        !          1168:                                TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 0 * 64);
        !          1169:                                TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 0 * 64);
        !          1170:                                TGAWALREG(dc, TGA_REG_GCSR, 1, tga_srcb + y + x + 1 * 64);
        !          1171:                                TGAWALREG(dc, TGA_REG_GCDR, 1, tga_dstb + y + x + 1 * 64);
        !          1172:                                TGAWALREG(dc, TGA_REG_GCSR, 2, tga_srcb + y + x + 2 * 64);
        !          1173:                                TGAWALREG(dc, TGA_REG_GCDR, 2, tga_dstb + y + x + 2 * 64);
        !          1174:                                TGAWALREG(dc, TGA_REG_GCSR, 3, tga_srcb + y + x + 3 * 64);
        !          1175:                                TGAWALREG(dc, TGA_REG_GCDR, 3, tga_dstb + y + x + 3 * 64);
        !          1176:                        }
        !          1177:
        !          1178:                        /* 64 byte chunks */
        !          1179:                        for ( ; x <= xend && xleft >= 64;
        !          1180:                              x += XINC64, xleft -= XINC64) {
        !          1181:                                TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 0 * 64);
        !          1182:                                TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 0 * 64);
        !          1183:                        }
        !          1184:                        lastx = x; lastleft = xleft;  /* remember for CPU loop */
        !          1185:
        !          1186:                }
        !          1187:                TGAWALREG(dc, TGA_REG_GOPR, 0, 0x0003); /* op -> dst = src */
        !          1188:                TGAWALREG(dc, TGA_REG_GMOR, 0, 0x0000); /* Simple mode */
        !          1189:
        !          1190:                for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
        !          1191:                        /* 4 byte granularity */
        !          1192:                        for (x = lastx, xleft = lastleft;
        !          1193:                             x <= xend && xleft >= 4;
        !          1194:                             x += XINC4, xleft -= XINC4) {
        !          1195:                                *(uint32_t *)(dst->ri_bits + dstb + y + x) =
        !          1196:                                        *(uint32_t *)(dst->ri_bits + srcb + y + x);
        !          1197:                        }
        !          1198:                }
        !          1199:        }
        !          1200:        else {    /* above move to the left, below move to the right */
        !          1201:
        !          1202:                for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
        !          1203:
        !          1204:                        /* 4*64 byte chunks */
        !          1205:                        for (xleft = wb, x = xstart;
        !          1206:                             x >= xend && xleft >= 4*64;
        !          1207:                             x -= XINC256, xleft -= XINC256) {
        !          1208:
        !          1209:                                /* XXX XXX Eight writes to different addresses should fill
        !          1210:                                 * XXX XXX up the write buffers on 21064 and 21164 chips,
        !          1211:                                 * XXX XXX but later CPUs might have larger write buffers which
        !          1212:                                 * XXX XXX require further unrolling of this loop, or the
        !          1213:                                 * XXX XXX insertion of memory barriers.
        !          1214:                                 */
        !          1215:                                TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 3 * 64);
        !          1216:                                TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 3 * 64);
        !          1217:                                TGAWALREG(dc, TGA_REG_GCSR, 1, tga_srcb + y + x + 2 * 64);
        !          1218:                                TGAWALREG(dc, TGA_REG_GCDR, 1, tga_dstb + y + x + 2 * 64);
        !          1219:                                TGAWALREG(dc, TGA_REG_GCSR, 2, tga_srcb + y + x + 1 * 64);
        !          1220:                                TGAWALREG(dc, TGA_REG_GCDR, 2, tga_dstb + y + x + 1 * 64);
        !          1221:                                TGAWALREG(dc, TGA_REG_GCSR, 3, tga_srcb + y + x + 0 * 64);
        !          1222:                                TGAWALREG(dc, TGA_REG_GCDR, 3, tga_dstb + y + x + 0 * 64);
        !          1223:                        }
        !          1224:
        !          1225:                        if (xleft) x += XINC256 - XINC64;
        !          1226:
        !          1227:                        /* 64 byte chunks */
        !          1228:                        for ( ; x >= xend && xleft >= 64;
        !          1229:                              x -= XINC64, xleft -= XINC64) {
        !          1230:                                TGAWALREG(dc, TGA_REG_GCSR, 0, tga_srcb + y + x + 0 * 64);
        !          1231:                                TGAWALREG(dc, TGA_REG_GCDR, 0, tga_dstb + y + x + 0 * 64);
        !          1232:                        }
        !          1233:                        if (xleft) x += XINC64 - XINC4;
        !          1234:                        lastx = x; lastleft = xleft;  /* remember for CPU loop */
        !          1235:                }
        !          1236:                TGAWALREG(dc, TGA_REG_GOPR, 0, 0x0003); /* op -> dst = src */
        !          1237:                TGAWALREG(dc, TGA_REG_GMOR, 0, 0x0000); /* Simple mode */
        !          1238:
        !          1239:                for (y = ystart; (ydir * y) <= (ydir * yend); y += yinc) {
        !          1240:                        /* 4 byte granularity */
        !          1241:                        for (x = lastx, xleft = lastleft;
        !          1242:                             x >= xend && xleft >= 4;
        !          1243:                             x -= XINC4, xleft -= XINC4) {
        !          1244:                                *(uint32_t *)(dst->ri_bits + dstb + y + x) =
        !          1245:                                        *(uint32_t *)(dst->ri_bits + srcb + y + x);
        !          1246:                        }
        !          1247:                }
        !          1248:        }
        !          1249:        return 0;
        !          1250: }
        !          1251:
        !          1252:
        !          1253: void
        !          1254: tga_putchar(c, row, col, uc, attr)
        !          1255:        void *c;
        !          1256:        int row, col;
        !          1257:        u_int uc;
        !          1258:        long attr;
        !          1259: {
        !          1260:        struct rasops_info *ri = c;
        !          1261:        struct tga_devconfig *dc = ri->ri_hw;
        !          1262:        int fs, height, width;
        !          1263:        int fg, bg, ul;
        !          1264:        u_char *fr;
        !          1265:        int32_t *rp;
        !          1266:
        !          1267:        rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
        !          1268:
        !          1269:        height = ri->ri_font->fontheight;
        !          1270:        width = ri->ri_font->fontwidth;
        !          1271:
        !          1272:        uc -= ri->ri_font->firstchar;
        !          1273:        fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
        !          1274:        fs = ri->ri_font->stride;
        !          1275:
        !          1276:        /* Set foreground and background color. XXX memoize this somehow?
        !          1277:         * The rasops code has already expanded the color entry to 32 bits
        !          1278:         * for us, even for 8-bit displays, so we don't have to do anything.
        !          1279:         */
        !          1280:        ri->ri_ops.unpack_attr(c, attr, &fg, &bg, &ul);
        !          1281:        TGAWREG(dc, TGA_REG_GFGR, ri->ri_devcmap[fg]);
        !          1282:        TGAWREG(dc, TGA_REG_GBGR, ri->ri_devcmap[bg]);
        !          1283:
        !          1284:        /* Set raster operation to "copy"... */
        !          1285:        if (ri->ri_depth == 8)
        !          1286:                TGAWREG(dc, TGA_REG_GOPR, 0x3);
        !          1287:        else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
        !          1288:                TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
        !          1289:
        !          1290:        /* Set which pixels we're drawing (of a possible 32). */
        !          1291:        TGAWREG(dc, TGA_REG_GPXR_P, (1 << width) - 1);
        !          1292:
        !          1293:        /* Set drawing mode to opaque stipple. */
        !          1294:        TGAWREG(dc, TGA_REG_GMOR, 0x1);
        !          1295:
        !          1296:        /* Insert write barrier before actually sending data */
        !          1297:        /* XXX Abuses the fact that there is only one write barrier on Alphas */
        !          1298:        TGAREGWB(dc, TGA_REG_GMOR, 1);
        !          1299:
        !          1300:        while (height--) {
        !          1301:                /* The actual stipple write */
        !          1302:                *rp = fr[0] | (fr[1] << 8) | (fr[2] << 16) | (fr[3] << 24);
        !          1303:
        !          1304:                fr += fs;
        !          1305:                rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
        !          1306:        }
        !          1307:
        !          1308:        /* Do underline */
        !          1309:        if (ul) {
        !          1310:                rp = (int32_t *)((caddr_t)rp - (ri->ri_stride << 1));
        !          1311:                *rp = 0xffffffff;
        !          1312:        }
        !          1313:
        !          1314:        /* Set grapics mode back to normal. */
        !          1315:        TGAWREG(dc, TGA_REG_GMOR, 0);
        !          1316:        TGAWREG(dc, TGA_REG_GPXR_P, 0xffffffff);
        !          1317: }
        !          1318:
        !          1319: void
        !          1320: tga_eraserows(c, row, num, attr)
        !          1321:        void *c;
        !          1322:        int row, num;
        !          1323:        long attr;
        !          1324: {
        !          1325:        struct rasops_info *ri = c;
        !          1326:        struct tga_devconfig *dc = ri->ri_hw;
        !          1327:        int32_t color, lines, pixels;
        !          1328:        int fg, bg;
        !          1329:        int32_t *rp;
        !          1330:
        !          1331:        ri->ri_ops.unpack_attr(c, attr, &fg, &bg, NULL);
        !          1332:        color = ri->ri_devcmap[bg];
        !          1333:        rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale);
        !          1334:        lines = num * ri->ri_font->fontheight;
        !          1335:        pixels = ri->ri_emuwidth - 1;
        !          1336:
        !          1337:        /* Set fill color in block-color registers */
        !          1338:        TGAWREG(dc, TGA_REG_GBCR0, color);
        !          1339:        TGAWREG(dc, TGA_REG_GBCR1, color);
        !          1340:        if (ri->ri_depth != 8) {
        !          1341:                TGAWREG(dc, TGA_REG_GBCR2, color);
        !          1342:                TGAWREG(dc, TGA_REG_GBCR3, color);
        !          1343:                TGAWREG(dc, TGA_REG_GBCR4, color);
        !          1344:                TGAWREG(dc, TGA_REG_GBCR5, color);
        !          1345:                TGAWREG(dc, TGA_REG_GBCR6, color);
        !          1346:                TGAWREG(dc, TGA_REG_GBCR7, color);
        !          1347:        }
        !          1348:
        !          1349:        /* Set raster operation to "copy"... */
        !          1350:        if (ri->ri_depth == 8)
        !          1351:                TGAWREG(dc, TGA_REG_GOPR, 0x3);
        !          1352:        else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
        !          1353:                TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
        !          1354:
        !          1355:        /* Set which pixels we're drawing (of a possible 32). */
        !          1356:        TGAWREG(dc, TGA_REG_GDAR, 0xffffffff);
        !          1357:
        !          1358:        /* Set drawing mode to block fill. */
        !          1359:        TGAWREG(dc, TGA_REG_GMOR, 0x2d);
        !          1360:
        !          1361:        /* Insert write barrier before actually sending data */
        !          1362:        /* XXX Abuses the fact that there is only one write barrier on Alphas */
        !          1363:        TGAREGWB(dc, TGA_REG_GMOR, 1);
        !          1364:
        !          1365:        while (lines--) {
        !          1366:                *rp = pixels;
        !          1367:                rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
        !          1368:        }
        !          1369:
        !          1370:        /* Set grapics mode back to normal. */
        !          1371:        TGAWREG(dc, TGA_REG_GMOR, 0);
        !          1372:
        !          1373: }
        !          1374:
        !          1375: void
        !          1376: tga_erasecols (c, row, col, num, attr)
        !          1377:        void *c;
        !          1378:        int row, col, num;
        !          1379:        long attr;
        !          1380: {
        !          1381:        struct rasops_info *ri = c;
        !          1382:        struct tga_devconfig *dc = ri->ri_hw;
        !          1383:        int32_t color, lines, pixels;
        !          1384:        int fg, bg;
        !          1385:        int32_t *rp;
        !          1386:
        !          1387:        ri->ri_ops.unpack_attr(c, attr, &fg, &bg, NULL);
        !          1388:        color = ri->ri_devcmap[bg];
        !          1389:        rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
        !          1390:        lines = ri->ri_font->fontheight;
        !          1391:        pixels = (num * ri->ri_font->fontwidth) - 1;
        !          1392:
        !          1393:        /* Set fill color in block-color registers */
        !          1394:        TGAWREG(dc, TGA_REG_GBCR0, color);
        !          1395:        TGAWREG(dc, TGA_REG_GBCR1, color);
        !          1396:        if (ri->ri_depth != 8) {
        !          1397:                TGAWREG(dc, TGA_REG_GBCR2, color);
        !          1398:                TGAWREG(dc, TGA_REG_GBCR3, color);
        !          1399:                TGAWREG(dc, TGA_REG_GBCR4, color);
        !          1400:                TGAWREG(dc, TGA_REG_GBCR5, color);
        !          1401:                TGAWREG(dc, TGA_REG_GBCR6, color);
        !          1402:                TGAWREG(dc, TGA_REG_GBCR7, color);
        !          1403:        }
        !          1404:
        !          1405:        /* Set raster operation to "copy"... */
        !          1406:        if (ri->ri_depth == 8)
        !          1407:                TGAWREG(dc, TGA_REG_GOPR, 0x3);
        !          1408:        else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
        !          1409:                TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
        !          1410:
        !          1411:        /* Set which pixels we're drawing (of a possible 32). */
        !          1412:        TGAWREG(dc, TGA_REG_GDAR, 0xffffffff);
        !          1413:
        !          1414:        /* Set drawing mode to block fill. */
        !          1415:        TGAWREG(dc, TGA_REG_GMOR, 0x2d);
        !          1416:
        !          1417:        /* Insert write barrier before actually sending data */
        !          1418:        /* XXX Abuses the fact that there is only one write barrier on Alphas */
        !          1419:        TGAREGWB(dc, TGA_REG_GMOR, 1);
        !          1420:
        !          1421:        while (lines--) {
        !          1422:                *rp = pixels;
        !          1423:                rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
        !          1424:        }
        !          1425:
        !          1426:        /* Set grapics mode back to normal. */
        !          1427:        TGAWREG(dc, TGA_REG_GMOR, 0);
        !          1428: }
        !          1429:
        !          1430:
        !          1431: void
        !          1432: tga_ramdac_wr(v, btreg, val)
        !          1433:        void *v;
        !          1434:        u_int btreg;
        !          1435:        u_int8_t val;
        !          1436: {
        !          1437:        struct tga_devconfig *dc = v;
        !          1438:
        !          1439:        if (btreg > BT485_REG_MAX)
        !          1440:                panic("tga_ramdac_wr: reg %d out of range", btreg);
        !          1441:
        !          1442:        TGAWREG(dc, TGA_REG_EPDR, (btreg << 9) | (0 << 8 ) | val); /* XXX */
        !          1443:        TGAREGWB(dc, TGA_REG_EPDR, 1);
        !          1444: }
        !          1445:
        !          1446: void
        !          1447: tga2_ramdac_wr(v, btreg, val)
        !          1448:        void *v;
        !          1449:        u_int btreg;
        !          1450:        u_int8_t val;
        !          1451: {
        !          1452:        struct tga_devconfig *dc = v;
        !          1453:        bus_space_handle_t ramdac;
        !          1454:
        !          1455:        if (btreg > BT485_REG_MAX)
        !          1456:                panic("tga_ramdac_wr: reg %d out of range", btreg);
        !          1457:
        !          1458:        bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_RAMDAC +
        !          1459:                (0xe << 12) + (btreg << 8), 4, &ramdac);
        !          1460:        bus_space_write_4(dc->dc_memt, ramdac, 0, val & 0xff);
        !          1461:        bus_space_barrier(dc->dc_memt, ramdac, 0, 4, BUS_SPACE_BARRIER_WRITE);
        !          1462: }
        !          1463:
        !          1464: u_int8_t
        !          1465: tga_bt463_rd(v, btreg)
        !          1466:        void *v;
        !          1467:        u_int btreg;
        !          1468: {
        !          1469:        struct tga_devconfig *dc = v;
        !          1470:        tga_reg_t rdval;
        !          1471:
        !          1472:        /*
        !          1473:         * Strobe CE# (high->low->high) since status and data are latched on
        !          1474:         * the falling and rising edges (repsectively) of this active-low signal.
        !          1475:         */
        !          1476:
        !          1477:        TGAREGWB(dc, TGA_REG_EPSR, 1);
        !          1478:        TGAWREG(dc, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
        !          1479:        TGAREGWB(dc, TGA_REG_EPSR, 1);
        !          1480:        TGAWREG(dc, TGA_REG_EPSR, (btreg << 2) | 2 | 0);
        !          1481:
        !          1482:        TGAREGRB(dc, TGA_REG_EPSR, 1);
        !          1483:
        !          1484:        rdval = TGARREG(dc, TGA_REG_EPDR);
        !          1485:        TGAREGWB(dc, TGA_REG_EPSR, 1);
        !          1486:        TGAWREG(dc, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
        !          1487:
        !          1488:        return (rdval >> 16) & 0xff;
        !          1489: }
        !          1490:
        !          1491: void
        !          1492: tga_bt463_wr(v, btreg, val)
        !          1493:        void *v;
        !          1494:        u_int btreg;
        !          1495:        u_int8_t val;
        !          1496: {
        !          1497:        struct tga_devconfig *dc = v;
        !          1498:
        !          1499:        /*
        !          1500:         * In spite of the 21030 documentation, to set the MPU bus bits for
        !          1501:         * a write, you set them in the upper bits of EPDR, not EPSR.
        !          1502:         */
        !          1503:
        !          1504:        /*
        !          1505:         * Strobe CE# (high->low->high) since status and data are latched on
        !          1506:         * the falling and rising edges of this active-low signal.
        !          1507:         */
        !          1508:
        !          1509:        TGAREGWB(dc, TGA_REG_EPDR, 1);
        !          1510:        TGAWREG(dc, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
        !          1511:        TGAREGWB(dc, TGA_REG_EPDR, 1);
        !          1512:        TGAWREG(dc, TGA_REG_EPDR, (btreg << 10) | 0x000 | val);
        !          1513:        TGAREGWB(dc, TGA_REG_EPDR, 1);
        !          1514:        TGAWREG(dc, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
        !          1515:
        !          1516: }
        !          1517:
        !          1518: u_int8_t
        !          1519: tga_ramdac_rd(v, btreg)
        !          1520:        void *v;
        !          1521:        u_int btreg;
        !          1522: {
        !          1523:        struct tga_devconfig *dc = v;
        !          1524:        tga_reg_t rdval;
        !          1525:
        !          1526:        if (btreg > BT485_REG_MAX)
        !          1527:                panic("tga_ramdac_rd: reg %d out of range", btreg);
        !          1528:
        !          1529:        TGAWREG(dc, TGA_REG_EPSR, (btreg << 1) | 0x1); /* XXX */
        !          1530:        TGAREGWB(dc, TGA_REG_EPSR, 1);
        !          1531:
        !          1532:        rdval = TGARREG(dc, TGA_REG_EPDR);
        !          1533:        return (rdval >> 16) & 0xff;                            /* XXX */
        !          1534: }
        !          1535:
        !          1536: u_int8_t
        !          1537: tga2_ramdac_rd(v, btreg)
        !          1538:        void *v;
        !          1539:        u_int btreg;
        !          1540: {
        !          1541:        struct tga_devconfig *dc = v;
        !          1542:        bus_space_handle_t ramdac;
        !          1543:        u_int8_t retval;
        !          1544:
        !          1545:        if (btreg > BT485_REG_MAX)
        !          1546:                panic("tga_ramdac_rd: reg %d out of range", btreg);
        !          1547:
        !          1548:        bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_RAMDAC +
        !          1549:                (0xe << 12) + (btreg << 8), 4, &ramdac);
        !          1550:        retval = bus_space_read_4(dc->dc_memt, ramdac, 0) & 0xff;
        !          1551:        bus_space_barrier(dc->dc_memt, ramdac, 0, 4, BUS_SPACE_BARRIER_READ);
        !          1552:        return retval;
        !          1553: }
        !          1554:
        !          1555: #include <dev/ic/decmonitors.c>
        !          1556: void tga2_ics9110_wr(
        !          1557:        struct tga_devconfig *dc,
        !          1558:        int dotclock
        !          1559: );
        !          1560:
        !          1561: struct monitor *tga_getmonitor(struct tga_devconfig *dc);
        !          1562:
        !          1563: void
        !          1564: tga2_init(dc)
        !          1565:        struct tga_devconfig *dc;
        !          1566: {
        !          1567:        struct  monitor *m = tga_getmonitor(dc);
        !          1568:
        !          1569:
        !          1570:        /* Deal with the dot clocks.
        !          1571:         */
        !          1572:        if (dc->dc_tga_type == TGA_TYPE_POWERSTORM_4D20) {
        !          1573:                /* Set this up as a reference clock for the
        !          1574:                 * ibm561's PLL.
        !          1575:                 */
        !          1576:                tga2_ics9110_wr(dc, 14300000);
        !          1577:                /* XXX Can't set up the dotclock properly, until such time
        !          1578:                 * as the RAMDAC is configured.
        !          1579:                 */
        !          1580:        } else {
        !          1581:                /* otherwise the ics9110 is our clock. */
        !          1582:                tga2_ics9110_wr(dc, m->dotclock);
        !          1583:        }
        !          1584: #if 0
        !          1585:        TGAWREG(dc, TGA_REG_VHCR,
        !          1586:             ((m->hbp / 4) << 21) |
        !          1587:             ((m->hsync / 4) << 14) |
        !          1588:            (((m->hfp - 4) / 4) << 9) |
        !          1589:             ((m->cols + 4) / 4));
        !          1590: #else
        !          1591:        TGAWREG(dc, TGA_REG_VHCR,
        !          1592:             ((m->hbp / 4) << 21) |
        !          1593:             ((m->hsync / 4) << 14) |
        !          1594:            (((m->hfp) / 4) << 9) |
        !          1595:             ((m->cols) / 4));
        !          1596: #endif
        !          1597:        TGAWREG(dc, TGA_REG_VVCR,
        !          1598:            (m->vbp << 22) |
        !          1599:            (m->vsync << 16) |
        !          1600:            (m->vfp << 11) |
        !          1601:            (m->rows));
        !          1602:        TGAWREG(dc, TGA_REG_VVBR, 1);
        !          1603:        TGAREGRWB(dc, TGA_REG_VHCR, 3);
        !          1604:        TGAWREG(dc, TGA_REG_VVVR, TGARREG(dc, TGA_REG_VVVR) | 1);
        !          1605:        TGAREGRWB(dc, TGA_REG_VVVR, 1);
        !          1606:        TGAWREG(dc, TGA_REG_GPMR, 0xffffffff);
        !          1607:        TGAREGRWB(dc, TGA_REG_GPMR, 1);
        !          1608: }
        !          1609:
        !          1610: void
        !          1611: tga2_ics9110_wr(dc, dotclock)
        !          1612:        struct tga_devconfig *dc;
        !          1613:        int dotclock;
        !          1614: {
        !          1615:        bus_space_handle_t clock;
        !          1616:        u_int32_t valU;
        !          1617:        int N, M, R, V, X;
        !          1618:        int i;
        !          1619:
        !          1620:        switch (dotclock) {
        !          1621:        case 130808000:
        !          1622:                N = 0x40; M = 0x7; V = 0x0; X = 0x1; R = 0x1; break;
        !          1623:        case 119840000:
        !          1624:                N = 0x2d; M = 0x2b; V = 0x1; X = 0x1; R = 0x1; break;
        !          1625:        case 108180000:
        !          1626:                N = 0x11; M = 0x9; V = 0x1; X = 0x1; R = 0x2; break;
        !          1627:        case 103994000:
        !          1628:                N = 0x6d; M = 0xf; V = 0x0; X = 0x1; R = 0x1; break;
        !          1629:        case 175000000:
        !          1630:                N = 0x5F; M = 0x3E; V = 0x1; X = 0x1; R = 0x1; break;
        !          1631:        case  75000000:
        !          1632:                N = 0x6e; M = 0x15; V = 0x0; X = 0x1; R = 0x1; break;
        !          1633:        case  74000000:
        !          1634:                N = 0x2a; M = 0x41; V = 0x1; X = 0x1; R = 0x1; break;
        !          1635:        case  69000000:
        !          1636:                N = 0x35; M = 0xb; V = 0x0; X = 0x1; R = 0x1; break;
        !          1637:        case  65000000:
        !          1638:                N = 0x6d; M = 0x0c; V = 0x0; X = 0x1; R = 0x2; break;
        !          1639:        case  50000000:
        !          1640:                N = 0x37; M = 0x3f; V = 0x1; X = 0x1; R = 0x2; break;
        !          1641:        case  40000000:
        !          1642:                N = 0x5f; M = 0x11; V = 0x0; X = 0x1; R = 0x2; break;
        !          1643:        case  31500000:
        !          1644:                N = 0x16; M = 0x05; V = 0x0; X = 0x1; R = 0x2; break;
        !          1645:        case  25175000:
        !          1646:                N = 0x66; M = 0x1d; V = 0x0; X = 0x1; R = 0x2; break;
        !          1647:        case 135000000:
        !          1648:                N = 0x42; M = 0x07; V = 0x0; X = 0x1; R = 0x1; break;
        !          1649:        case 110000000:
        !          1650:                N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
        !          1651:        case 202500000:
        !          1652:                N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
        !          1653:        case  14300000:         /* this one is just a ref clock */
        !          1654:                N = 0x03; M = 0x03; V = 0x1; X = 0x1; R = 0x3; break;
        !          1655:        default:
        !          1656:                panic("unrecognized clock rate %d", dotclock);
        !          1657:        }
        !          1658:
        !          1659:        /* XXX -- hard coded, bad */
        !          1660:        valU  = N | ( M << 7 ) | (V << 14);
        !          1661:        valU |= (X << 15) | (R << 17);
        !          1662:        valU |= 0x17 << 19;
        !          1663:
        !          1664:        bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_EXTDEV +
        !          1665:            TGA2_MEM_CLOCK + (0xe << 12), 4, &clock); /* XXX */
        !          1666:
        !          1667:        for (i = 24; i > 0; i--) {
        !          1668:                u_int32_t writeval;
        !          1669:
        !          1670:                writeval = valU & 0x1;
        !          1671:                if (i == 1)
        !          1672:                        writeval |= 0x2;
        !          1673:                valU >>= 1;
        !          1674:                bus_space_write_4(dc->dc_memt, clock, 0, writeval);
        !          1675:                bus_space_barrier(dc->dc_memt, clock, 0, 4, BUS_SPACE_BARRIER_WRITE);
        !          1676:         }
        !          1677:        bus_space_subregion(dc->dc_memt, dc->dc_memh, TGA2_MEM_EXTDEV +
        !          1678:            TGA2_MEM_CLOCK + (0xe << 12) + (0x1 << 11) + (0x1 << 11), 4,
        !          1679:                &clock); /* XXX */
        !          1680:        bus_space_write_4(dc->dc_memt, clock, 0, 0x0);
        !          1681:        bus_space_barrier(dc->dc_memt, clock, 0, 0, BUS_SPACE_BARRIER_WRITE);
        !          1682: }
        !          1683:
        !          1684: struct monitor *
        !          1685: tga_getmonitor(dc)
        !          1686:        struct tga_devconfig *dc;
        !          1687: {
        !          1688:        return &decmonitors[(~TGARREG(dc, TGA_REG_GREV) >> 16) & 0x0f];
        !          1689: }
        !          1690:
        !          1691: unsigned
        !          1692: tga_getdotclock(dc)
        !          1693:        struct tga_devconfig *dc;
        !          1694: {
        !          1695:        return tga_getmonitor(dc)->dotclock;
        !          1696: }

CVSweb