ref: d8d47f14b5ed8f6d3f892761ed86c6ce2075c337
dir: /sys/src/9/alphapc/cga.c/
#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "io.h" enum { Width = 160, Height = 25, Attr = 0x4f, /* white on blue */ }; static ulong cgabase; #define CGASCREENBASE ((uchar*)cgabase) static int cgapos; static int screeninitdone; static Lock cgascreenlock; static uchar cgaregr(int index) { outb(0x3D4, index); return inb(0x3D4+1) & 0xFF; } static void cgaregw(int index, int data) { outb(0x3D4, index); outb(0x3D4+1, data); } static void movecursor(void) { cgaregw(0x0E, (cgapos/2>>8) & 0xFF); cgaregw(0x0F, cgapos/2 & 0xFF); CGASCREENBASE[cgapos+1] = Attr; } static void cgascreenputc(int c) { int i; if(c == '\n'){ cgapos = cgapos/Width; cgapos = (cgapos+1)*Width; } else if(c == '\t'){ i = 8 - ((cgapos/2)&7); while(i-->0) cgascreenputc(' '); } else if(c == '\b'){ if(cgapos >= 2) cgapos -= 2; cgascreenputc(' '); cgapos -= 2; } else{ CGASCREENBASE[cgapos++] = c; CGASCREENBASE[cgapos++] = Attr; } if(cgapos >= Width*Height){ memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1)); for (i = Width*(Height-1); i < Width*Height;) { CGASCREENBASE[i++] = 0x20; CGASCREENBASE[i++] = Attr; } cgapos = Width*(Height-1); } movecursor(); } void screeninit(void) { cgabase = (ulong)arch->pcimem(0xB8000, 0x8000); cgapos = cgaregr(0x0E)<<8; cgapos |= cgaregr(0x0F); cgapos *= 2; screeninitdone = 1; } static void cgascreenputs(char* s, int n) { if(!screeninitdone) return; if(!islo()){ /* * Don't deadlock trying to * print in an interrupt. */ if(!canlock(&cgascreenlock)) return; } else lock(&cgascreenlock); while(n-- > 0) cgascreenputc(*s++); unlock(&cgascreenlock); } void (*screenputs)(char*, int) = cgascreenputs;