Annotation of lucent/sys/src/9/pc/devvga.c, revision 1.1.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.