Medium frame buffer driver: drivers/fbutil.c
Ken Turkowski
ken at turtleva.UUCP
Thu Dec 22 16:01:03 AEST 1983
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!
More information about the Comp.sources.unix
mailing list