[BACK]Return to r128fb.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / pci

Annotation of src/sys/dev/pci/r128fb.c, Revision 1.1.4.2

1.1.4.2 ! bouyer      1: /*     $NetBSD$        */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2007 Michael Lorenz
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. The name of the author may not be used to endorse or promote products
        !            16:  *    derived from this software without specific prior written permission.
        !            17:  *
        !            18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            27:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: /*
        !            31:  * A console driver for ATI Rage 128 graphics controllers
        !            32:  * tested on macppc only so far
        !            33:  */
        !            34:
        !            35: #include <sys/cdefs.h>
        !            36: __KERNEL_RCSID(0, "$NetBSD$");
        !            37:
        !            38: #include <sys/param.h>
        !            39: #include <sys/systm.h>
        !            40: #include <sys/kernel.h>
        !            41: #include <sys/device.h>
        !            42: #include <sys/malloc.h>
        !            43: #include <sys/lwp.h>
        !            44: #include <sys/kauth.h>
        !            45:
        !            46: #include <uvm/uvm_extern.h>
        !            47:
        !            48: #include <dev/videomode/videomode.h>
        !            49:
        !            50: #include <dev/pci/pcivar.h>
        !            51: #include <dev/pci/pcireg.h>
        !            52: #include <dev/pci/pcidevs.h>
        !            53: #include <dev/pci/pciio.h>
        !            54: #include <dev/pci/r128fbreg.h>
        !            55:
        !            56: #include <dev/wscons/wsdisplayvar.h>
        !            57: #include <dev/wscons/wsconsio.h>
        !            58: #include <dev/wsfont/wsfont.h>
        !            59: #include <dev/rasops/rasops.h>
        !            60: #include <dev/wscons/wsdisplay_vconsvar.h>
        !            61:
        !            62: #include <dev/i2c/i2cvar.h>
        !            63:
        !            64: struct r128fb_softc {
        !            65:        device_t sc_dev;
        !            66:
        !            67:        pci_chipset_tag_t sc_pc;
        !            68:        pcitag_t sc_pcitag;
        !            69:
        !            70:        bus_space_tag_t sc_memt;
        !            71:        bus_space_tag_t sc_iot;
        !            72:
        !            73:        bus_space_handle_t sc_fbh;
        !            74:        bus_space_handle_t sc_regh;
        !            75:        bus_addr_t sc_fb, sc_reg;
        !            76:        bus_size_t sc_fbsize, sc_regsize;
        !            77:
        !            78:        int sc_width, sc_height, sc_depth, sc_stride;
        !            79:        int sc_locked;
        !            80:        void *sc_fbaddr;
        !            81:        struct vcons_screen sc_console_screen;
        !            82:        struct wsscreen_descr sc_defaultscreen_descr;
        !            83:        const struct wsscreen_descr *sc_screens[1];
        !            84:        struct wsscreen_list sc_screenlist;
        !            85:        struct vcons_data vd;
        !            86:        int sc_mode;
        !            87:        u_char sc_cmap_red[256];
        !            88:        u_char sc_cmap_green[256];
        !            89:        u_char sc_cmap_blue[256];
        !            90:        /* engine stuff */
        !            91:        uint32_t sc_master_cntl;
        !            92: };
        !            93:
        !            94: static int     r128fb_match(device_t, cfdata_t, void *);
        !            95: static void    r128fb_attach(device_t, device_t, void *);
        !            96:
        !            97: CFATTACH_DECL_NEW(r128fb, sizeof(struct r128fb_softc),
        !            98:     r128fb_match, r128fb_attach, NULL, NULL);
        !            99:
        !           100: extern const u_char rasops_cmap[768];
        !           101:
        !           102: static int     r128fb_ioctl(void *, void *, u_long, void *, int,
        !           103:                             struct lwp *);
        !           104: static paddr_t r128fb_mmap(void *, void *, off_t, int);
        !           105: static void    r128fb_init_screen(void *, struct vcons_screen *, int, long *);
        !           106:
        !           107: static int     r128fb_putcmap(struct r128fb_softc *, struct wsdisplay_cmap *);
        !           108: static int     r128fb_getcmap(struct r128fb_softc *, struct wsdisplay_cmap *);
        !           109: static void    r128fb_restore_palette(struct r128fb_softc *);
        !           110: static int     r128fb_putpalreg(struct r128fb_softc *, uint8_t, uint8_t,
        !           111:                            uint8_t, uint8_t);
        !           112:
        !           113: static void    r128fb_init(struct r128fb_softc *);
        !           114: static void    r128fb_flush_engine(struct r128fb_softc *);
        !           115: static void    r128fb_rectfill(struct r128fb_softc *, int, int, int, int,
        !           116:                            uint32_t);
        !           117: static void    r128fb_bitblt(struct r128fb_softc *, int, int, int, int, int,
        !           118:                            int, int);
        !           119:
        !           120: static void    r128fb_cursor(void *, int, int, int);
        !           121: #if 0
        !           122: static void    r128fb_putchar(void *, int, int, u_int, long);
        !           123: #endif
        !           124: static void    r128fb_copycols(void *, int, int, int, int);
        !           125: static void    r128fb_erasecols(void *, int, int, int, long);
        !           126: static void    r128fb_copyrows(void *, int, int, int);
        !           127: static void    r128fb_eraserows(void *, int, int, long);
        !           128:
        !           129: struct wsdisplay_accessops r128fb_accessops = {
        !           130:        r128fb_ioctl,
        !           131:        r128fb_mmap,
        !           132:        NULL,   /* alloc_screen */
        !           133:        NULL,   /* free_screen */
        !           134:        NULL,   /* show_screen */
        !           135:        NULL,   /* load_font */
        !           136:        NULL,   /* pollc */
        !           137:        NULL    /* scroll */
        !           138: };
        !           139:
        !           140: static inline void
        !           141: r128fb_wait(struct r128fb_softc *sc, int slots)
        !           142: {
        !           143:        uint32_t reg;
        !           144:
        !           145:        do {
        !           146:                reg = (bus_space_read_4(sc->sc_memt, sc->sc_regh,
        !           147:                    R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK);
        !           148:        } while (reg <= slots);
        !           149: }
        !           150:
        !           151: static void
        !           152: r128fb_flush_engine(struct r128fb_softc *sc)
        !           153: {
        !           154:        uint32_t reg;
        !           155:
        !           156:        reg = bus_space_read_4(sc->sc_memt, sc->sc_regh, R128_PC_NGUI_CTLSTAT);
        !           157:        reg |= R128_PC_FLUSH_ALL;
        !           158:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PC_NGUI_CTLSTAT, reg);
        !           159:        do {
        !           160:                reg = bus_space_read_4(sc->sc_memt, sc->sc_regh,
        !           161:                    R128_PC_NGUI_CTLSTAT);
        !           162:        } while (reg & R128_PC_BUSY);
        !           163: }
        !           164:
        !           165: static int
        !           166: r128fb_match(device_t parent, cfdata_t match, void *aux)
        !           167: {
        !           168:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
        !           169:
        !           170:        if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY ||
        !           171:            PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_DISPLAY_VGA)
        !           172:                return 0;
        !           173:        if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_ATI)
        !           174:                return 0;
        !           175:
        !           176:        /* only card tested on so far - likely need a list */
        !           177:        if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_RAGE1AGP4XT)
        !           178:                return 100;
        !           179:        return (0);
        !           180: }
        !           181:
        !           182: static void
        !           183: r128fb_attach(device_t parent, device_t self, void *aux)
        !           184: {
        !           185:        struct r128fb_softc     *sc = device_private(self);
        !           186:        struct pci_attach_args  *pa = aux;
        !           187:        struct rasops_info      *ri;
        !           188:        char devinfo[256];
        !           189:        struct wsemuldisplaydev_attach_args aa;
        !           190:        prop_dictionary_t       dict;
        !           191:        unsigned long           defattr;
        !           192:        bool                    is_console;
        !           193:        int i, j;
        !           194:
        !           195:        sc->sc_pc = pa->pa_pc;
        !           196:        sc->sc_pcitag = pa->pa_tag;
        !           197:        sc->sc_memt = pa->pa_memt;
        !           198:        sc->sc_iot = pa->pa_iot;
        !           199:        sc->sc_dev = self;
        !           200:
        !           201:        pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
        !           202:        aprint_normal(": %s\n", devinfo);
        !           203:
        !           204:        /* fill in parameters from properties */
        !           205:        dict = device_properties(self);
        !           206:        if (!prop_dictionary_get_uint32(dict, "width", &sc->sc_width)) {
        !           207:                aprint_error("%s: no width property\n", device_xname(self));
        !           208:                return;
        !           209:        }
        !           210:        if (!prop_dictionary_get_uint32(dict, "height", &sc->sc_height)) {
        !           211:                aprint_error("%s: no height property\n", device_xname(self));
        !           212:                return;
        !           213:        }
        !           214:        if (!prop_dictionary_get_uint32(dict, "depth", &sc->sc_depth)) {
        !           215:                aprint_error("%s: no depth property\n", device_xname(self));
        !           216:                return;
        !           217:        }
        !           218:        if (!prop_dictionary_get_uint32(dict, "linebytes", &sc->sc_stride)) {
        !           219:                aprint_error("%s: no linebytes property\n",
        !           220:                    device_xname(self));
        !           221:                return;
        !           222:        }
        !           223:
        !           224:        prop_dictionary_get_bool(dict, "is_console", &is_console);
        !           225:
        !           226:        if (pci_mapreg_map(pa, 0x10, PCI_MAPREG_TYPE_MEM,
        !           227:            BUS_SPACE_MAP_LINEAR,
        !           228:            &sc->sc_memt, &sc->sc_fbh, &sc->sc_fb, &sc->sc_fbsize)) {
        !           229:                aprint_error("%s: failed to map the frame buffer.\n",
        !           230:                    device_xname(sc->sc_dev));
        !           231:        }
        !           232:        sc->sc_fbaddr = bus_space_vaddr(sc->sc_memt, sc->sc_fbh);
        !           233:
        !           234:        if (pci_mapreg_map(pa, 0x18, PCI_MAPREG_TYPE_MEM, 0,
        !           235:            &sc->sc_memt, &sc->sc_regh, &sc->sc_reg, &sc->sc_regsize)) {
        !           236:                aprint_error("%s: failed to map registers.\n",
        !           237:                    device_xname(sc->sc_dev));
        !           238:        }
        !           239:
        !           240:        aprint_normal("%s: %d MB aperture at 0x%08x\n", device_xname(self),
        !           241:            (sc->sc_fbsize >> 20), sc->sc_fb);
        !           242:
        !           243:        sc->sc_defaultscreen_descr = (struct wsscreen_descr){
        !           244:                "default",
        !           245:                0, 0,
        !           246:                NULL,
        !           247:                8, 16,
        !           248:                WSSCREEN_WSCOLORS | WSSCREEN_HILIT,
        !           249:                NULL
        !           250:        };
        !           251:        sc->sc_screens[0] = &sc->sc_defaultscreen_descr;
        !           252:        sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens};
        !           253:        sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
        !           254:        sc->sc_locked = 0;
        !           255:
        !           256:        vcons_init(&sc->vd, sc, &sc->sc_defaultscreen_descr,
        !           257:            &r128fb_accessops);
        !           258:        sc->vd.init_screen = r128fb_init_screen;
        !           259:
        !           260:        /* init engine here */
        !           261:        r128fb_init(sc);
        !           262:
        !           263:        ri = &sc->sc_console_screen.scr_ri;
        !           264:
        !           265:        if (is_console) {
        !           266:                vcons_init_screen(&sc->vd, &sc->sc_console_screen, 1,
        !           267:                    &defattr);
        !           268:                sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
        !           269:
        !           270:                sc->sc_defaultscreen_descr.textops = &ri->ri_ops;
        !           271:                sc->sc_defaultscreen_descr.capabilities = ri->ri_caps;
        !           272:                sc->sc_defaultscreen_descr.nrows = ri->ri_rows;
        !           273:                sc->sc_defaultscreen_descr.ncols = ri->ri_cols;
        !           274:                wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0,
        !           275:                    defattr);
        !           276:        } else {
        !           277:                /*
        !           278:                 * since we're not the console we can postpone the rest
        !           279:                 * until someone actually allocates a screen for us
        !           280:                 */
        !           281:                (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
        !           282:        }
        !           283:
        !           284:        j = 0;
        !           285:        for (i = 0; i < (1 << sc->sc_depth); i++) {
        !           286:
        !           287:                sc->sc_cmap_red[i] = rasops_cmap[j];
        !           288:                sc->sc_cmap_green[i] = rasops_cmap[j + 1];
        !           289:                sc->sc_cmap_blue[i] = rasops_cmap[j + 2];
        !           290:                r128fb_putpalreg(sc, i, rasops_cmap[j], rasops_cmap[j + 1],
        !           291:                    rasops_cmap[j + 2]);
        !           292:                j += 3;
        !           293:        }
        !           294:
        !           295:        r128fb_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height,
        !           296:            ri->ri_devcmap[(defattr >> 16) & 0xff]);
        !           297:
        !           298:        aa.console = is_console;
        !           299:        aa.scrdata = &sc->sc_screenlist;
        !           300:        aa.accessops = &r128fb_accessops;
        !           301:        aa.accesscookie = &sc->vd;
        !           302:
        !           303:        config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
        !           304:
        !           305: }
        !           306:
        !           307: static int
        !           308: r128fb_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
        !           309:        struct lwp *l)
        !           310: {
        !           311:        struct vcons_data *vd = v;
        !           312:        struct r128fb_softc *sc = vd->cookie;
        !           313:        struct wsdisplay_fbinfo *wdf;
        !           314:        struct vcons_screen *ms = vd->active;
        !           315:
        !           316:        switch (cmd) {
        !           317:
        !           318:                case WSDISPLAYIO_GTYPE:
        !           319:                        *(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
        !           320:                        return 0;
        !           321:
        !           322:                /* PCI config read/write passthrough. */
        !           323:                case PCI_IOC_CFGREAD:
        !           324:                case PCI_IOC_CFGWRITE:
        !           325:                        return (pci_devioctl(sc->sc_pc, sc->sc_pcitag,
        !           326:                            cmd, data, flag, l));
        !           327:
        !           328:                case WSDISPLAYIO_GINFO:
        !           329:                        if (ms == NULL)
        !           330:                                return ENODEV;
        !           331:                        wdf = (void *)data;
        !           332:                        wdf->height = ms->scr_ri.ri_height;
        !           333:                        wdf->width = ms->scr_ri.ri_width;
        !           334:                        wdf->depth = ms->scr_ri.ri_depth;
        !           335:                        wdf->cmsize = 256;
        !           336:                        return 0;
        !           337:
        !           338:                case WSDISPLAYIO_GETCMAP:
        !           339:                        return r128fb_getcmap(sc,
        !           340:                            (struct wsdisplay_cmap *)data);
        !           341:
        !           342:                case WSDISPLAYIO_PUTCMAP:
        !           343:                        return r128fb_putcmap(sc,
        !           344:                            (struct wsdisplay_cmap *)data);
        !           345:
        !           346:                case WSDISPLAYIO_LINEBYTES:
        !           347:                        *(u_int *)data = sc->sc_stride;
        !           348:                        return 0;
        !           349:
        !           350:                case WSDISPLAYIO_SMODE:
        !           351:                        {
        !           352:                                int new_mode = *(int*)data;
        !           353:
        !           354:                                /* notify the bus backend */
        !           355:                                if (new_mode != sc->sc_mode) {
        !           356:                                        sc->sc_mode = new_mode;
        !           357:                                        if(new_mode == WSDISPLAYIO_MODE_EMUL) {
        !           358:                                                r128fb_restore_palette(sc);
        !           359:                                                vcons_redraw_screen(ms);
        !           360:                                        }
        !           361:                                }
        !           362:                        }
        !           363:                        return 0;
        !           364:        }
        !           365:        return EPASSTHROUGH;
        !           366: }
        !           367:
        !           368: static paddr_t
        !           369: r128fb_mmap(void *v, void *vs, off_t offset, int prot)
        !           370: {
        !           371:        struct vcons_data *vd = v;
        !           372:        struct r128fb_softc *sc = vd->cookie;
        !           373:        struct lwp *me;
        !           374:        paddr_t pa;
        !           375:
        !           376:        /* 'regular' framebuffer mmap()ing */
        !           377:        if (offset < sc->sc_fbsize) {
        !           378:                pa = bus_space_mmap(sc->sc_memt, sc->sc_fb + offset, 0, prot,
        !           379:                    BUS_SPACE_MAP_LINEAR);
        !           380:                return pa;
        !           381:        }
        !           382:
        !           383:        /*
        !           384:         * restrict all other mappings to processes with superuser privileges
        !           385:         * or the kernel itself
        !           386:         */
        !           387:        me = curlwp;
        !           388:        if (me != NULL) {
        !           389:                if (kauth_authorize_generic(me->l_cred, KAUTH_GENERIC_ISSUSER,
        !           390:                    NULL) != 0) {
        !           391:                        aprint_normal("%s: mmap() rejected.\n",
        !           392:                            device_xname(sc->sc_dev));
        !           393:                        return -1;
        !           394:                }
        !           395:        }
        !           396:
        !           397:        if ((offset >= sc->sc_fb) && (offset < (sc->sc_fb + sc->sc_fbsize))) {
        !           398:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
        !           399:                    BUS_SPACE_MAP_LINEAR);
        !           400:                return pa;
        !           401:        }
        !           402:
        !           403:        if ((offset >= sc->sc_reg) &&
        !           404:            (offset < (sc->sc_reg + sc->sc_regsize))) {
        !           405:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
        !           406:                    BUS_SPACE_MAP_LINEAR);
        !           407:                return pa;
        !           408:        }
        !           409:
        !           410: #ifdef macppc
        !           411:        /* allow mapping of IO space */
        !           412:        if ((offset >= 0xf2000000) && (offset < 0xf2800000)) {
        !           413:                pa = bus_space_mmap(sc->sc_iot, offset - 0xf2000000, 0, prot,
        !           414:                    BUS_SPACE_MAP_LINEAR);
        !           415:                return pa;
        !           416:        }
        !           417: #endif
        !           418:
        !           419: #ifdef OFB_ALLOW_OTHERS
        !           420:        if (offset >= 0x80000000) {
        !           421:                pa = bus_space_mmap(sc->sc_memt, offset, 0, prot,
        !           422:                    BUS_SPACE_MAP_LINEAR);
        !           423:                return pa;
        !           424:        }
        !           425: #endif
        !           426:        return -1;
        !           427: }
        !           428:
        !           429: static void
        !           430: r128fb_init_screen(void *cookie, struct vcons_screen *scr,
        !           431:     int existing, long *defattr)
        !           432: {
        !           433:        struct r128fb_softc *sc = cookie;
        !           434:        struct rasops_info *ri = &scr->scr_ri;
        !           435:
        !           436:        ri->ri_depth = sc->sc_depth;
        !           437:        ri->ri_width = sc->sc_width;
        !           438:        ri->ri_height = sc->sc_height;
        !           439:        ri->ri_stride = sc->sc_stride;
        !           440:        ri->ri_flg = RI_CENTER | RI_FULLCLEAR;
        !           441:
        !           442:        ri->ri_bits = (char *)sc->sc_fbaddr;
        !           443:
        !           444:        if (existing) {
        !           445:                ri->ri_flg |= RI_CLEAR;
        !           446:        }
        !           447:
        !           448:        rasops_init(ri, sc->sc_height / 8, sc->sc_width / 8);
        !           449:        ri->ri_caps = WSSCREEN_WSCOLORS;
        !           450:
        !           451:        rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
        !           452:                    sc->sc_width / ri->ri_font->fontwidth);
        !           453:
        !           454:        ri->ri_hw = scr;
        !           455:        ri->ri_ops.copyrows = r128fb_copyrows;
        !           456:        ri->ri_ops.copycols = r128fb_copycols;
        !           457:        ri->ri_ops.eraserows = r128fb_eraserows;
        !           458:        ri->ri_ops.erasecols = r128fb_erasecols;
        !           459:        ri->ri_ops.cursor = r128fb_cursor;
        !           460: #if 0
        !           461:        ri->ri_ops.putchar = r128fb_putchar;
        !           462: #endif
        !           463: }
        !           464:
        !           465: static int
        !           466: r128fb_putcmap(struct r128fb_softc *sc, struct wsdisplay_cmap *cm)
        !           467: {
        !           468:        u_char *r, *g, *b;
        !           469:        u_int index = cm->index;
        !           470:        u_int count = cm->count;
        !           471:        int i, error;
        !           472:        u_char rbuf[256], gbuf[256], bbuf[256];
        !           473:
        !           474: #ifdef R128FB_DEBUG
        !           475:        aprint_debug("putcmap: %d %d\n",index, count);
        !           476: #endif
        !           477:        if (cm->index >= 256 || cm->count > 256 ||
        !           478:            (cm->index + cm->count) > 256)
        !           479:                return EINVAL;
        !           480:        error = copyin(cm->red, &rbuf[index], count);
        !           481:        if (error)
        !           482:                return error;
        !           483:        error = copyin(cm->green, &gbuf[index], count);
        !           484:        if (error)
        !           485:                return error;
        !           486:        error = copyin(cm->blue, &bbuf[index], count);
        !           487:        if (error)
        !           488:                return error;
        !           489:
        !           490:        memcpy(&sc->sc_cmap_red[index], &rbuf[index], count);
        !           491:        memcpy(&sc->sc_cmap_green[index], &gbuf[index], count);
        !           492:        memcpy(&sc->sc_cmap_blue[index], &bbuf[index], count);
        !           493:
        !           494:        r = &sc->sc_cmap_red[index];
        !           495:        g = &sc->sc_cmap_green[index];
        !           496:        b = &sc->sc_cmap_blue[index];
        !           497:
        !           498:        for (i = 0; i < count; i++) {
        !           499:                r128fb_putpalreg(sc, index, *r, *g, *b);
        !           500:                index++;
        !           501:                r++, g++, b++;
        !           502:        }
        !           503:        return 0;
        !           504: }
        !           505:
        !           506: static int
        !           507: r128fb_getcmap(struct r128fb_softc *sc, struct wsdisplay_cmap *cm)
        !           508: {
        !           509:        u_int index = cm->index;
        !           510:        u_int count = cm->count;
        !           511:        int error;
        !           512:
        !           513:        if (index >= 255 || count > 256 || index + count > 256)
        !           514:                return EINVAL;
        !           515:
        !           516:        error = copyout(&sc->sc_cmap_red[index],   cm->red,   count);
        !           517:        if (error)
        !           518:                return error;
        !           519:        error = copyout(&sc->sc_cmap_green[index], cm->green, count);
        !           520:        if (error)
        !           521:                return error;
        !           522:        error = copyout(&sc->sc_cmap_blue[index],  cm->blue,  count);
        !           523:        if (error)
        !           524:                return error;
        !           525:
        !           526:        return 0;
        !           527: }
        !           528:
        !           529: static void
        !           530: r128fb_restore_palette(struct r128fb_softc *sc)
        !           531: {
        !           532:        int i;
        !           533:
        !           534:        for (i = 0; i < (1 << sc->sc_depth); i++) {
        !           535:                r128fb_putpalreg(sc, i, sc->sc_cmap_red[i],
        !           536:                    sc->sc_cmap_green[i], sc->sc_cmap_blue[i]);
        !           537:        }
        !           538: }
        !           539:
        !           540: static int
        !           541: r128fb_putpalreg(struct r128fb_softc *sc, uint8_t idx, uint8_t r, uint8_t g,
        !           542:     uint8_t b)
        !           543: {
        !           544:        uint32_t reg;
        !           545:
        !           546:        /* whack the DAC */
        !           547:        reg = (r << 16) | (g << 8) | b;
        !           548:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PALETTE_INDEX, idx);
        !           549:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_PALETTE_DATA, reg);
        !           550:        return 0;
        !           551: }
        !           552:
        !           553: static void
        !           554: r128fb_init(struct r128fb_softc *sc)
        !           555: {
        !           556:        uint32_t datatype;
        !           557:
        !           558:        r128fb_flush_engine(sc);
        !           559:
        !           560:        r128fb_wait(sc, 8);
        !           561:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_CRTC_OFFSET, 0);
        !           562:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DEFAULT_OFFSET, 0);
        !           563:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DEFAULT_PITCH,
        !           564:            sc->sc_stride >> 3);
        !           565:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_AUX_SC_CNTL, 0);
        !           566:        bus_space_write_4(sc->sc_memt, sc->sc_regh,
        !           567:            R128_DEFAULT_SC_BOTTOM_RIGHT,
        !           568:            R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
        !           569:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SC_TOP_LEFT, 0);
        !           570:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SC_BOTTOM_RIGHT,
        !           571:            R128_DEFAULT_SC_RIGHT_MAX | R128_DEFAULT_SC_BOTTOM_MAX);
        !           572:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_DATATYPE,
        !           573:            R128_HOST_BIG_ENDIAN_EN);
        !           574:
        !           575:        r128fb_wait(sc, 5);
        !           576:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_PITCH,
        !           577:            sc->sc_stride >> 3);
        !           578:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_PITCH,
        !           579:            sc->sc_stride >> 3);
        !           580:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_OFFSET, 0);
        !           581:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_OFFSET, 0);
        !           582:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_WRITE_MASK,
        !           583:            0xffffffff);
        !           584:
        !           585:        switch (sc->sc_depth) {
        !           586:                case 8:
        !           587:                        datatype = R128_GMC_DST_8BPP_CI;
        !           588:                        break;
        !           589:                case 15:
        !           590:                        datatype = R128_GMC_DST_15BPP;
        !           591:                        break;
        !           592:                case 16:
        !           593:                        datatype = R128_GMC_DST_16BPP;
        !           594:                        break;
        !           595:                case 24:
        !           596:                        datatype = R128_GMC_DST_24BPP;
        !           597:                        break;
        !           598:                case 32:
        !           599:                        datatype = R128_GMC_DST_32BPP;
        !           600:                        break;
        !           601:                default:
        !           602:                        aprint_error("%s: unsupported depth %d\n",
        !           603:                            device_xname(sc->sc_dev), sc->sc_depth);
        !           604:                        return;
        !           605:        }
        !           606:        sc->sc_master_cntl = R128_GMC_CLR_CMP_CNTL_DIS |
        !           607:            R128_GMC_AUX_CLIP_DIS | datatype;
        !           608:
        !           609:        r128fb_flush_engine(sc);
        !           610: }
        !           611:
        !           612: static void
        !           613: r128fb_rectfill(struct r128fb_softc *sc, int x, int y, int wi, int he,
        !           614:      uint32_t colour)
        !           615: {
        !           616:
        !           617:        r128fb_wait(sc, 6);
        !           618:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_GUI_MASTER_CNTL,
        !           619:            R128_GMC_BRUSH_SOLID_COLOR |
        !           620:            R128_GMC_SRC_DATATYPE_COLOR |
        !           621:            R128_ROP3_P |
        !           622:            sc->sc_master_cntl);
        !           623:
        !           624:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_BRUSH_FRGD_CLR,
        !           625:            colour);
        !           626:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_CNTL,
        !           627:            R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
        !           628:        /* now feed it coordinates */
        !           629:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
        !           630:            (x << 16) | y);
        !           631:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
        !           632:            (wi << 16) | he);
        !           633:        r128fb_flush_engine(sc);
        !           634: }
        !           635:
        !           636: static void
        !           637: r128fb_bitblt(struct r128fb_softc *sc, int xs, int ys, int xd, int yd,
        !           638:     int wi, int he, int rop)
        !           639: {
        !           640:        uint32_t dp_cntl = 0;
        !           641:
        !           642:        r128fb_wait(sc, 5);
        !           643:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_GUI_MASTER_CNTL,
        !           644:            R128_GMC_BRUSH_SOLID_COLOR |
        !           645:            R128_GMC_SRC_DATATYPE_COLOR |
        !           646:            rop |
        !           647:            R128_DP_SRC_SOURCE_MEMORY |
        !           648:            sc->sc_master_cntl);
        !           649:
        !           650:        if (yd <= ys) {
        !           651:                dp_cntl = R128_DST_Y_TOP_TO_BOTTOM;
        !           652:        } else {
        !           653:                ys += he - 1;
        !           654:                yd += he - 1;
        !           655:        }
        !           656:        if (xd <= xs) {
        !           657:                dp_cntl |= R128_DST_X_LEFT_TO_RIGHT;
        !           658:        } else {
        !           659:                xs += wi - 1;
        !           660:                xd += wi - 1;
        !           661:        }
        !           662:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DP_CNTL, dp_cntl);
        !           663:
        !           664:        /* now feed it coordinates */
        !           665:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y,
        !           666:            (xs << 16) | ys);
        !           667:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y,
        !           668:            (xd << 16) | yd);
        !           669:        bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT,
        !           670:            (wi << 16) | he);
        !           671:        r128fb_flush_engine(sc);
        !           672: }
        !           673:
        !           674: static void
        !           675: r128fb_cursor(void *cookie, int on, int row, int col)
        !           676: {
        !           677:        struct rasops_info *ri = cookie;
        !           678:        struct vcons_screen *scr = ri->ri_hw;
        !           679:        struct r128fb_softc *sc = scr->scr_cookie;
        !           680:        int x, y, wi, he;
        !           681:
        !           682:        wi = ri->ri_font->fontwidth;
        !           683:        he = ri->ri_font->fontheight;
        !           684:
        !           685:        if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) {
        !           686:                x = ri->ri_ccol * wi + ri->ri_xorigin;
        !           687:                y = ri->ri_crow * he + ri->ri_yorigin;
        !           688:                if (ri->ri_flg & RI_CURSOR) {
        !           689:                        r128fb_bitblt(sc, x, y, x, y, wi, he, R128_ROP3_Dn);
        !           690:                        ri->ri_flg &= ~RI_CURSOR;
        !           691:                }
        !           692:                ri->ri_crow = row;
        !           693:                ri->ri_ccol = col;
        !           694:                if (on) {
        !           695:                        x = ri->ri_ccol * wi + ri->ri_xorigin;
        !           696:                        y = ri->ri_crow * he + ri->ri_yorigin;
        !           697:                        r128fb_bitblt(sc, x, y, x, y, wi, he, R128_ROP3_Dn);
        !           698:                        ri->ri_flg |= RI_CURSOR;;
        !           699:                }
        !           700:        } else {
        !           701:                scr->scr_ri.ri_crow = row;
        !           702:                scr->scr_ri.ri_ccol = col;
        !           703:                scr->scr_ri.ri_flg &= ~RI_CURSOR;
        !           704:        }
        !           705:
        !           706: }
        !           707:
        !           708: #if 0
        !           709: static void
        !           710: r128fb_putchar(void *cookie, int row, int col, u_int c, long attr)
        !           711: {
        !           712: }
        !           713: #endif
        !           714:
        !           715: static void
        !           716: r128fb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
        !           717: {
        !           718:        struct rasops_info *ri = cookie;
        !           719:        struct vcons_screen *scr = ri->ri_hw;
        !           720:        struct r128fb_softc *sc = scr->scr_cookie;
        !           721:        int32_t xs, xd, y, width, height;
        !           722:
        !           723:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
        !           724:                xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol;
        !           725:                xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol;
        !           726:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
        !           727:                width = ri->ri_font->fontwidth * ncols;
        !           728:                height = ri->ri_font->fontheight;
        !           729:                r128fb_bitblt(sc, xs, y, xd, y, width, height, R128_ROP3_S);
        !           730:        }
        !           731: }
        !           732:
        !           733: static void
        !           734: r128fb_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
        !           735: {
        !           736:        struct rasops_info *ri = cookie;
        !           737:        struct vcons_screen *scr = ri->ri_hw;
        !           738:        struct r128fb_softc *sc = scr->scr_cookie;
        !           739:        int32_t x, y, width, height, fg, bg, ul;
        !           740:
        !           741:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
        !           742:                x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol;
        !           743:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
        !           744:                width = ri->ri_font->fontwidth * ncols;
        !           745:                height = ri->ri_font->fontheight;
        !           746:                rasops_unpack_attr(fillattr, &fg, &bg, &ul);
        !           747:
        !           748:                r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
        !           749:        }
        !           750: }
        !           751:
        !           752: static void
        !           753: r128fb_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
        !           754: {
        !           755:        struct rasops_info *ri = cookie;
        !           756:        struct vcons_screen *scr = ri->ri_hw;
        !           757:        struct r128fb_softc *sc = scr->scr_cookie;
        !           758:        int32_t x, ys, yd, width, height;
        !           759:
        !           760:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
        !           761:                x = ri->ri_xorigin;
        !           762:                ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow;
        !           763:                yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow;
        !           764:                width = ri->ri_emuwidth;
        !           765:                height = ri->ri_font->fontheight*nrows;
        !           766:                r128fb_bitblt(sc, x, ys, x, yd, width, height, R128_ROP3_S);
        !           767:        }
        !           768: }
        !           769:
        !           770: static void
        !           771: r128fb_eraserows(void *cookie, int row, int nrows, long fillattr)
        !           772: {
        !           773:        struct rasops_info *ri = cookie;
        !           774:        struct vcons_screen *scr = ri->ri_hw;
        !           775:        struct r128fb_softc *sc = scr->scr_cookie;
        !           776:        int32_t x, y, width, height, fg, bg, ul;
        !           777:
        !           778:        if ((sc->sc_locked == 0) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) {
        !           779:                x = ri->ri_xorigin;
        !           780:                y = ri->ri_yorigin + ri->ri_font->fontheight * row;
        !           781:                width = ri->ri_emuwidth;
        !           782:                height = ri->ri_font->fontheight * nrows;
        !           783:                rasops_unpack_attr(fillattr, &fg, &bg, &ul);
        !           784:
        !           785:                r128fb_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]);
        !           786:        }
        !           787: }
        !           788:

CVSweb <webmaster@jp.NetBSD.org>