[net.sources] Medium frame buffer driver: drivers/fbutil.c

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!