251 lines
4.1 KiB
C
251 lines
4.1 KiB
C
/*
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
* in the LICENSE file.
|
|
*/
|
|
|
|
#include "u.h"
|
|
#include "../port/lib.h"
|
|
#include "mem.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
|
|
enum {
|
|
Black = 0x00,
|
|
Blue = 0x01,
|
|
Green = 0x02,
|
|
Cyan = 0x03,
|
|
Red = 0x04,
|
|
Magenta = 0x05,
|
|
Brown = 0x06,
|
|
Grey = 0x07,
|
|
|
|
Bright = 0x08,
|
|
Blinking = 0x80,
|
|
|
|
Attr = (Black<<4)|Grey, /* (background<<4)|foreground */
|
|
};
|
|
|
|
enum {
|
|
Index = 0x3d4,
|
|
Data = Index+1,
|
|
|
|
Width = 80*2,
|
|
Height = 25,
|
|
|
|
Poststrlen = 0,
|
|
Postcodelen = 2,
|
|
Postlen = Poststrlen+Postcodelen,
|
|
|
|
Cgasize = 16384,
|
|
};
|
|
|
|
#define CGA (BIOSSEG(0xb800))
|
|
|
|
static Lock cgalock;
|
|
static int cgapos;
|
|
static int cgainitdone;
|
|
|
|
static int
|
|
cgaregr(int index)
|
|
{
|
|
outb(Index, index);
|
|
return inb(Data) & 0xff;
|
|
}
|
|
|
|
static void
|
|
cgaregw(int index, int data)
|
|
{
|
|
outb(Index, index);
|
|
outb(Data, data);
|
|
}
|
|
|
|
static void
|
|
cgablinkoff(void)
|
|
{
|
|
cgaregw(0x0a, 1<<5);
|
|
}
|
|
|
|
static void
|
|
cgacursor(void)
|
|
{
|
|
uint8_t *cga;
|
|
|
|
cgaregw(0x0e, (cgapos/2>>8) & 0xff);
|
|
cgaregw(0x0f, cgapos/2 & 0xff);
|
|
|
|
cga = CGA;
|
|
cga[cgapos+1] = Attr;
|
|
}
|
|
|
|
/*
|
|
* extern, so we could use it to debug things like
|
|
* lock() if necessary.
|
|
*/
|
|
void
|
|
cgaputc(int c)
|
|
{
|
|
int i;
|
|
uint8_t *cga, *p;
|
|
|
|
cga = CGA;
|
|
|
|
if(c == '\n'){
|
|
cgapos = cgapos/Width;
|
|
cgapos = (cgapos+1)*Width;
|
|
}
|
|
else if(c == '\t'){
|
|
i = 8 - ((cgapos/2)&7);
|
|
while(i-- > 0)
|
|
cgaputc(' ');
|
|
}
|
|
else if(c == '\b'){
|
|
if(cgapos >= 2)
|
|
cgapos -= 2;
|
|
cgaputc(' ');
|
|
cgapos -= 2;
|
|
}
|
|
else{
|
|
cga[cgapos++] = c;
|
|
cga[cgapos++] = Attr;
|
|
}
|
|
if(cgapos >= (Width*Height)-Postlen*2){
|
|
jehanne_memmove(cga, &cga[Width], Width*(Height-1));
|
|
p = &cga[Width*(Height-1)-Postlen*2];
|
|
for(i = 0; i < Width/2; i++){
|
|
*p++ = ' ';
|
|
*p++ = Attr;
|
|
}
|
|
cgapos -= Width;
|
|
}
|
|
cgacursor();
|
|
}
|
|
|
|
int
|
|
cgaprint(int off, char *fmt, ...)
|
|
{
|
|
va_list va;
|
|
char buf[128];
|
|
uint8_t *cga;
|
|
int i, n;
|
|
|
|
va_start(va, fmt);
|
|
n = jehanne_vsnprint(buf, sizeof buf, fmt, va);
|
|
va_end(va);
|
|
|
|
cga = CGA;
|
|
for(i = 0; (2*(i+off))+1 < Cgasize && i < n; i++){
|
|
cga[2*(i+off)+0] = buf[i];
|
|
cga[2*(i+off)+1] = Attr;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
int
|
|
cgaclearln(int off, int c)
|
|
{
|
|
uint8_t *cga;
|
|
int i;
|
|
|
|
cga = CGA;
|
|
for(i = off; (2*i)+1 < Cgasize && i%80 != 0; i++){
|
|
cga[2*i+0] = c;
|
|
cga[2*i+1] = Attr;
|
|
}
|
|
return i-off;
|
|
}
|
|
|
|
/*
|
|
* debug
|
|
*/
|
|
void
|
|
cgaprinthex(uintptr_t x)
|
|
{
|
|
char str[30];
|
|
char *s;
|
|
static char dig[] = "0123456789abcdef";
|
|
|
|
str[29] = 0;
|
|
s = &str[29];
|
|
while(x != 0){
|
|
*--s = dig[x&0xF];
|
|
x >>= 4;
|
|
}
|
|
while(*s != 0)
|
|
cgaputc(*s++);
|
|
cgaputc('\n');
|
|
}
|
|
|
|
static void
|
|
cgaconsputs(char* s, int n)
|
|
{
|
|
ilock(&cgalock);
|
|
while(n-- > 0)
|
|
cgaputc(*s++);
|
|
iunlock(&cgalock);
|
|
}
|
|
|
|
void
|
|
cgapost(int code)
|
|
{
|
|
uint8_t *cga;
|
|
|
|
static char hex[] = "0123456789ABCDEF";
|
|
|
|
cga = CGA;
|
|
cga[Width*Height-Postcodelen*2] = hex[(code>>4) & 0x0f];
|
|
cga[Width*Height-Postcodelen*2+1] = Attr;
|
|
cga[Width*Height-Postcodelen*2+2] = hex[code & 0x0f];
|
|
cga[Width*Height-Postcodelen*2+3] = Attr;
|
|
}
|
|
|
|
static long
|
|
cgaread(Chan* c, void *vbuf, long len, int64_t off)
|
|
{
|
|
uint8_t *cga;
|
|
extern int panicking;
|
|
if(panicking)
|
|
error("cgaread: kernel panic");
|
|
if(off < 0 || off > Cgasize)
|
|
error("cgaread: offset out of bounds");
|
|
if(off+len > Cgasize)
|
|
len = Cgasize - off;
|
|
cga = CGA;
|
|
jehanne_memmove(vbuf, cga + off, len);
|
|
return len;
|
|
}
|
|
|
|
static long
|
|
cgawrite(Chan* c, void *vbuf, long len, int64_t off)
|
|
{
|
|
uint8_t *cga;
|
|
extern int panicking;
|
|
if(panicking)
|
|
error("cgawrite: kernel panic");
|
|
if(off < 0 || off > Cgasize)
|
|
error("cgawrite: offset out of bounds");
|
|
if(off+len > Cgasize)
|
|
len = Cgasize - off;
|
|
cga = CGA;
|
|
jehanne_memmove(cga + off, vbuf, len);
|
|
return len;
|
|
}
|
|
|
|
void
|
|
screen_init(void)
|
|
{
|
|
ilock(&cgalock);
|
|
|
|
cgapos = cgaregr(0x0e)<<8;
|
|
cgapos |= cgaregr(0x0f);
|
|
cgapos *= 2;
|
|
cgablinkoff();
|
|
cgainitdone = 1;
|
|
iunlock(&cgalock);
|
|
screenputs = cgaconsputs;
|
|
addarchfile("cgamem", 0666, cgaread, cgawrite);
|
|
}
|