Annotation of lucent/sys/src/9/pc/devvga.c, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: #include       "io.h"
        !             7: #include       "../port/error.h"
        !             8: 
        !             9: #include       <libg.h>
        !            10: #include       <gnot.h>
        !            11: #include       "screen.h"
        !            12: #include       "vga.h"
        !            13: 
        !            14: static void setscreen(int, int, int);
        !            15: static void vgaupdate(void);
        !            16: 
        !            17: #define        MINX    8
        !            18: 
        !            19: struct{
        !            20:        Point   pos;
        !            21:        int     bwid;
        !            22: }out;
        !            23: 
        !            24: /* imported */
        !            25: extern GSubfont defont0;
        !            26: extern Cursor arrow;
        !            27: extern GBitmap cursorback;
        !            28: 
        !            29: /* exported */
        !            30: GSubfont *defont;
        !            31: int islittle = 1;                      /* little endian bit ordering in bytes */
        !            32: GBitmap        vgascreen;                      /* hard screen */
        !            33: GBitmap        gscreen;                        /* soft screen */
        !            34: Lock palettelock;                      /* access to DAC registers */
        !            35: Cursor curcursor;                      /* current cursor */
        !            36: 
        !            37: /* local */
        !            38: static ulong   colormap[Pcolours][3];
        !            39: static int     cga = 1;                /* true if in cga mode */
        !            40: static int     vgachanging;            /* true while vga is being worked on */
        !            41: 
        !            42: static Rectangle mbb;
        !            43: static Rectangle NULLMBB = {10000, 10000, -10000, -10000};
        !            44: 
        !            45: /*
        !            46:  *  screen dimensions
        !            47:  */
        !            48: #define        CGAWIDTH        160
        !            49: #define        CGAHEIGHT       24
        !            50: 
        !            51: /*
        !            52:  *  screen memory addresses
        !            53:  */
        !            54: #define SCREENMEM      (0xA0000 | KZERO)
        !            55: #define CGASCREEN      ((uchar*)(0xB8000 | KZERO))
        !            56: 
        !            57: static void nopage(int);
        !            58: 
        !            59: static Vgac vga = {
        !            60:        "vga",
        !            61:        nopage,
        !            62: 
        !            63:        0,
        !            64: };
        !            65: 
        !            66: static Vgac *vgactlr = &vga;                   /* available VGA ctlrs */
        !            67: static Vgac *vgac = &vga;                      /* current VGA ctlr */
        !            68: static Hwgc *hwgctlr;                          /* available HWGC's */
        !            69: Hwgc *hwgc;                                    /* current HWGC */
        !            70: 
        !            71: static char interlaced[2];
        !            72: 
        !            73: Cursor fatarrow = {
        !            74:        { -1, -1 },
        !            75:        {
        !            76:                0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c, 
        !            77:                0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 
        !            78:                0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04, 
        !            79:                0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40, 
        !            80:        },
        !            81:        {
        !            82:                0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0, 
        !            83:                0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8, 
        !            84:                0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8, 
        !            85:                0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00, 
        !            86:        },
        !            87: };
        !            88: 
        !            89: /*
        !            90:  *  vga device
        !            91:  */
        !            92: enum {
        !            93:        Qdir            = 0,
        !            94:        Qvgaiob         = 1,
        !            95:        Qvgaiow         = 2,
        !            96:        Qvgaiol         = 3,
        !            97:        Qvgactl         = 4,
        !            98:        Nvga            = Qvgactl,
        !            99: };
        !           100: Dirtab vgadir[]={
        !           101:        "vgaiob",       { Qvgaiob },    0,      0666,
        !           102:        "vgaiow",       { Qvgaiow },    0,      0666,
        !           103:        "vgaiol",       { Qvgaiol },    0,      0666,
        !           104:        "vgactl",       { Qvgactl },    0,      0666,
        !           105: };
        !           106: 
        !           107: void
        !           108: vgareset(void)
        !           109: {
        !           110:        bbinit();
        !           111: }
        !           112: 
        !           113: void
        !           114: vgainit(void)
        !           115: {
        !           116: }
        !           117: 
        !           118: Chan*
        !           119: vgaattach(char *upec)
        !           120: {
        !           121:        return devattach('v', upec);
        !           122: }
        !           123: 
        !           124: Chan*
        !           125: vgaclone(Chan *c, Chan *nc)
        !           126: {
        !           127:        return devclone(c, nc);
        !           128: }
        !           129: 
        !           130: int
        !           131: vgawalk(Chan *c, char *name)
        !           132: {
        !           133:        return devwalk(c, name, vgadir, Nvga, devgen);
        !           134: }
        !           135: 
        !           136: void
        !           137: vgastat(Chan *c, char *dp)
        !           138: {
        !           139:        devstat(c, dp, vgadir, Nvga, devgen);
        !           140: }
        !           141: 
        !           142: Chan*
        !           143: vgaopen(Chan *c, int omode)
        !           144: {
        !           145:        c = devopen(c, omode, vgadir, Nvga, devgen);
        !           146:        switch(c->qid.path){
        !           147:        case Qvgaiob:
        !           148:        case Qvgaiow:
        !           149:        case Qvgaiol:
        !           150:                lock(&palettelock);
        !           151:                vgachanging++;
        !           152:                unlock(&palettelock);
        !           153:                break;
        !           154:        }
        !           155:        return c;
        !           156: }
        !           157: 
        !           158: void
        !           159: vgacreate(Chan *c, char *name, int omode, ulong perm)
        !           160: {
        !           161:        USED(c, name, omode, perm);
        !           162:        error(Eperm);
        !           163: }
        !           164: 
        !           165: void
        !           166: vgaclose(Chan *c)
        !           167: {
        !           168:        if(c->flag & COPEN)
        !           169:                switch(c->qid.path){
        !           170:                case Qvgaiob:
        !           171:                case Qvgaiow:
        !           172:                case Qvgaiol:
        !           173:                        lock(&palettelock);
        !           174:                        vgachanging--;
        !           175:                        vgaupdate();
        !           176:                        unlock(&palettelock);
        !           177:                        break;
        !           178:                }
        !           179: }
        !           180: 
        !           181: long
        !           182: vgaread(Chan *c, void *buf, long n, ulong offset)
        !           183: {
        !           184:        int port;
        !           185:        uchar *cp;
        !           186:        char cbuf[64];
        !           187:        ushort *sp;
        !           188:        ulong *lp;
        !           189:        Vgac *vgacp;
        !           190: 
        !           191:        switch(c->qid.path&~CHDIR){
        !           192:        case Qdir:
        !           193:                return devdirread(c, buf, n, vgadir, Nvga, devgen);
        !           194:        case Qvgactl:
        !           195:                if(cga)
        !           196:                        return readstr(offset, buf, n, "type: cga\n");
        !           197:                vgacp = vgac;
        !           198:                port = sprint(cbuf, "type: %s\n", vgacp->name);
        !           199:                port += sprint(cbuf+port, "size: %dx%dx%d%s\n",
        !           200:                        gscreen.r.max.x, gscreen.r.max.y,
        !           201:                        1<<gscreen.ldepth, interlaced);
        !           202:                port += sprint(cbuf+port, "hwgc: ");
        !           203:                if(hwgc)
        !           204:                        sprint(cbuf+port, "%s\n", hwgc->name);
        !           205:                else
        !           206:                        sprint(cbuf+port, "off\n");
        !           207:                return readstr(offset, buf, n, cbuf);
        !           208:        case Qvgaiob:
        !           209:                port = offset;
        !           210:                /*
        !           211:                 * It would be nice to be able to do this, but
        !           212:                 * impractical as all the cards are different.
        !           213:                if(checkvgaport(port, n))
        !           214:                        error(Eperm);
        !           215:                 */
        !           216:                for(cp = buf; port < offset+n; port++)
        !           217:                        *cp++ = vgai(port);
        !           218:                return n;
        !           219:        case Qvgaiow:
        !           220:                if((n & 01) || (offset & 01))
        !           221:                        error(Ebadarg);
        !           222:                n /= 2;
        !           223:                for (sp = buf, port=offset; port<offset+n; port+=2)
        !           224:                        *sp++ = ins(port);
        !           225:                return n*2;
        !           226:        case Qvgaiol:
        !           227:                if((n & 03) || (offset & 03))
        !           228:                        error(Ebadarg);
        !           229:                n /= 4;
        !           230:                for (lp = buf, port=offset; port<offset+n; port+=4)
        !           231:                        *lp++ = inl(port);
        !           232:                return n*4;
        !           233:        }
        !           234:        error(Eperm);
        !           235:        return 0;
        !           236: }
        !           237: 
        !           238: static void
        !           239: vgactl(char *arg)
        !           240: {
        !           241:        int x, y, z;
        !           242:        char *cp, *field[3];
        !           243:        Hwgc *hwgcp;
        !           244:        Vgac *vgacp;
        !           245: 
        !           246:        if(getfields(arg, field, 3, " \t\n") != 2)
        !           247:                error(Ebadarg);
        !           248: 
        !           249:        if(strcmp(field[0], "hwgc") == 0){
        !           250:                if(strcmp(field[1], "off") == 0){
        !           251:                        if(hwgc){
        !           252:                                (*hwgc->disable)();
        !           253:                                hwgc = 0;
        !           254:                                hwcurs = 0;
        !           255:                                cursoron(1);
        !           256:                        }
        !           257:                        return;
        !           258:                }
        !           259: 
        !           260:                for(hwgcp = hwgctlr; hwgcp; hwgcp = hwgcp->link){
        !           261:                        if(strcmp(field[1], hwgcp->name) == 0){
        !           262:                                if(hwgc)
        !           263:                                        (*hwgc->disable)();
        !           264:                                else
        !           265:                                        cursoroff(1);
        !           266:                                hwgc = hwgcp;
        !           267:                                hwcurs = 1;
        !           268:                                (*hwgc->enable)();
        !           269:                                setcursor(&curcursor);
        !           270:                                cursoron(1);
        !           271:                                return;
        !           272:                        }
        !           273:                }
        !           274:        }
        !           275:        else if(strcmp(field[0], "type") == 0){
        !           276:                for(vgacp = vgactlr; vgacp; vgacp = vgacp->link){
        !           277:                        if(strcmp(field[1], vgacp->name) == 0){
        !           278:                                vgac = vgacp;
        !           279:                                return;
        !           280:                        }
        !           281:                }
        !           282:        }
        !           283:        else if(strcmp(field[0], "size") == 0){
        !           284:                x = strtoul(field[1], &cp, 0);
        !           285:                if(x == 0 || x > 2048)
        !           286:                        error(Ebadarg);
        !           287: 
        !           288:                if(*cp)
        !           289:                        cp++;
        !           290:                y = strtoul(cp, &cp, 0);
        !           291:                if(y == 0 || y > 1280)
        !           292:                        error(Ebadarg);
        !           293: 
        !           294:                if(*cp)
        !           295:                        cp++;
        !           296:                z = 0;  /* to make the compiler happy */
        !           297:                switch(strtoul(cp, &cp, 0)){
        !           298:                case 8:
        !           299:                        z = 3; break;
        !           300:                case 4:
        !           301:                        z = 2; break;
        !           302:                case 2:
        !           303:                        z = 1; break;
        !           304:                case 1:
        !           305:                        z = 0; break;
        !           306:                default:
        !           307:                        error(Ebadarg);
        !           308:                }
        !           309:                interlaced[0] = *cp;
        !           310: 
        !           311:                cursoroff(1);
        !           312:                setscreen(x, y, z);
        !           313:                cursoron(1);
        !           314:                return;
        !           315:        }
        !           316: 
        !           317:        error(Ebadarg);
        !           318: }
        !           319: 
        !           320: long
        !           321: vgawrite(Chan *c, void *buf, long n, ulong offset)
        !           322: {
        !           323:        int port;
        !           324:        uchar *cp;
        !           325:        char cbuf[64];
        !           326:        ushort *sp;
        !           327:        ulong *lp;
        !           328: 
        !           329:        switch(c->qid.path&~CHDIR){
        !           330:        case Qdir:
        !           331:                error(Eperm);
        !           332:        case Qvgactl:
        !           333:                if(offset != 0 || n >= sizeof(cbuf))
        !           334:                        error(Ebadarg);
        !           335:                memmove(cbuf, buf, n);
        !           336:                cbuf[n] = 0;
        !           337:                vgactl(cbuf);
        !           338:                return n;
        !           339:        case Qvgaiob:
        !           340:                port = offset;
        !           341:                /*
        !           342:                if(checkvgaport(port, n))
        !           343:                        error(Eperm);
        !           344:                 */
        !           345:                for(cp = buf; port < offset+n; port++)
        !           346:                        vgao(port, *cp++);
        !           347:                return n;
        !           348:        case Qvgaiow:
        !           349:                if((n & 01) || (offset & 01))
        !           350:                        error(Ebadarg);
        !           351:                n /= 2;
        !           352:                for (sp = buf, port=offset; port<offset+n; port+=2)
        !           353:                        outs(port, *sp++);
        !           354:                return n*2;
        !           355:        case Qvgaiol:
        !           356:                if((n & 03) || (offset & 03))
        !           357:                        error(Ebadarg);
        !           358:                n /= 4;
        !           359:                for (lp = buf, port=offset; port<offset+n; port+=4)
        !           360:                        outl(port, *lp++);
        !           361:                return n*4;
        !           362:        }
        !           363:        error(Eperm);
        !           364:        return 0;
        !           365: }
        !           366: 
        !           367: void
        !           368: vgaremove(Chan *c)
        !           369: {
        !           370:        USED(c);
        !           371:        error(Eperm);
        !           372: }
        !           373: 
        !           374: void
        !           375: vgawstat(Chan *c, char *dp)
        !           376: {
        !           377:        USED(c, dp);
        !           378:        error(Eperm);
        !           379: }
        !           380: 
        !           381: int
        !           382: vgaxi(long port, uchar index)
        !           383: {
        !           384:        uchar data;
        !           385: 
        !           386:        switch(port){
        !           387: 
        !           388:        case Seqx:
        !           389:        case Crtx:
        !           390:        case Grx:
        !           391:                outb(port, index);
        !           392:                data = inb(port+1);
        !           393:                break;
        !           394: 
        !           395:        case Attrx:
        !           396:                /*
        !           397:                 * Allow processor access to the colour
        !           398:                 * palette registers. Writes to Attrx must
        !           399:                 * be preceded by a read from Status1 to
        !           400:                 * initialise the register to point to the
        !           401:                 * index register and not the data register.
        !           402:                 * Processor access is allowed by turning
        !           403:                 * off bit 0x20.
        !           404:                 */
        !           405:                inb(Status1);
        !           406:                if(index < 0x10){
        !           407:                        outb(Attrx, index);
        !           408:                        data = inb(Attrx+1);
        !           409:                        inb(Status1);
        !           410:                        outb(Attrx, 0x20|index);
        !           411:                }
        !           412:                else{
        !           413:                        outb(Attrx, 0x20|index);
        !           414:                        data = inb(Attrx+1);
        !           415:                }
        !           416:                break;
        !           417: 
        !           418:        default:
        !           419:                return -1;
        !           420:        }
        !           421: 
        !           422:        return data & 0xFF;
        !           423: }
        !           424: 
        !           425: int
        !           426: vgaxo(long port, uchar index, uchar data)
        !           427: {
        !           428:        switch(port){
        !           429: 
        !           430:        case Seqx:
        !           431:        case Crtx:
        !           432:        case Grx:
        !           433:                /*
        !           434:                 * We could use an outport here, but some chips
        !           435:                 * (e.g. 86C928) have trouble with that for some
        !           436:                 * registers.
        !           437:                 */
        !           438:                outb(port, index);
        !           439:                outb(port+1, data);
        !           440:                break;
        !           441: 
        !           442:        case Attrx:
        !           443:                inb(Status1);
        !           444:                if(index < 0x10){
        !           445:                        outb(Attrx, index);
        !           446:                        outb(Attrx, data);
        !           447:                        inb(Status1);
        !           448:                        outb(Attrx, 0x20|index);
        !           449:                }
        !           450:                else{
        !           451:                        outb(Attrx, 0x20|index);
        !           452:                        outb(Attrx, data);
        !           453:                }
        !           454:                break;
        !           455: 
        !           456:        default:
        !           457:                return -1;
        !           458:        }
        !           459: 
        !           460:        return 0;
        !           461: }
        !           462: 
        !           463: /*
        !           464:  *  expand n bits of color to 32
        !           465:  */
        !           466: static ulong
        !           467: xnto32(uchar x, int n)
        !           468: {
        !           469:        int s;
        !           470:        ulong y;
        !           471: 
        !           472:        x &= (1<<n)-1;
        !           473:        y = 0;
        !           474:        for(s = 32 - n; s > 0; s -= n)
        !           475:                y |= x<<s;
        !           476:        if(s < 0)
        !           477:                y |= x>>(-s);
        !           478:        return y;
        !           479: }
        !           480: 
        !           481: /*
        !           482:  *  expand 3 and 6 bits of color to 32
        !           483:  */
        !           484: static ulong
        !           485: x3to32(uchar x)
        !           486: {
        !           487:        ulong y;
        !           488: 
        !           489:        x = x&7;
        !           490:        x= (x<<3)|x;
        !           491:        y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30));
        !           492:        return y;
        !           493: }
        !           494: static ulong
        !           495: x6to32(uchar x)
        !           496: {
        !           497:        ulong y;
        !           498: 
        !           499:        x = x&0x3f;
        !           500:        y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30));
        !           501:        return y;
        !           502: }
        !           503: 
        !           504: void
        !           505: setscreen(int maxx, int maxy, int ldepth)
        !           506: {
        !           507:        int len, vgamaxy, width, i, x, s;
        !           508:        ulong *p, *oldp;
        !           509: 
        !           510:        /* allocate a new soft bitmap area */
        !           511:        width = (maxx*(1<<ldepth))/32;
        !           512:        len = width * BY2WD * maxy;
        !           513:        p = xalloc(len);
        !           514:        if(p == 0)
        !           515:                error(Enobitstore);
        !           516:        memset(p, 0xff, len);
        !           517:        mbb = NULLMBB;
        !           518: 
        !           519:        /*
        !           520:         *  setup a bitmap for the new size
        !           521:         */
        !           522:        if(ldepth == 3)
        !           523:                vgascreen.ldepth = 3;
        !           524:        else
        !           525:                vgascreen.ldepth = 0;
        !           526:        vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32;
        !           527:        if(maxy > (64*1024)/(vgascreen.width*BY2WD))
        !           528:                vgamaxy = (64*1024)/(vgascreen.width*BY2WD);
        !           529:        else
        !           530:                vgamaxy = maxy;
        !           531:        vgascreen.base = (void*)SCREENMEM;
        !           532:        vgascreen.r.min = Pt(0, 0);
        !           533:        vgascreen.r.max = Pt(maxx, vgamaxy);
        !           534:        vgascreen.clipr = vgascreen.r;
        !           535: 
        !           536:        /*
        !           537:         *  setup new soft screen, free memory for old screen
        !           538:         */
        !           539:        oldp = gscreen.base;
        !           540:        s = splhi();
        !           541:        gscreen.ldepth = ldepth;
        !           542:        gscreen.width = width;
        !           543:        gscreen.r.min = Pt(0, 0);
        !           544:        gscreen.r.max = Pt(maxx, maxy);
        !           545:        gscreen.clipr = gscreen.r;
        !           546:        gscreen.base = p;
        !           547:        splx(s);
        !           548:        if(oldp)
        !           549:                xfree(oldp);
        !           550: 
        !           551:        /*
        !           552:         *  set depth of cursor backup area
        !           553:         */
        !           554:        bitdepth();
        !           555: 
        !           556:        /*
        !           557:         *  set string pointer to upper left
        !           558:         */
        !           559:        out.pos.x = MINX;
        !           560:        out.pos.y = 0;
        !           561:        out.bwid = defont0.info[' '].width;
        !           562: 
        !           563:        /*
        !           564:         *  default color map
        !           565:         */
        !           566:        switch(ldepth){
        !           567:        case 3:
        !           568:                for(i = 0; i < Pcolours; i++)
        !           569:                        setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1));
        !           570:                setcolor(0x55, xnto32(0x15, 6), xnto32(0x15, 6), xnto32(0x15, 6));
        !           571:                setcolor(0xaa, xnto32(0x2a, 6), xnto32(0x2a, 6), xnto32(0x2a, 6));
        !           572:                setcolor(0xff, xnto32(0x3f, 6), xnto32(0x3f, 6), xnto32(0x3f, 6));
        !           573:                break;
        !           574:        case 2:
        !           575:        case 1:
        !           576:        case 0:
        !           577:                gscreen.ldepth = 3;
        !           578:                for(i = 0; i < 16; i++){
        !           579:                        x = x6to32((i*63)/15);
        !           580:                        setcolor(i, x, x, x);
        !           581:                }
        !           582:                gscreen.ldepth = ldepth;
        !           583:                break;
        !           584:        }
        !           585: 
        !           586:        /*
        !           587:         * clear screen
        !           588:         */
        !           589:        cga = 0;
        !           590:        mbb = gscreen.r;
        !           591:        vgaupdate();
        !           592: }
        !           593: 
        !           594: void
        !           595: screeninit(void)
        !           596: {
        !           597:        int i;
        !           598:        ulong *l;
        !           599: 
        !           600:        /*
        !           601:         *  arrow is defined as a big endian
        !           602:         */
        !           603:        memmove(&arrow, &fatarrow, sizeof(fatarrow));
        !           604:        pixreverse(arrow.set, 2*16, 0);
        !           605:        pixreverse(arrow.clr, 2*16, 0);
        !           606: 
        !           607:        /*
        !           608:         *  swizzle the font longs.  we do both byte and bit swizzling
        !           609:         *  since the font is initialized with big endian longs.
        !           610:         */
        !           611:        defont = &defont0;
        !           612:        l = defont->bits->base;
        !           613:        for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++)
        !           614:                *l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);
        !           615:        pixreverse((uchar*)defont->bits->base,
        !           616:                defont->bits->width*BY2WD*Dy(defont->bits->r), 0);
        !           617: 
        !           618:        cga = 1;
        !           619:        memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
        !           620: }
        !           621: 
        !           622: /*
        !           623:  *  collect changes to the 'soft' screen
        !           624:  */
        !           625: void
        !           626: mbbrect(Rectangle r)
        !           627: {
        !           628:        if (r.min.x < mbb.min.x)
        !           629:                mbb.min.x = r.min.x;
        !           630:        if (r.min.y < mbb.min.y)
        !           631:                mbb.min.y = r.min.y;
        !           632:        if (r.max.x > mbb.max.x)
        !           633:                mbb.max.x = r.max.x;
        !           634:        if (r.max.y > mbb.max.y)
        !           635:                mbb.max.y = r.max.y;
        !           636:        mousescreenupdate();
        !           637: }
        !           638: 
        !           639: void
        !           640: mbbpt(Point p)
        !           641: {
        !           642:        if (p.x < mbb.min.x)
        !           643:                mbb.min.x = p.x;
        !           644:        if (p.y < mbb.min.y)
        !           645:                mbb.min.y = p.y;
        !           646:        if (p.x >= mbb.max.x)
        !           647:                mbb.max.x = p.x+1;
        !           648:        if (p.y >= mbb.max.y)
        !           649:                mbb.max.y = p.y+1;
        !           650: }
        !           651: 
        !           652: /*
        !           653:  *  paging routines for different cards
        !           654:  */
        !           655: static void
        !           656: nopage(int page)
        !           657: {
        !           658:        USED(page);
        !           659: }
        !           660: 
        !           661: /*
        !           662:  *  copy little endian soft screen to big endian hard screen
        !           663:  */
        !           664: static void
        !           665: vgaupdate(void)
        !           666: {
        !           667:        uchar *sp, *hp, *edisp;
        !           668:        int y, len, incs, inch, off, page;
        !           669:        Rectangle r;
        !           670:        void* (*f)(void*, void*, long);
        !           671: 
        !           672:        if(cga || vgachanging)
        !           673:                return;
        !           674: 
        !           675:        r = mbb;
        !           676:        mbb = NULLMBB;
        !           677: 
        !           678:        /* pad a few bits */
        !           679:        r.min.y -= 2;
        !           680:        r.max.y += 2;
        !           681: 
        !           682:        if(Dy(r) < 0)
        !           683:                return;
        !           684: 
        !           685:        if(r.min.x < 0)
        !           686:                r.min.x = 0;
        !           687:        if(r.min.y < 0)
        !           688:                r.min.y = 0;
        !           689:        if(r.max.x > gscreen.r.max.x)
        !           690:                r.max.x = gscreen.r.max.x;
        !           691:        if(r.max.y > gscreen.r.max.y)
        !           692:                r.max.y = gscreen.r.max.y;
        !           693: 
        !           694:        incs = gscreen.width * BY2WD;
        !           695:        inch = vgascreen.width * BY2WD;
        !           696: 
        !           697:        switch(gscreen.ldepth){
        !           698:        case 0:
        !           699:                r.min.x &= ~15;         /* 16 pixel allignment for l0update() */
        !           700:                f = l0update;
        !           701:                len = (r.max.x + 7)/8 - r.min.x/8;
        !           702:                if(len & 1)
        !           703:                        len++;          /* 16 bit allignment for l0update() */
        !           704:                break;
        !           705:        case 1:
        !           706:                r.min.x &= ~15;         /* 8 pixel allignment for l1update() */
        !           707:                f = l1update;
        !           708:                len = (r.max.x + 7)/8 - r.min.x/8;
        !           709:                if(len & 1)
        !           710:                        len++;          /* 8 pixel allignment for l1update() */
        !           711:                break;
        !           712:        case 2:
        !           713:                r.min.x &= ~7;          /* 8 pixel allignment for l2update() */
        !           714:                f = l2update;
        !           715:                len = (r.max.x + 7)/8 - r.min.x/8;
        !           716:                break;
        !           717:        case 3:
        !           718:                f = memmove;
        !           719:                len = r.max.x - r.min.x;
        !           720:                break;
        !           721:        default:
        !           722:                return;
        !           723:        }
        !           724:        if(len < 1)
        !           725:                return;
        !           726: 
        !           727:        off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth));
        !           728:        page = off>>16;
        !           729:        off &= (1<<16)-1;
        !           730:        hp = ((uchar*)vgascreen.base) + off;
        !           731:        off = r.min.y * gscreen.width * BY2WD
        !           732:                + (r.min.x>>(3 - gscreen.ldepth));
        !           733:        sp = ((uchar*)gscreen.base) + off;
        !           734: 
        !           735:        edisp = ((uchar*)vgascreen.base) + 64*1024;
        !           736:        vgac->page(page);
        !           737:        for(y = r.min.y; y < r.max.y; y++){
        !           738:                if(hp + inch < edisp){
        !           739:                        f(hp, sp, len);
        !           740:                        sp += incs;
        !           741:                        hp += inch;
        !           742:                } else {
        !           743:                        off = edisp - hp;
        !           744:                        if(off <= len){
        !           745:                                if(off > 0)
        !           746:                                        f(hp, sp, off);
        !           747:                                vgac->page(++page);
        !           748:                                if(len - off > 0)
        !           749:                                        f(vgascreen.base, sp+off, len - off);
        !           750:                        } else {
        !           751:                                f(hp, sp, len);
        !           752:                                vgac->page(++page);
        !           753:                        }
        !           754:                        sp += incs;
        !           755:                        hp += inch - 64*1024;
        !           756:                }
        !           757:        }
        !           758: }
        !           759: 
        !           760: void
        !           761: screenupdate(void)
        !           762: {
        !           763:        lock(&palettelock);
        !           764:        vgaupdate();
        !           765:        unlock(&palettelock);
        !           766: }
        !           767: 
        !           768: void
        !           769: mousescreenupdate(void)
        !           770: {
        !           771:        int x;
        !           772: 
        !           773:        if(canlock(&palettelock)){
        !           774:                x = spllo();
        !           775:                vgaupdate();
        !           776:                splx(x);
        !           777:                unlock(&palettelock);
        !           778:        }
        !           779: }
        !           780: 
        !           781: static int pos;
        !           782: 
        !           783: static void
        !           784: cgaregw(uchar index, uchar data)
        !           785: {
        !           786:        outb(0x03D4, index);
        !           787:        outb(0x03D4+1, data);
        !           788: }
        !           789: 
        !           790: static void
        !           791: movecursor(void)
        !           792: {
        !           793:        cgaregw(0x0E, (pos/2>>8) & 0xFF);
        !           794:        cgaregw(0x0F, pos/2 & 0xFF);
        !           795: }
        !           796: 
        !           797: static void
        !           798: cgascreenputc(int c)
        !           799: {
        !           800:        int i;
        !           801:        static int color;
        !           802: 
        !           803:        if(c == '\n'){
        !           804:                pos = pos/CGAWIDTH;
        !           805:                pos = (pos+1)*CGAWIDTH;
        !           806:        } else if(c == '\t'){
        !           807:                i = 8 - ((pos/2)&7);
        !           808:                while(i-->0)
        !           809:                        cgascreenputc(' ');
        !           810:        } else if(c == '\b'){
        !           811:                if(pos >= 2)
        !           812:                        pos -= 2;
        !           813:                cgascreenputc(' ');
        !           814:                pos -= 2;
        !           815:        } else {
        !           816:                CGASCREEN[pos++] = c;
        !           817:                CGASCREEN[pos++] = 2;   /* green on black */
        !           818:        }
        !           819:        if(pos >= CGAWIDTH*CGAHEIGHT){
        !           820:                memmove(CGASCREEN, &CGASCREEN[CGAWIDTH], CGAWIDTH*(CGAHEIGHT-1));
        !           821:                memset(&CGASCREEN[CGAWIDTH*(CGAHEIGHT-1)], 0, CGAWIDTH);
        !           822:                pos = CGAWIDTH*(CGAHEIGHT-1);
        !           823:        }
        !           824:        movecursor();
        !           825: }
        !           826: 
        !           827: void
        !           828: cgascreenputs(char *s, int n)
        !           829: {
        !           830:        while(n-- > 0)
        !           831:                cgascreenputc(*s++);
        !           832: }
        !           833: 
        !           834: void
        !           835: screenputnl(void)
        !           836: {
        !           837:        Rectangle r;
        !           838: 
        !           839:        out.pos.x = MINX;
        !           840:        out.pos.y += defont0.height;
        !           841:        if(out.pos.y > gscreen.r.max.y-defont0.height){
        !           842:                vgaupdate();
        !           843:                out.pos.y = gscreen.r.min.y;
        !           844:        }
        !           845:        r = Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height);
        !           846:        gbitblt(&gscreen, r.min, &gscreen, r, flipD[0]);
        !           847:        mbbrect(r);
        !           848:        vgaupdate();
        !           849: }
        !           850: 
        !           851: void
        !           852: screenputs(char *s, int n)
        !           853: {
        !           854:        Rune r;
        !           855:        int i;
        !           856:        char buf[4];
        !           857:        Rectangle rect;
        !           858: 
        !           859:        if(vgachanging)
        !           860:                return;
        !           861:        if(cga) {
        !           862:                cgascreenputs(s, n);
        !           863:                return;
        !           864:        }
        !           865: 
        !           866:        while(n > 0){
        !           867:                i = chartorune(&r, s);
        !           868:                if(i == 0){
        !           869:                        s++;
        !           870:                        --n;
        !           871:                        continue;
        !           872:                }
        !           873:                memmove(buf, s, i);
        !           874:                buf[i] = 0;
        !           875:                n -= i;
        !           876:                s += i;
        !           877:                if(r == '\n')
        !           878:                        screenputnl();
        !           879:                else if(r == '\t'){
        !           880:                        out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
        !           881:                        if(out.pos.x >= gscreen.r.max.x)
        !           882:                                screenputnl();
        !           883:                }else if(r == '\b'){
        !           884:                        if(out.pos.x >= out.bwid+MINX){
        !           885:                                out.pos.x -= out.bwid;
        !           886:                                gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]);
        !           887:                        }
        !           888:                        rect.min = Pt(out.pos.x, out.pos.y);
        !           889:                        rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height);
        !           890:                        mbbrect(rect);
        !           891:                }else{
        !           892:                        if(out.pos.x >= gscreen.r.max.x-out.bwid)
        !           893:                                screenputnl();
        !           894:                        rect.min = Pt(out.pos.x, out.pos.y);
        !           895:                        rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height);
        !           896:                        out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]);
        !           897:                        mbbrect(rect);
        !           898:                }
        !           899:        }
        !           900:        vgaupdate();
        !           901: }
        !           902: 
        !           903: int
        !           904: screenbits(void)
        !           905: {
        !           906:        return 1<<gscreen.ldepth;       /* bits per pixel */
        !           907: }
        !           908: 
        !           909: void
        !           910: getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
        !           911: {
        !           912:        p &= (1<<(1<<gscreen.ldepth))-1;
        !           913:        lock(&palettelock);
        !           914:        *pr = colormap[p][Pred];
        !           915:        *pg = colormap[p][Pgreen];
        !           916:        *pb = colormap[p][Pblue];
        !           917:        unlock(&palettelock);
        !           918: }
        !           919: 
        !           920: int
        !           921: setcolor(ulong p, ulong r, ulong g, ulong b)
        !           922: {
        !           923:        p &= (1<<(1<<gscreen.ldepth))-1;
        !           924:        lock(&palettelock);
        !           925:        colormap[p][Pred] = r;
        !           926:        colormap[p][Pgreen] = g;
        !           927:        colormap[p][Pblue] = b;
        !           928:        vgao(PaddrW, p);
        !           929:        vgao(Pdata, r>>(32-6));
        !           930:        vgao(Pdata, g>>(32-6));
        !           931:        vgao(Pdata, b>>(32-6));
        !           932:        unlock(&palettelock);
        !           933:        return ~0;
        !           934: }
        !           935: 
        !           936: int
        !           937: hwgcmove(Point p)
        !           938: {
        !           939:        if(hwgc)
        !           940:                return (*hwgc->move)(p);
        !           941:        return 0;
        !           942: }
        !           943: 
        !           944: void
        !           945: setcursor(Cursor *curs)
        !           946: {
        !           947:        uchar *p;
        !           948:        int i;
        !           949:        extern GBitmap set, clr;
        !           950: 
        !           951:        if(hwgc)
        !           952:                (*hwgc->load)(curs);
        !           953:        else for(i=0; i<16; i++){
        !           954:                p = (uchar*)&set.base[i];
        !           955:                *p = curs->set[2*i];
        !           956:                *(p+1) = curs->set[2*i+1];
        !           957:                p = (uchar*)&clr.base[i];
        !           958:                *p = curs->clr[2*i];
        !           959:                *(p+1) = curs->clr[2*i+1];
        !           960:                memmove(&curcursor, curs, sizeof(Cursor));
        !           961:        }
        !           962: }
        !           963: 
        !           964: void
        !           965: addhwgclink(Hwgc *hwgcp)
        !           966: {
        !           967:        hwgcp->link = hwgctlr;
        !           968:        hwgctlr = hwgcp;
        !           969: }
        !           970: 
        !           971: void
        !           972: addvgaclink(Vgac *vgacp)
        !           973: {
        !           974:        vgacp->link = vgactlr;
        !           975:        vgactlr = vgacp;
        !           976: }
        !           977: 
        !           978: /*
        !           979:  *  Table for separating and reversing bits in a ldepth 1 bitmap.
        !           980:  *  This aids in coverting a little endian ldepth 1 bitmap into the
        !           981:  *  2 big-endian ldepth 0 bitmaps used for the VGA bit planes.
        !           982:  *
        !           983:  *     if the bits in uchar x are labeled
        !           984:  *             76543210
        !           985:  *     then l1revsep[x] yields a ushort with bits
        !           986:  *             ________1357________0246
        !           987:  *     where _ represents a bit whose value is 0.
        !           988:  *
        !           989:  *  This table is used by l1update() in l.s.  l1update is implemented
        !           990:  *  in assembler for speed.
        !           991:  *
        !           992:  */
        !           993: ulong l1revsep[] = {
        !           994:  0x00000, 0x00008, 0x80000, 0x80008, 0x00004, 0x0000c, 0x80004, 0x8000c,
        !           995:  0x40000, 0x40008, 0xc0000, 0xc0008, 0x40004, 0x4000c, 0xc0004, 0xc000c,
        !           996:  0x00002, 0x0000a, 0x80002, 0x8000a, 0x00006, 0x0000e, 0x80006, 0x8000e,
        !           997:  0x40002, 0x4000a, 0xc0002, 0xc000a, 0x40006, 0x4000e, 0xc0006, 0xc000e,
        !           998:  0x20000, 0x20008, 0xa0000, 0xa0008, 0x20004, 0x2000c, 0xa0004, 0xa000c,
        !           999:  0x60000, 0x60008, 0xe0000, 0xe0008, 0x60004, 0x6000c, 0xe0004, 0xe000c,
        !          1000:  0x20002, 0x2000a, 0xa0002, 0xa000a, 0x20006, 0x2000e, 0xa0006, 0xa000e,
        !          1001:  0x60002, 0x6000a, 0xe0002, 0xe000a, 0x60006, 0x6000e, 0xe0006, 0xe000e,
        !          1002:  0x00001, 0x00009, 0x80001, 0x80009, 0x00005, 0x0000d, 0x80005, 0x8000d,
        !          1003:  0x40001, 0x40009, 0xc0001, 0xc0009, 0x40005, 0x4000d, 0xc0005, 0xc000d,
        !          1004:  0x00003, 0x0000b, 0x80003, 0x8000b, 0x00007, 0x0000f, 0x80007, 0x8000f,
        !          1005:  0x40003, 0x4000b, 0xc0003, 0xc000b, 0x40007, 0x4000f, 0xc0007, 0xc000f,
        !          1006:  0x20001, 0x20009, 0xa0001, 0xa0009, 0x20005, 0x2000d, 0xa0005, 0xa000d,
        !          1007:  0x60001, 0x60009, 0xe0001, 0xe0009, 0x60005, 0x6000d, 0xe0005, 0xe000d,
        !          1008:  0x20003, 0x2000b, 0xa0003, 0xa000b, 0x20007, 0x2000f, 0xa0007, 0xa000f,
        !          1009:  0x60003, 0x6000b, 0xe0003, 0xe000b, 0x60007, 0x6000f, 0xe0007, 0xe000f,
        !          1010:  0x10000, 0x10008, 0x90000, 0x90008, 0x10004, 0x1000c, 0x90004, 0x9000c,
        !          1011:  0x50000, 0x50008, 0xd0000, 0xd0008, 0x50004, 0x5000c, 0xd0004, 0xd000c,
        !          1012:  0x10002, 0x1000a, 0x90002, 0x9000a, 0x10006, 0x1000e, 0x90006, 0x9000e,
        !          1013:  0x50002, 0x5000a, 0xd0002, 0xd000a, 0x50006, 0x5000e, 0xd0006, 0xd000e,
        !          1014:  0x30000, 0x30008, 0xb0000, 0xb0008, 0x30004, 0x3000c, 0xb0004, 0xb000c,
        !          1015:  0x70000, 0x70008, 0xf0000, 0xf0008, 0x70004, 0x7000c, 0xf0004, 0xf000c,
        !          1016:  0x30002, 0x3000a, 0xb0002, 0xb000a, 0x30006, 0x3000e, 0xb0006, 0xb000e,
        !          1017:  0x70002, 0x7000a, 0xf0002, 0xf000a, 0x70006, 0x7000e, 0xf0006, 0xf000e,
        !          1018:  0x10001, 0x10009, 0x90001, 0x90009, 0x10005, 0x1000d, 0x90005, 0x9000d,
        !          1019:  0x50001, 0x50009, 0xd0001, 0xd0009, 0x50005, 0x5000d, 0xd0005, 0xd000d,
        !          1020:  0x10003, 0x1000b, 0x90003, 0x9000b, 0x10007, 0x1000f, 0x90007, 0x9000f,
        !          1021:  0x50003, 0x5000b, 0xd0003, 0xd000b, 0x50007, 0x5000f, 0xd0007, 0xd000f,
        !          1022:  0x30001, 0x30009, 0xb0001, 0xb0009, 0x30005, 0x3000d, 0xb0005, 0xb000d,
        !          1023:  0x70001, 0x70009, 0xf0001, 0xf0009, 0x70005, 0x7000d, 0xf0005, 0xf000d,
        !          1024:  0x30003, 0x3000b, 0xb0003, 0xb000b, 0x30007, 0x3000f, 0xb0007, 0xb000f,
        !          1025:  0x70003, 0x7000b, 0xf0003, 0xf000b, 0x70007, 0x7000f, 0xf0007, 0xf000f,
        !          1026: };
        !          1027: 
        !          1028: /*
        !          1029:  *  Table for separating and reversing bits in a ldepth 2 bitmap.
        !          1030:  *  This aids in coverting a little endian ldepth 1 bitmap into the
        !          1031:  *  4 big-endian ldepth 0 bitmaps used for the VGA bit planes.
        !          1032:  *
        !          1033:  *     if the bits in uchar x are labeled
        !          1034:  *             76543210
        !          1035:  *     then l1revsep[x] yields a ushort with bits
        !          1036:  *             ______37______26______15______04
        !          1037:  *     where _ represents a bit whose value is 0.
        !          1038:  *
        !          1039:  *  This table is used by l2update() in l.s.  l2update is implemented
        !          1040:  *  in assembler for speed.
        !          1041:  *
        !          1042:  */
        !          1043: ulong l2revsep[] = {
        !          1044:  0x0000000, 0x0000002, 0x0000200, 0x0000202, 0x0020000, 0x0020002, 0x0020200, 0x0020202,
        !          1045:  0x2000000, 0x2000002, 0x2000200, 0x2000202, 0x2020000, 0x2020002, 0x2020200, 0x2020202,
        !          1046:  0x0000001, 0x0000003, 0x0000201, 0x0000203, 0x0020001, 0x0020003, 0x0020201, 0x0020203,
        !          1047:  0x2000001, 0x2000003, 0x2000201, 0x2000203, 0x2020001, 0x2020003, 0x2020201, 0x2020203,
        !          1048:  0x0000100, 0x0000102, 0x0000300, 0x0000302, 0x0020100, 0x0020102, 0x0020300, 0x0020302,
        !          1049:  0x2000100, 0x2000102, 0x2000300, 0x2000302, 0x2020100, 0x2020102, 0x2020300, 0x2020302,
        !          1050:  0x0000101, 0x0000103, 0x0000301, 0x0000303, 0x0020101, 0x0020103, 0x0020301, 0x0020303,
        !          1051:  0x2000101, 0x2000103, 0x2000301, 0x2000303, 0x2020101, 0x2020103, 0x2020301, 0x2020303,
        !          1052:  0x0010000, 0x0010002, 0x0010200, 0x0010202, 0x0030000, 0x0030002, 0x0030200, 0x0030202,
        !          1053:  0x2010000, 0x2010002, 0x2010200, 0x2010202, 0x2030000, 0x2030002, 0x2030200, 0x2030202,
        !          1054:  0x0010001, 0x0010003, 0x0010201, 0x0010203, 0x0030001, 0x0030003, 0x0030201, 0x0030203,
        !          1055:  0x2010001, 0x2010003, 0x2010201, 0x2010203, 0x2030001, 0x2030003, 0x2030201, 0x2030203,
        !          1056:  0x0010100, 0x0010102, 0x0010300, 0x0010302, 0x0030100, 0x0030102, 0x0030300, 0x0030302,
        !          1057:  0x2010100, 0x2010102, 0x2010300, 0x2010302, 0x2030100, 0x2030102, 0x2030300, 0x2030302,
        !          1058:  0x0010101, 0x0010103, 0x0010301, 0x0010303, 0x0030101, 0x0030103, 0x0030301, 0x0030303,
        !          1059:  0x2010101, 0x2010103, 0x2010301, 0x2010303, 0x2030101, 0x2030103, 0x2030301, 0x2030303,
        !          1060:  0x1000000, 0x1000002, 0x1000200, 0x1000202, 0x1020000, 0x1020002, 0x1020200, 0x1020202,
        !          1061:  0x3000000, 0x3000002, 0x3000200, 0x3000202, 0x3020000, 0x3020002, 0x3020200, 0x3020202,
        !          1062:  0x1000001, 0x1000003, 0x1000201, 0x1000203, 0x1020001, 0x1020003, 0x1020201, 0x1020203,
        !          1063:  0x3000001, 0x3000003, 0x3000201, 0x3000203, 0x3020001, 0x3020003, 0x3020201, 0x3020203,
        !          1064:  0x1000100, 0x1000102, 0x1000300, 0x1000302, 0x1020100, 0x1020102, 0x1020300, 0x1020302,
        !          1065:  0x3000100, 0x3000102, 0x3000300, 0x3000302, 0x3020100, 0x3020102, 0x3020300, 0x3020302,
        !          1066:  0x1000101, 0x1000103, 0x1000301, 0x1000303, 0x1020101, 0x1020103, 0x1020301, 0x1020303,
        !          1067:  0x3000101, 0x3000103, 0x3000301, 0x3000303, 0x3020101, 0x3020103, 0x3020301, 0x3020303,
        !          1068:  0x1010000, 0x1010002, 0x1010200, 0x1010202, 0x1030000, 0x1030002, 0x1030200, 0x1030202,
        !          1069:  0x3010000, 0x3010002, 0x3010200, 0x3010202, 0x3030000, 0x3030002, 0x3030200, 0x3030202,
        !          1070:  0x1010001, 0x1010003, 0x1010201, 0x1010203, 0x1030001, 0x1030003, 0x1030201, 0x1030203,
        !          1071:  0x3010001, 0x3010003, 0x3010201, 0x3010203, 0x3030001, 0x3030003, 0x3030201, 0x3030203,
        !          1072:  0x1010100, 0x1010102, 0x1010300, 0x1010302, 0x1030100, 0x1030102, 0x1030300, 0x1030302,
        !          1073:  0x3010100, 0x3010102, 0x3010300, 0x3010302, 0x3030100, 0x3030102, 0x3030300, 0x3030302,
        !          1074:  0x1010101, 0x1010103, 0x1010301, 0x1010303, 0x1030101, 0x1030103, 0x1030301, 0x1030303,
        !          1075:  0x3010101, 0x3010103, 0x3010301, 0x3010303, 0x3030101, 0x3030103, 0x3030301, 0x3030303,
        !          1076: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.