[BACK]Return to lunafb.c CVS log [TXT][DIR] Up to [local] / sys / arch / luna88k / dev

Annotation of sys/arch/luna88k/dev/lunafb.c, Revision 1.1

1.1     ! nbrk        1: /* $OpenBSD: lunafb.c,v 1.8 2006/11/29 12:13:54 miod Exp $ */
        !             2: /* $NetBSD: lunafb.c,v 1.7.6.1 2002/08/07 01:48:34 lukem Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Tohru Nishimura.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *     This product includes software developed by the NetBSD
        !            22:  *     Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/conf.h>
        !            43: #include <sys/device.h>
        !            44: #include <sys/ioctl.h>
        !            45: #include <sys/malloc.h>
        !            46: #include <sys/mman.h>
        !            47: #include <sys/proc.h>
        !            48: #include <sys/tty.h>
        !            49: #include <sys/errno.h>
        !            50: #include <sys/buf.h>
        !            51:
        !            52: #include <uvm/uvm_extern.h>
        !            53:
        !            54: #include <dev/wscons/wsconsio.h>
        !            55: #include <dev/wscons/wsdisplayvar.h>
        !            56: #include <dev/rasops/rasops.h>
        !            57:
        !            58: #include <machine/cpu.h>
        !            59: #include <machine/autoconf.h>
        !            60:
        !            61: struct bt454 {
        !            62:        u_int8_t bt_addr;               /* map address register */
        !            63:        u_int8_t bt_cmap;               /* colormap data register */
        !            64: };
        !            65:
        !            66: struct bt458 {
        !            67:        u_int8_t bt_addr;               /* map address register */
        !            68:                unsigned :24;
        !            69:        u_int8_t bt_cmap;               /* colormap data register */
        !            70:                unsigned :24;
        !            71:        u_int8_t bt_ctrl;               /* control register */
        !            72:                unsigned :24;
        !            73:        u_int8_t bt_omap;               /* overlay (cursor) map register */
        !            74:                unsigned :24;
        !            75: };
        !            76:
        !            77: #define        OMFB_RFCNT      0xB1000000      /* video h-origin/v-origin */
        !            78: #define        OMFB_PLANEMASK  0xB1040000      /* planemask register */
        !            79: #define        OMFB_FB_WADDR   0xB1080008      /* common plane */
        !            80: #define        OMFB_FB_RADDR   0xB10C0008      /* plane #0 */
        !            81: #define        OMFB_ROPFUNC    0xB12C0000      /* ROP function code */
        !            82: #define        OMFB_RAMDAC     0xC1100000      /* Bt454/Bt458 RAMDAC */
        !            83: #define        OMFB_SIZE       (0xB1300000 - 0xB1080000 + NBPG)
        !            84:
        !            85: struct om_hwdevconfig {
        !            86:        int     dc_wid;                 /* width of frame buffer */
        !            87:        int     dc_ht;                  /* height of frame buffer */
        !            88:        int     dc_depth;               /* depth, bits per pixel */
        !            89:        int     dc_rowbytes;            /* bytes in a FB scan line */
        !            90:        int     dc_cmsize;              /* colormap size */
        !            91:        vaddr_t dc_videobase;           /* base of flat frame buffer */
        !            92:        struct rasops_info dc_ri;       /* raster blitter variables */
        !            93: };
        !            94:
        !            95: struct hwcmap {
        !            96: #define CMAP_SIZE 256
        !            97:        u_int8_t r[CMAP_SIZE];
        !            98:        u_int8_t g[CMAP_SIZE];
        !            99:        u_int8_t b[CMAP_SIZE];
        !           100: };
        !           101:
        !           102: struct omfb_softc {
        !           103:        struct device sc_dev;           /* base device */
        !           104:        struct om_hwdevconfig *sc_dc;   /* device configuration */
        !           105:        struct hwcmap sc_cmap;          /* software copy of colormap */
        !           106:        int nscreens;
        !           107: };
        !           108:
        !           109: int  omgetcmap(struct omfb_softc *, struct wsdisplay_cmap *);
        !           110: int  omsetcmap(struct omfb_softc *, struct wsdisplay_cmap *);
        !           111:
        !           112: struct om_hwdevconfig omfb_console_dc;
        !           113: void omfb_getdevconfig(paddr_t, struct om_hwdevconfig *);
        !           114:
        !           115: /* in omrasops.c */
        !           116: void   om_cursor(void *, int, int, int);
        !           117: void   om_putchar(void *, int, int, u_int, long);
        !           118: void   om_copycols(void *, int, int, int, int);
        !           119: void   om_copyrows(void *, int, int, int num);
        !           120: void   om_erasecols(void *, int, int, int, long);
        !           121: void   om_eraserows(void *, int, int, long);
        !           122:
        !           123: struct wsscreen_descr omfb_stdscreen = {
        !           124:        "std"
        !           125: };
        !           126:
        !           127: const struct wsscreen_descr *_omfb_scrlist[] = {
        !           128:        &omfb_stdscreen,
        !           129: };
        !           130:
        !           131: const struct wsscreen_list omfb_screenlist = {
        !           132:        sizeof(_omfb_scrlist) / sizeof(struct wsscreen_descr *), _omfb_scrlist
        !           133: };
        !           134:
        !           135: int   omfbioctl(void *, u_long, caddr_t, int, struct proc *);
        !           136: paddr_t omfbmmap(void *, off_t, int);
        !           137: int   omfb_alloc_screen(void *, const struct wsscreen_descr *,
        !           138:                                      void **, int *, int *, long *);
        !           139: void  omfb_free_screen(void *, void *);
        !           140: int   omfb_show_screen(void *, void *, int,
        !           141:                                void (*) (void *, int, int), void *);
        !           142:
        !           143: const struct wsdisplay_accessops omfb_accessops = {
        !           144:        omfbioctl,
        !           145:        omfbmmap,
        !           146:        omfb_alloc_screen,
        !           147:        omfb_free_screen,
        !           148:        omfb_show_screen,
        !           149:        NULL,   /* load_font */
        !           150:        NULL,   /* scrollback */
        !           151:        NULL,   /* getchar */
        !           152:        NULL    /* burner */
        !           153: };
        !           154:
        !           155: int  omfbmatch(struct device *, void *, void *);
        !           156: void omfbattach(struct device *, struct device *, void *);
        !           157:
        !           158: const struct cfattach fb_ca = {
        !           159:        sizeof(struct omfb_softc), omfbmatch, omfbattach
        !           160: };
        !           161:
        !           162: struct cfdriver fb_cd = {
        !           163:         NULL, "fb", DV_DULL
        !           164: };
        !           165:
        !           166: extern int hwplanebits;        /* hardware plane bits; retrieved at boot */
        !           167:
        !           168: int omfb_console;
        !           169: int omfb_cnattach(void);
        !           170:
        !           171: int
        !           172: omfbmatch(parent, cf, aux)
        !           173:        struct device *parent;
        !           174:        void *cf, *aux;
        !           175: {
        !           176:        struct mainbus_attach_args *ma = aux;
        !           177:
        !           178:        if (strcmp(ma->ma_name, fb_cd.cd_name))
        !           179:                return (0);
        !           180: #if 0  /* XXX badaddr() bombs if no framebuffer is installed */
        !           181:        if (badaddr((caddr_t)ma->ma_addr, 4))
        !           182:                return (0);
        !           183: #else
        !           184:        if (hwplanebits == 0)
        !           185:                return (0);
        !           186: #endif
        !           187:        return (1);
        !           188: }
        !           189:
        !           190: void
        !           191: omfbattach(parent, self, args)
        !           192:        struct device *parent, *self;
        !           193:        void *args;
        !           194: {
        !           195:        struct omfb_softc *sc = (struct omfb_softc *)self;
        !           196:        struct wsemuldisplaydev_attach_args waa;
        !           197:
        !           198:        if (omfb_console) {
        !           199:                sc->sc_dc = &omfb_console_dc;
        !           200:                sc->nscreens = 1;
        !           201:        }
        !           202:        else {
        !           203:                sc->sc_dc = (struct om_hwdevconfig *)
        !           204:                    malloc(sizeof(struct om_hwdevconfig), M_DEVBUF, M_WAITOK);
        !           205:                omfb_getdevconfig(OMFB_FB_WADDR, sc->sc_dc);
        !           206:        }
        !           207:        printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
        !           208:            sc->sc_dc->dc_depth);
        !           209:
        !           210: #if 0  /* WHITE on BLACK */
        !           211:        cm = &sc->sc_cmap;
        !           212:        memset(cm, 255, sizeof(struct hwcmap));
        !           213:        cm->r[0] = cm->g[0] = cm->b[0] = 0;
        !           214: #endif
        !           215:        waa.console = omfb_console;
        !           216:        waa.scrdata = &omfb_screenlist;
        !           217:        waa.accessops = &omfb_accessops;
        !           218:        waa.accesscookie = sc;
        !           219:        waa.defaultscreens = 0;
        !           220:
        !           221:        config_found(self, &waa, wsemuldisplaydevprint);
        !           222: }
        !           223:
        !           224: /* EXPORT */ int
        !           225: omfb_cnattach()
        !           226: {
        !           227:        struct om_hwdevconfig *dc = &omfb_console_dc;
        !           228:        struct rasops_info *ri = &dc->dc_ri;
        !           229:        long defattr;
        !           230:
        !           231:        omfb_getdevconfig(OMFB_FB_WADDR, dc);
        !           232:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
        !           233:        wsdisplay_cnattach(&omfb_stdscreen, ri, 0, 0, defattr);
        !           234:        omfb_console = 1;
        !           235:        return (0);
        !           236: }
        !           237:
        !           238: int
        !           239: omfbioctl(v, cmd, data, flag, p)
        !           240:        void *v;
        !           241:        u_long cmd;
        !           242:        caddr_t data;
        !           243:        int flag;
        !           244:        struct proc *p;
        !           245: {
        !           246:        struct omfb_softc *sc = v;
        !           247:        struct om_hwdevconfig *dc = sc->sc_dc;
        !           248:
        !           249:        switch (cmd) {
        !           250:        case WSDISPLAYIO_GTYPE:
        !           251:                *(u_int *)data = WSDISPLAY_TYPE_LUNA;
        !           252:                break;
        !           253:
        !           254:        case WSDISPLAYIO_GINFO:
        !           255: #define        wsd_fbip ((struct wsdisplay_fbinfo *)data)
        !           256:                wsd_fbip->height = dc->dc_ht;
        !           257:                wsd_fbip->width = dc->dc_wid;
        !           258:                wsd_fbip->depth = dc->dc_depth;
        !           259:                wsd_fbip->cmsize = dc->dc_cmsize;
        !           260: #undef fbt
        !           261:                break;
        !           262:
        !           263:        case WSDISPLAYIO_GETCMAP:
        !           264:                return omgetcmap(sc, (struct wsdisplay_cmap *)data);
        !           265:
        !           266:        case WSDISPLAYIO_PUTCMAP:
        !           267:                return omsetcmap(sc, (struct wsdisplay_cmap *)data);
        !           268:
        !           269:        case WSDISPLAYIO_SVIDEO:
        !           270:        case WSDISPLAYIO_GVIDEO:
        !           271:                break;
        !           272:
        !           273:        case WSDISPLAYIO_GCURPOS:
        !           274:        case WSDISPLAYIO_SCURPOS:
        !           275:        case WSDISPLAYIO_GCURMAX:
        !           276:        case WSDISPLAYIO_GCURSOR:
        !           277:        case WSDISPLAYIO_SCURSOR:
        !           278:        default:
        !           279:                return (-1);
        !           280:        }
        !           281:
        !           282:        return (0);
        !           283: }
        !           284:
        !           285: /*
        !           286:  * Return the address that would map the given device at the given
        !           287:  * offset, allowing for the given protection, or return -1 for error.
        !           288:  */
        !           289:
        !           290: paddr_t
        !           291: omfbmmap(v, offset, prot)
        !           292:        void *v;
        !           293:        off_t offset;
        !           294:        int prot;
        !           295: {
        !           296:        struct omfb_softc *sc = v;
        !           297:
        !           298:        if (offset & PGOFSET)
        !           299:                return (-1);
        !           300:        if (offset >= OMFB_SIZE || offset < 0)
        !           301:                return (-1);
        !           302:
        !           303:        return atop(trunc_page(sc->sc_dc->dc_videobase) + offset);
        !           304: }
        !           305:
        !           306: int
        !           307: omgetcmap(sc, p)
        !           308:        struct omfb_softc *sc;
        !           309:        struct wsdisplay_cmap *p;
        !           310: {
        !           311:        u_int index = p->index, count = p->count;
        !           312:         unsigned int cmsize;
        !           313:        int error;
        !           314:
        !           315:        cmsize = sc->sc_dc->dc_cmsize;
        !           316:        if (index >= cmsize || count > cmsize - index)
        !           317:                return (EINVAL);
        !           318:
        !           319:        error = copyout(&sc->sc_cmap.r[index], p->red, count);
        !           320:        if (error != 0)
        !           321:                return (error);
        !           322:        error = copyout(&sc->sc_cmap.g[index], p->green, count);
        !           323:        if (error != 0)
        !           324:                return (error);
        !           325:        error = copyout(&sc->sc_cmap.b[index], p->blue, count);
        !           326:        if (error != 0)
        !           327:                return (error);
        !           328:
        !           329:        return (0);
        !           330: }
        !           331:
        !           332: int
        !           333: omsetcmap(sc, p)
        !           334:        struct omfb_softc *sc;
        !           335:        struct wsdisplay_cmap *p;
        !           336: {
        !           337:        u_int index = p->index, count = p->count;
        !           338:         unsigned int cmsize, i;
        !           339:        int error;
        !           340:
        !           341:        cmsize = sc->sc_dc->dc_cmsize;
        !           342:        if (index >= cmsize || count > cmsize - index)
        !           343:                return (EINVAL);
        !           344:
        !           345:        error = copyin(p->red, &sc->sc_cmap.r[index], count);
        !           346:        if (error != 0)
        !           347:                return (error);
        !           348:        error = copyin(p->green, &sc->sc_cmap.g[index], count);
        !           349:        if (error != 0)
        !           350:                return (error);
        !           351:        error = copyin(p->blue, &sc->sc_cmap.b[index], count);
        !           352:        if (error != 0)
        !           353:                return (error);
        !           354:
        !           355:        if (hwplanebits == 4) {
        !           356:                struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
        !           357:                odac->bt_addr = index;
        !           358:                for (i = index; i < count; i++) {
        !           359:                        odac->bt_cmap = sc->sc_cmap.r[i];
        !           360:                        odac->bt_cmap = sc->sc_cmap.g[i];
        !           361:                        odac->bt_cmap = sc->sc_cmap.b[i];
        !           362:                }
        !           363:        }
        !           364:        else if (hwplanebits == 8) {
        !           365:                struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
        !           366:                ndac->bt_addr = index;
        !           367:                for (i = index; i < count; i++) {
        !           368:                        ndac->bt_cmap = sc->sc_cmap.r[i];
        !           369:                        ndac->bt_cmap = sc->sc_cmap.g[i];
        !           370:                        ndac->bt_cmap = sc->sc_cmap.b[i];
        !           371:                }
        !           372:        }
        !           373:        return (0);
        !           374: }
        !           375:
        !           376: void
        !           377: omfb_getdevconfig(paddr, dc)
        !           378:        paddr_t paddr;
        !           379:        struct om_hwdevconfig *dc;
        !           380: {
        !           381:        int bpp, i;
        !           382:        struct rasops_info *ri;
        !           383:        union {
        !           384:                struct { short h, v; } p;
        !           385:                u_int32_t u;
        !           386:        } rfcnt;
        !           387:
        !           388:        switch (hwplanebits) {
        !           389:        case 8:
        !           390:                bpp = 8;        /* XXX check monochrome bit in DIPSW */
        !           391:                break;
        !           392:        default:
        !           393:        case 4:
        !           394:                bpp = 4;        /* XXX check monochrome bit in DIPSW */
        !           395:                break;
        !           396:        case 1:
        !           397:                bpp = 1;
        !           398:                break;
        !           399:        }
        !           400:        dc->dc_wid = 1280;
        !           401:        dc->dc_ht = 1024;
        !           402:        dc->dc_depth = bpp;
        !           403:        dc->dc_rowbytes = 2048 / 8;
        !           404:        dc->dc_cmsize = (bpp == 1) ? 0 : 1 << bpp;
        !           405:        dc->dc_videobase = paddr;
        !           406:
        !           407: #if 0 /* WHITE on BLACK XXX experiment resulted in WHITE on SKYBLUE... */
        !           408:        if (hwplanebits == 4) {
        !           409:                /* XXX Need Bt454 initialization */
        !           410:                struct bt454 *odac = (struct bt454 *)OMFB_RAMDAC;
        !           411:                odac->bt_addr = 0;
        !           412:                odac->bt_cmap = 0;
        !           413:                odac->bt_cmap = 0;
        !           414:                odac->bt_cmap = 0;
        !           415:                for (i = 1; i < 16; i++) {
        !           416:                        odac->bt_cmap = 255;
        !           417:                        odac->bt_cmap = 255;
        !           418:                        odac->bt_cmap = 255;
        !           419:                }
        !           420:        }
        !           421:        else if (hwplanebits == 8) {
        !           422:                struct bt458 *ndac = (struct bt458 *)OMFB_RAMDAC;
        !           423:
        !           424:                ndac->bt_addr = 0x04;
        !           425:                ndac->bt_ctrl = 0xff; /* all planes will be read */
        !           426:                ndac->bt_ctrl = 0x00; /* all planes have non-blink */
        !           427:                ndac->bt_ctrl = 0x43; /* pallete enabled, ovly plane */
        !           428:                ndac->bt_ctrl = 0x00; /* no test mode */
        !           429:                ndac->bt_addr = 0;
        !           430:                ndac->bt_cmap = 0;
        !           431:                ndac->bt_cmap = 0;
        !           432:                ndac->bt_cmap = 0;
        !           433:                for (i = 1; i < 256; i++) {
        !           434:                        ndac->bt_cmap = 255;
        !           435:                        ndac->bt_cmap = 255;
        !           436:                        ndac->bt_cmap = 255;
        !           437:                }
        !           438:        }
        !           439: #endif
        !           440:
        !           441:        /* adjust h/v origin on screen */
        !           442:        rfcnt.p.h = 7;
        !           443:        rfcnt.p.v = -27;
        !           444:        *(u_int32_t *)OMFB_RFCNT = rfcnt.u; /* single write of 0x007ffe6 */
        !           445:
        !           446:        /* clear the screen */
        !           447:        *(u_int32_t *)OMFB_PLANEMASK = 0xff;
        !           448:        ((u_int32_t *)OMFB_ROPFUNC)[5] = ~0;    /* ROP copy */
        !           449:        for (i = 0; i < dc->dc_ht * dc->dc_rowbytes / sizeof(u_int32_t); i++)
        !           450:                *((u_int32_t *)dc->dc_videobase + i) = 0;
        !           451:        *(u_int32_t *)OMFB_PLANEMASK = 0x01;
        !           452:
        !           453:        /* initialize the raster */
        !           454:        ri = &dc->dc_ri;
        !           455:        ri->ri_width = dc->dc_wid;
        !           456:        ri->ri_height = dc->dc_ht;
        !           457:        ri->ri_depth = 1;       /* since planes are independently addressed */
        !           458:        ri->ri_stride = dc->dc_rowbytes;
        !           459:        ri->ri_bits = (void *)dc->dc_videobase;
        !           460:        ri->ri_flg = RI_CENTER;
        !           461:        ri->ri_hw = dc;
        !           462:
        !           463:        rasops_init(ri, 35, 80);
        !           464:
        !           465:        omfb_stdscreen.ncols = ri->ri_cols;
        !           466:        omfb_stdscreen.nrows = ri->ri_rows;
        !           467:        ri->ri_ops.cursor = om_cursor;
        !           468:        ri->ri_ops.putchar = om_putchar;
        !           469:        ri->ri_ops.copycols = om_copycols;
        !           470:        ri->ri_ops.erasecols = om_erasecols;
        !           471:        ri->ri_ops.copyrows = om_copyrows;
        !           472:        ri->ri_ops.eraserows = om_eraserows;
        !           473:        omfb_stdscreen.textops = &ri->ri_ops;
        !           474:        omfb_stdscreen.fontwidth = ri->ri_font->fontwidth;
        !           475:        omfb_stdscreen.fontheight = ri->ri_font->fontheight;
        !           476:        omfb_stdscreen.capabilities = ri->ri_caps & ~WSSCREEN_UNDERLINE;
        !           477: }
        !           478:
        !           479: int
        !           480: omfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
        !           481:        void *v;
        !           482:        const struct wsscreen_descr *type;
        !           483:        void **cookiep;
        !           484:        int *curxp, *curyp;
        !           485:        long *attrp;
        !           486: {
        !           487:        struct omfb_softc *sc = v;
        !           488:        struct rasops_info *ri = &sc->sc_dc->dc_ri;
        !           489:
        !           490:        if (sc->nscreens > 0)
        !           491:                return (ENOMEM);
        !           492:
        !           493:        *cookiep = ri;
        !           494:        *curxp = 0;
        !           495:        *curyp = 0;
        !           496:        ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
        !           497:        sc->nscreens++;
        !           498:        return (0);
        !           499: }
        !           500:
        !           501: void
        !           502: omfb_free_screen(v, cookie)
        !           503:        void *v;
        !           504:        void *cookie;
        !           505: {
        !           506:        struct omfb_softc *sc = v;
        !           507:
        !           508:        sc->nscreens--;
        !           509: }
        !           510:
        !           511: int
        !           512: omfb_show_screen(v, cookie, waitok, cb, cbarg)
        !           513:        void *v;
        !           514:        void *cookie;
        !           515:        int waitok;
        !           516:        void (*cb)(void *, int, int);
        !           517:        void *cbarg;
        !           518: {
        !           519:        return 0;
        !           520: }

CVSweb