ken@turtleva.UUCP (Ken Turkowski) (12/22/83)
echo x - drivers/fbutil.c cat >drivers/fbutil.c <<'!Funky!Stuff!' /* fbutil.c 8/28/80 - 10-bit frame buffer utilities */ #define FBON 0x10 /* display on/off bit */ #define CRSON 0x08 /* cursor on/off bit */ #define CRSRED 0x04 /* cursor red on/off */ #define CRSGRN 0x02 /* " green " */ #define CRSBLU 0x01 /* " blue " */ #define PXBASE 0x34C0 /* pixel address base (16 MSBs) */ #define PBASE1 0x24C0 /* " (non-incrementing) */ #define PLBASE 0x1041 /* pallette address base (16 MSBs) */ #define CRSADR 0x0040 /* cursor address register in FB */ #define CRSADRL 0x8000 #define CTLADR 0x0040 /* control register address in FB */ #define CTLADRL 0x4000 #define PIXMASK0 0xFFFFFC00 /* masks for individual pixel writes */ #define PIXMASK1 0xFFF003FF #define PIXMASK2 0xC00FFFFF static short fd = 0; /* 'file descriptor' points ioctl to FB */ static short FBquad = -1; /* display quadrant being used */ static short flag,OldX,OldY,LnLngth; static short Buf[16]; static long PakdBuf[5]; fbinit() /* frame buffer initialization */ { char reply[3]; short quad; do { printf(" which frame buffer quadrant? : "); scanf("%d",&quad); fbquad(quad); if (FBquad < 0) { printf(" want to try another? : "); scanf("%1s",reply); } } while ((fd <= 0) && (reply[0] != 'n') && (reply[0] != 'N') ); } fbquad(quad) /* initialization with quadrant as argument */ short quad; { short mode; if (FBquad > -1) close(fd); FBquad = quad; switch ( FBquad ) { case 0: { fd = open("/dev/fb0",mode); break; } case 1: { fd = open("/dev/fb1",mode); break; } case 2: { fd = open("/dev/fb2",mode); break; } case 3: { fd = open("/dev/fb3",mode); break; } case 4: { fd = open("/dev/fb4",mode); break; } } if ( fd < 0 ) FBquad = -1; if (FBquad < 0) { printf(" FB quadrant busy "); fd = 0; return -1; } else { LnLngth = (FBquad > 0) ? 256 : 512; return 0; } } fbrelease() /* release frame buffer without shutting off (for another task) */ { long array; array = FBquad; ioctl(fd,101,&array,flag); FBquad = -1; } fbclose() /* close frame buffer for another process to use */ { close(fd); FBquad = -1; } fbwrite(X,Y,buffer,numpix) /* write from 'buffer' to FB */ short X,Y,numpix,buffer[]; { long array[4]; short i,j,Xlsb,lupend; if (fd <= 0) { printf(" please call fbinit!!\n"); return; } if (FBquad > 0) { quadwrite(FBquad,X,Y,buffer,numpix); return; /* write restricted to quadrant */ } Xlsb = (X & 15); if ((numpix == 1) && ((Xlsb) != 15)) /* for single pixel */ { long word; array[0] = (Y << 9) | ((X & 0x1F0) | ((Xlsb)/3)); array[1] = PBASE1 | (Y >> 7); ioctl(fd,10,array,flag); /* write to address regs. */ array[0] = 1; array[1] = (long) &word; /* set pointer to 'word' */ ioctl(fd,13,array,flag); /* read data registers once */ switch (Xlsb % 3) { case 0: { word = (word & PIXMASK0) | buffer[0] ; break; } case 1: { word = (word & PIXMASK1) | (buffer[0]<<10); break; } case 2: { word = (word & PIXMASK2) | (buffer[0]<<20); break; } } ioctl(fd,12,array,flag); /* write to data registers */ if ((OldX == (X & 0x1F0)) && (OldY == Y)) Buf[Xlsb] = buffer[0]; return; } for (i=0; i<numpix; ) /* read-modify-write pixel blocks */ { if (((numpix-i < 16) || ((Xlsb) != 0)) && /* if partial block */ ((OldY != Y) || (OldX != (X & 0x1F0)))) { array[0] = X; array[1] = Y; array[2] = 1; array[3] = (long) PakdBuf; /* set pointer to PakdBuf */ ioctl(fd,3,array,flag); /* read a packed block */ OldY = Y; OldX = X & 0x1F0; unpack(PakdBuf,Buf); } lupend = 16 < (numpix-i+Xlsb) ? 16 : (numpix-i+Xlsb); /* set up loop */ for (j=Xlsb; j<lupend; j++) Buf[j] = buffer[i++]; packup(Buf,PakdBuf); array[0] = X; array[1] = Y; array[2] = 1; array[3] = (long) PakdBuf; ioctl(fd,2,array,flag); /* write packed block */ X = (X & 0x1F0) + 16; Xlsb = 0; /* clear lower bits of X and incr. */ if (X > 511) { Y++; X = 0; } /* update Y if nec. */ } } /* Caution!! this doesn't protect quadrants. Do not use casually */ fbpkdwr(X,Y,buffer,numblks) /* write packed blocks to FB */ short X,Y,numblks; long buffer[]; { long array[4]; array[0] = X; array[1] = Y; array[2] = numblks; array[3] = (long) buffer; ioctl(fd,2,array,flag); /* write out blocks */ } quadwrite(quad,X,Y,buffer,numpix) /* restrict write to quadrant */ short quad,X,Y,numpix,buffer[]; { short xtrans,ytrans,ptrans,tbuffer[256]; switch (FBquad) { case 1: { xtrans = 256; ytrans = 0; ptrans = 0; break; } case 2: { xtrans = 0; ytrans = 0; ptrans = 256; break; } case 3: { xtrans = 0; ytrans = 243; ptrans = 512; break; } case 4: { xtrans = 256; ytrans = 243; ptrans = 768; break; } } FBquad=0; /* reset FBquad temporarily to allow calls to fbwrite */ if ((X < 256) && (Y < 243) && (X >= 0) && (Y >= 0)) { short i; if (( X + numpix) <= 256) { for (i=0; i<numpix; i++) tbuffer[i] = buffer[i] + ptrans; fbwrite(X+xtrans,Y+ytrans,tbuffer,numpix); } else { long bufpos; for (i=0; i<(256-X); i++) tbuffer[i] = buffer[i] + ptrans; fbwrite(X+xtrans,Y+ytrans,tbuffer,256-X); numpix-=256-X; bufpos = 256-X; while ((numpix > 256) && (++Y < 243)) { for (i=0; i<256; i++) tbuffer[i] = buffer[i+bufpos] + ptrans; fbwrite(X+xtrans,Y+ytrans,tbuffer,256); numpix-=256; bufpos+=256; } if (++Y < 243) { for (i=0; i<numpix; i++) tbuffer[i] = buffer[i+bufpos] + ptrans; fbwrite(X+xtrans,Y+ytrans,tbuffer,numpix); } } } else printf(" scissoring!! "); FBquad = quad; } fbrun(X,Y,color,numpix) /* output constant run */ short X,Y,numpix,color; { short i,Buf[16],Xlsb,FBtmp,Xleft; long PakdBuf[5]; FBtmp = FBquad; Xleft = 0; if(FBquad > 0) { switch (FBquad) { case 1: { X += 256; Xleft = 256; break; } case 2: { color += 256; break; } case 3: { Y += 243; color += 512; break; } case 4: { X += 256; Y += 243; color += 768; Xleft = 256; break;} } FBquad = 0; } for (i=0; i<16; i++) Buf[i] = color; if (numpix <= 16) { fbwrite(X,Y,Buf,numpix); FBquad = FBtmp; return; } packup(Buf,PakdBuf); Xlsb = X & 15; if (Xlsb > 0) { fbwrite(X,Y,Buf,16-Xlsb); /* write up to first block end */ X += 16-Xlsb; numpix -= (16 - Xlsb); } while (numpix > 15) /* output blocks of 16 pixels */ { fbpkdwr(X,Y,PakdBuf,1); X += 16; numpix -= 16; if (X >= LnLngth) { X = Xleft; Y++; } /* spill over to next line */ } if (numpix > 0) fbwrite(X,Y,Buf,numpix); /* trailing partial blk. */ FBquad = FBtmp; } fbread(X,Y,buffer,numpix) /* read from FB to 'buffer' */ short X,Y,numpix,buffer[]; { long array[5]; short i,j,lupend; if (fd <= 0) { printf(" please call fbinit!!\n"); return; } if (FBquad > 0) { quadread(FBquad,X,Y,buffer,numpix); return; /* read restricted to quadrant */ } for (i=0; i<numpix; ) /* read 16-pixel blocks */ { if ((OldY != Y) || (OldX != (X & 0x1F0))) { array[0] = X; array[1] = Y; array[2] = 1; array[3] = (long) PakdBuf; /* set pointer to PakdBuf */ ioctl(fd,3,array,flag); /* read a packed block */ OldY = Y; OldX = X & 0x1F0; unpack(PakdBuf,Buf); } /* loop runs to end of unpacked block or end of request */ lupend = 16 < (numpix - i + (X&15)) ? 16 : (numpix-i)+(X&15); for (j=(X&15); j<lupend; j++) buffer[i++] = Buf[j]; X = (X&0x1F0) + 16; /* clear lower bits of X and incr. */ if (X > 511) { Y++; X = 0; } /* update Y if nec. */ } } /* Caution!! this doesn't protect quadrants. Do not use casually */ fbpkdrd(X,Y,buffer,numblks) /* read packed blocks */ short X,Y,numblks; long buffer[]; { long array[4]; array[0] = X; array[1] = Y; array[2] = numblks; array[3] = (long) buffer; ioctl(fd,3,array,flag); /* read in blocks */ } quadread(quad,X,Y,buffer,numpix) /* restrict read to quadrant */ short X,Y,numpix,quad,buffer[]; { short i,xtrans,ytrans,ptrans; switch (FBquad) { case 1: { xtrans = 256; ytrans = 0; ptrans = 0; break; } case 2: { xtrans = 0; ytrans = 0; ptrans = 256; break; } case 3: { xtrans = 0; ytrans = 243; ptrans = 512; break; } case 4: { xtrans = 256; ytrans = 243; ptrans = 768; break; } } FBquad=0; /* reset FBquad temporarily to allow calls to fbwrite */ if ((X < 256) && (Y < 243) && (X >= 0) && (Y >= 0)) { if (( X + numpix) <= 256) fbread(X+xtrans,Y+ytrans,buffer,numpix); else { long bufpos,pixleft; fbread(X+xtrans,Y+ytrans,buffer,256-X); pixleft = numpix - (256-X); bufpos = 256-X; while ((pixleft > 256) && (++Y < 243)) { fbread(X+xtrans,Y+ytrans,&buffer[bufpos],256); pixleft-=256; bufpos+=256; } if (++Y < 243) fbread(X+xtrans,Y+ytrans,&buffer[bufpos],pixleft); } for (i=0; i<numpix; i++) buffer[i] -= ptrans; /* offset color */ } else printf(" scissoring!! "); FBquad = quad; } packup(Buf,PakdBuf) long PakdBuf[5]; short Buf[16]; { /* pack up complete block of 16 10-bit pixels */ PakdBuf[0] = Buf[15] << 30 | Buf[2] << 20 | Buf[1] << 10 | Buf[0]; PakdBuf[1] = (Buf[15]&0x3FC) << 28 | Buf[5] << 20 | Buf[4] << 10 | Buf[3]; PakdBuf[2] = (Buf[15]&0x3F0) << 26 | Buf[8] << 20 | Buf[7] << 10 | Buf[6]; PakdBuf[3] = (Buf[15]&0x3C0) << 24 | Buf[11]<< 20 | Buf[10]<< 10 | Buf[9]; PakdBuf[4] = (Buf[15]&0x300) << 22 | Buf[14]<< 20 | Buf[13]<< 10 | Buf[12]; } unpack(PakdBuf,Buf) long PakdBuf[5]; short Buf[16]; { /* unpack complete block */ short i,j; i = 0; for (j=0; j<15; j+=3) Buf[j] = PakdBuf[i++] & 1023; i = 0; for (j=1; j<15; j+=3) Buf[j] = (PakdBuf[i++] >> 10) & 1023; i = 0; for (j=2; j<15; j+=3) Buf[j] = (PakdBuf[i++] >> 20) & 1023; Buf[15] = ((PakdBuf[0] >> 30)&3) | (((PakdBuf[1] >> 30)&3) << 2) | (((PakdBuf[2] >> 30)&3) << 4) | (((PakdBuf[3] >> 30)&3) << 6) | (((PakdBuf[4] >> 30)&3) << 8); } fbpalr(buffer) /* read back whole pallette */ short buffer[]; { long array[4]; short i; switch (FBquad) { case 0: { array[0] = 0; array[1] = PLBASE; array[2] =1024; break; } case 1: { array[0] = 0; array[1] = PLBASE; array[2] = 256; break; } case 2: { array[0] = 0x1000; array[1] = PLBASE; array[2] = 256; break; } case 3: { array[0] = 0x2000; array[1] = PLBASE; array[2] = 256; break; } case 4: { array[0] = 0x3000; array[1] = PLBASE; array[2] = 256; break; } } array[3] = (long) buffer; /* set up pointer to buffer */ ioctl(fd,10,array,flag); /* load address regs. */ ioctl(fd,13,&array[2],flag); /* read pallette */ } fbpalw(buffer) /* write entire pallette */ short buffer[]; { long array[4]; switch (FBquad) { case 0: { array[0] = 0; array[1] = PLBASE; array[2] = 1024; break;} case 1: { array[0] = 0; array[1] = PLBASE; array[2] = 256; break; } case 2: { array[0] = 0x1000; array[1] = PLBASE; array[2] = 256; break; } case 3: { array[0] = 0x2000; array[1] = PLBASE; array[2] = 256; break; } case 4: { array[0] = 0x3000; array[1] = PLBASE; array[2] = 256; break; } } ioctl(fd,10,array,flag); /* load address regs. */ array[3] = (long) buffer; /* set up pointer to buffer */ ioctl(fd,12,&array[2],flag); /* write pallette */ } fbclear(color) short color; { short i,j,Buf[16],X,Y,lupend; long array[4],PakdBuf[160]; switch (FBquad) { case 0: { X = 0; Y = 0; break; } case 1: { X = 256; Y = 0; break; } case 2: { X = 0; Y = 0; color += 256; break; } case 3: { X = 0; Y = 243; color += 512; break; } case 4: { X = 256; Y = 243; color += 768; break; } } for (i=0; i<16; i++) Buf[i] = color; packup(Buf,PakdBuf); lupend = (FBquad > 0) ? 80 : 160 ; /* resolution*5/16 */ for (i=5; i<lupend; ) /* copy PakdBuf to whole line */ for (j=0; j<5; j++) PakdBuf[i++] = PakdBuf[j]; array[0] = X; array[1] = Y; array[2] = lupend/5; array[3] = (long) PakdBuf; lupend = (FBquad > 0) ? 243 : 486 ; for (i=0; i<lupend; i++) { ioctl(fd,2,array,flag); array[1]++; } } !Funky!Stuff!