1*219b2ee8SDavid du Colombier #include <u.h> 2*219b2ee8SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <stdarg.h> 4*219b2ee8SDavid du Colombier 5*219b2ee8SDavid du Colombier #include "vga.h" 6*219b2ee8SDavid du Colombier 7*219b2ee8SDavid du Colombier static int iobfd = -1; 8*219b2ee8SDavid du Colombier static int iowfd = -1; 9*219b2ee8SDavid du Colombier static int iolfd = -1; 10*219b2ee8SDavid du Colombier static int biosfd = -1; 11*219b2ee8SDavid du Colombier 12*219b2ee8SDavid du Colombier enum { 13*219b2ee8SDavid du Colombier Nctlchar = 256, 14*219b2ee8SDavid du Colombier Nattr = 16, 15*219b2ee8SDavid du Colombier }; 16*219b2ee8SDavid du Colombier 17*219b2ee8SDavid du Colombier static int ctlfd = -1; 18*219b2ee8SDavid du Colombier static char ctlbuf[Nctlchar]; 19*219b2ee8SDavid du Colombier 20*219b2ee8SDavid du Colombier static struct { 21*219b2ee8SDavid du Colombier char* attr; 22*219b2ee8SDavid du Colombier char* val; 23*219b2ee8SDavid du Colombier } attr[Nattr]; 24*219b2ee8SDavid du Colombier 25*219b2ee8SDavid du Colombier static int 26*219b2ee8SDavid du Colombier devopen(char *device, int mode) 27*219b2ee8SDavid du Colombier { 28*219b2ee8SDavid du Colombier int fd; 29*219b2ee8SDavid du Colombier 30*219b2ee8SDavid du Colombier if((fd = open(device, mode)) < 0) 31*219b2ee8SDavid du Colombier error("devopen(%s, %d): %r\n", device, mode); 32*219b2ee8SDavid du Colombier return fd; 33*219b2ee8SDavid du Colombier } 34*219b2ee8SDavid du Colombier 35*219b2ee8SDavid du Colombier uchar 36*219b2ee8SDavid du Colombier inportb(long port) 37*219b2ee8SDavid du Colombier { 38*219b2ee8SDavid du Colombier uchar data; 39*219b2ee8SDavid du Colombier 40*219b2ee8SDavid du Colombier if(iobfd == -1) 41*219b2ee8SDavid du Colombier iobfd = devopen("#v/vgaiob", ORDWR); 42*219b2ee8SDavid du Colombier 43*219b2ee8SDavid du Colombier seek(iobfd, port, 0); 44*219b2ee8SDavid du Colombier if(read(iobfd, &data, sizeof(data)) != sizeof(data)) 45*219b2ee8SDavid du Colombier error("inportb(0x%4.4x): %r\n", port); 46*219b2ee8SDavid du Colombier return data; 47*219b2ee8SDavid du Colombier } 48*219b2ee8SDavid du Colombier 49*219b2ee8SDavid du Colombier void 50*219b2ee8SDavid du Colombier outportb(long port, uchar data) 51*219b2ee8SDavid du Colombier { 52*219b2ee8SDavid du Colombier if(iobfd == -1) 53*219b2ee8SDavid du Colombier iobfd = devopen("#v/vgaiob", ORDWR); 54*219b2ee8SDavid du Colombier 55*219b2ee8SDavid du Colombier seek(iobfd, port, 0); 56*219b2ee8SDavid du Colombier if(write(iobfd, &data, sizeof(data)) != sizeof(data)) 57*219b2ee8SDavid du Colombier error("outportb(0x%4.4x, 0x%2.2X): %r\n", port, data); 58*219b2ee8SDavid du Colombier } 59*219b2ee8SDavid du Colombier 60*219b2ee8SDavid du Colombier ushort 61*219b2ee8SDavid du Colombier inportw(long port) 62*219b2ee8SDavid du Colombier { 63*219b2ee8SDavid du Colombier ushort data; 64*219b2ee8SDavid du Colombier 65*219b2ee8SDavid du Colombier if(iowfd == -1) 66*219b2ee8SDavid du Colombier iowfd = devopen("#v/vgaiow", ORDWR); 67*219b2ee8SDavid du Colombier 68*219b2ee8SDavid du Colombier seek(iowfd, port, 0); 69*219b2ee8SDavid du Colombier if(read(iowfd, &data, sizeof(data)) != sizeof(data)) 70*219b2ee8SDavid du Colombier error("inportw(0x%4.4x): %r\n", port); 71*219b2ee8SDavid du Colombier return data; 72*219b2ee8SDavid du Colombier } 73*219b2ee8SDavid du Colombier 74*219b2ee8SDavid du Colombier void 75*219b2ee8SDavid du Colombier outportw(long port, ushort data) 76*219b2ee8SDavid du Colombier { 77*219b2ee8SDavid du Colombier if(iowfd == -1) 78*219b2ee8SDavid du Colombier iowfd = devopen("#v/vgaiow", ORDWR); 79*219b2ee8SDavid du Colombier 80*219b2ee8SDavid du Colombier seek(iowfd, port, 0); 81*219b2ee8SDavid du Colombier if(write(iowfd, &data, sizeof(data)) != sizeof(data)) 82*219b2ee8SDavid du Colombier error("outportw(0x%4.4x, 0x%2.2X): %r\n", port, data); 83*219b2ee8SDavid du Colombier } 84*219b2ee8SDavid du Colombier 85*219b2ee8SDavid du Colombier ulong 86*219b2ee8SDavid du Colombier inportl(long port) 87*219b2ee8SDavid du Colombier { 88*219b2ee8SDavid du Colombier ulong data; 89*219b2ee8SDavid du Colombier 90*219b2ee8SDavid du Colombier if(iolfd == -1) 91*219b2ee8SDavid du Colombier iolfd = devopen("#v/vgaiol", ORDWR); 92*219b2ee8SDavid du Colombier 93*219b2ee8SDavid du Colombier seek(iolfd, port, 0); 94*219b2ee8SDavid du Colombier if(read(iolfd, &data, sizeof(data)) != sizeof(data)) 95*219b2ee8SDavid du Colombier error("inportl(0x%4.4x): %r\n", port); 96*219b2ee8SDavid du Colombier return data; 97*219b2ee8SDavid du Colombier } 98*219b2ee8SDavid du Colombier 99*219b2ee8SDavid du Colombier void 100*219b2ee8SDavid du Colombier outportl(long port, ulong data) 101*219b2ee8SDavid du Colombier { 102*219b2ee8SDavid du Colombier if(iolfd == -1) 103*219b2ee8SDavid du Colombier iolfd = devopen("#v/vgaiol", ORDWR); 104*219b2ee8SDavid du Colombier 105*219b2ee8SDavid du Colombier seek(iolfd, port, 0); 106*219b2ee8SDavid du Colombier if(write(iolfd, &data, sizeof(data)) != sizeof(data)) 107*219b2ee8SDavid du Colombier error("outportl(0x%4.4x, 0x%2.2X): %r\n", port, data); 108*219b2ee8SDavid du Colombier } 109*219b2ee8SDavid du Colombier 110*219b2ee8SDavid du Colombier static void 111*219b2ee8SDavid du Colombier vgactlinit(void) 112*219b2ee8SDavid du Colombier { 113*219b2ee8SDavid du Colombier int nattr; 114*219b2ee8SDavid du Colombier char *nl, *p, *vp; 115*219b2ee8SDavid du Colombier 116*219b2ee8SDavid du Colombier if(ctlfd == -1){ 117*219b2ee8SDavid du Colombier ctlfd = devopen("#v/vgactl", ORDWR); 118*219b2ee8SDavid du Colombier memset(attr, 0, sizeof(attr)); 119*219b2ee8SDavid du Colombier } 120*219b2ee8SDavid du Colombier 121*219b2ee8SDavid du Colombier if(attr[0].attr) 122*219b2ee8SDavid du Colombier return; 123*219b2ee8SDavid du Colombier 124*219b2ee8SDavid du Colombier seek(ctlfd, 0, 0); 125*219b2ee8SDavid du Colombier if(read(ctlfd, ctlbuf, Nctlchar) < 0) 126*219b2ee8SDavid du Colombier error("vgactlr: read: %r\n"); 127*219b2ee8SDavid du Colombier ctlbuf[Nctlchar-1] = 0; 128*219b2ee8SDavid du Colombier 129*219b2ee8SDavid du Colombier nattr = 0; 130*219b2ee8SDavid du Colombier vp = ctlbuf; 131*219b2ee8SDavid du Colombier for(nl = strchr(ctlbuf, '\n'); nl; nl = strchr(nl, '\n')){ 132*219b2ee8SDavid du Colombier 133*219b2ee8SDavid du Colombier *nl = '\0'; 134*219b2ee8SDavid du Colombier if(p = strtok(vp, ":")){ 135*219b2ee8SDavid du Colombier attr[nattr].attr = p; 136*219b2ee8SDavid du Colombier if((p = strtok(0, " \t")) == 0) 137*219b2ee8SDavid du Colombier error("vgactlr: bad format: <%s>\n", vp); 138*219b2ee8SDavid du Colombier attr[nattr].val = p; 139*219b2ee8SDavid du Colombier } 140*219b2ee8SDavid du Colombier else 141*219b2ee8SDavid du Colombier error("vgactlr: bad format: <%s>\n", vp); 142*219b2ee8SDavid du Colombier 143*219b2ee8SDavid du Colombier if(++nattr >= Nattr-2) 144*219b2ee8SDavid du Colombier error("vgactlr: too many attributes: %d\n", nattr); 145*219b2ee8SDavid du Colombier attr[nattr].attr = 0; 146*219b2ee8SDavid du Colombier 147*219b2ee8SDavid du Colombier vp = ++nl; 148*219b2ee8SDavid du Colombier } 149*219b2ee8SDavid du Colombier } 150*219b2ee8SDavid du Colombier 151*219b2ee8SDavid du Colombier char* 152*219b2ee8SDavid du Colombier vgactlr(char *a, char *v) 153*219b2ee8SDavid du Colombier { 154*219b2ee8SDavid du Colombier int i; 155*219b2ee8SDavid du Colombier 156*219b2ee8SDavid du Colombier vgactlinit(); 157*219b2ee8SDavid du Colombier 158*219b2ee8SDavid du Colombier for(i = 0; attr[i].attr; i++){ 159*219b2ee8SDavid du Colombier if(strcmp(attr[i].attr, a) == 0){ 160*219b2ee8SDavid du Colombier strcpy(v, attr[i].val); 161*219b2ee8SDavid du Colombier return v; 162*219b2ee8SDavid du Colombier } 163*219b2ee8SDavid du Colombier } 164*219b2ee8SDavid du Colombier 165*219b2ee8SDavid du Colombier return 0; 166*219b2ee8SDavid du Colombier } 167*219b2ee8SDavid du Colombier 168*219b2ee8SDavid du Colombier void 169*219b2ee8SDavid du Colombier vgactlw(char *attr, char *val) 170*219b2ee8SDavid du Colombier { 171*219b2ee8SDavid du Colombier int len; 172*219b2ee8SDavid du Colombier char buf[128]; 173*219b2ee8SDavid du Colombier 174*219b2ee8SDavid du Colombier if(ctlfd == -1) 175*219b2ee8SDavid du Colombier ctlfd = devopen("#v/vgactl", ORDWR); 176*219b2ee8SDavid du Colombier 177*219b2ee8SDavid du Colombier seek(ctlfd, 0, 0); 178*219b2ee8SDavid du Colombier len = sprint(buf, "%s %s", attr, val); 179*219b2ee8SDavid du Colombier verbose("+vgactlw %s\n", buf); 180*219b2ee8SDavid du Colombier if(write(ctlfd, buf, len) != len) 181*219b2ee8SDavid du Colombier error("vgactlw: <%s>: %r\n", buf); 182*219b2ee8SDavid du Colombier verbose("-vgactlw %s\n", buf); 183*219b2ee8SDavid du Colombier } 184*219b2ee8SDavid du Colombier 185*219b2ee8SDavid du Colombier long 186*219b2ee8SDavid du Colombier readbios(char *buf, long len, long offset) 187*219b2ee8SDavid du Colombier { 188*219b2ee8SDavid du Colombier if(biosfd == -1) 189*219b2ee8SDavid du Colombier biosfd = devopen("#p/1/mem", OREAD); 190*219b2ee8SDavid du Colombier 191*219b2ee8SDavid du Colombier seek(biosfd, 0x80000000|offset, 0); 192*219b2ee8SDavid du Colombier if(read(biosfd, buf, len) != len) 193*219b2ee8SDavid du Colombier error("readbios read: %r\n"); 194*219b2ee8SDavid du Colombier return len; 195*219b2ee8SDavid du Colombier } 196*219b2ee8SDavid du Colombier 197*219b2ee8SDavid du Colombier void 198*219b2ee8SDavid du Colombier dumpbios(void) 199*219b2ee8SDavid du Colombier { 200*219b2ee8SDavid du Colombier uchar buf[256]; 201*219b2ee8SDavid du Colombier long offset; 202*219b2ee8SDavid du Colombier int i, n; 203*219b2ee8SDavid du Colombier char c; 204*219b2ee8SDavid du Colombier 205*219b2ee8SDavid du Colombier offset = 0xC0000; 206*219b2ee8SDavid du Colombier readbios((char*)buf, sizeof(buf), offset); 207*219b2ee8SDavid du Colombier if(buf[0] != 0x55 || buf[1] != 0xAA){ 208*219b2ee8SDavid du Colombier offset = 0xE0000; 209*219b2ee8SDavid du Colombier readbios((char*)buf, sizeof(buf), offset); 210*219b2ee8SDavid du Colombier if(buf[0] != 0x55 || buf[1] != 0xAA) 211*219b2ee8SDavid du Colombier return; 212*219b2ee8SDavid du Colombier } 213*219b2ee8SDavid du Colombier 214*219b2ee8SDavid du Colombier for(i = 0; i < sizeof(buf); i += 16){ 215*219b2ee8SDavid du Colombier print("0x%X", offset+i); 216*219b2ee8SDavid du Colombier for(n = 0; n < 16; n++) 217*219b2ee8SDavid du Colombier print(" %2.2uX", buf[i+n]); 218*219b2ee8SDavid du Colombier print(" "); 219*219b2ee8SDavid du Colombier for(n = 0; n < 16; n++){ 220*219b2ee8SDavid du Colombier c = buf[i+n]; 221*219b2ee8SDavid du Colombier if(c < 0x20 || c >= 0x7F) 222*219b2ee8SDavid du Colombier c = '.'; 223*219b2ee8SDavid du Colombier print("%c", c); 224*219b2ee8SDavid du Colombier } 225*219b2ee8SDavid du Colombier print("\n"); 226*219b2ee8SDavid du Colombier } 227*219b2ee8SDavid du Colombier } 228*219b2ee8SDavid du Colombier 229*219b2ee8SDavid du Colombier int vflag; 230*219b2ee8SDavid du Colombier 231*219b2ee8SDavid du Colombier void 232*219b2ee8SDavid du Colombier error(char *format, ...) 233*219b2ee8SDavid du Colombier { 234*219b2ee8SDavid du Colombier char buf[512]; 235*219b2ee8SDavid du Colombier int n; 236*219b2ee8SDavid du Colombier 237*219b2ee8SDavid du Colombier sequencer(0, 1); 238*219b2ee8SDavid du Colombier n = sprint(buf, "%s: ", argv0); 239*219b2ee8SDavid du Colombier doprint(buf+n, buf+sizeof(buf)-n, format, (&format+1)); 240*219b2ee8SDavid du Colombier fprint(2, buf); 241*219b2ee8SDavid du Colombier if(vflag) 242*219b2ee8SDavid du Colombier print(buf+n); 243*219b2ee8SDavid du Colombier exits("error"); 244*219b2ee8SDavid du Colombier } 245*219b2ee8SDavid du Colombier 246*219b2ee8SDavid du Colombier void* 247*219b2ee8SDavid du Colombier alloc(ulong nbytes) 248*219b2ee8SDavid du Colombier { 249*219b2ee8SDavid du Colombier void *v; 250*219b2ee8SDavid du Colombier 251*219b2ee8SDavid du Colombier if((v = malloc(nbytes)) == 0) 252*219b2ee8SDavid du Colombier error("can't malloc %d bytes - %r\n", nbytes); 253*219b2ee8SDavid du Colombier 254*219b2ee8SDavid du Colombier return memset(v, 0, nbytes); 255*219b2ee8SDavid du Colombier } 256*219b2ee8SDavid du Colombier 257*219b2ee8SDavid du Colombier static int curindex; 258*219b2ee8SDavid du Colombier 259*219b2ee8SDavid du Colombier void 260*219b2ee8SDavid du Colombier printitem(char *ctlr, char *item) 261*219b2ee8SDavid du Colombier { 262*219b2ee8SDavid du Colombier int n; 263*219b2ee8SDavid du Colombier 264*219b2ee8SDavid du Colombier if(curindex){ 265*219b2ee8SDavid du Colombier curindex = 0; 266*219b2ee8SDavid du Colombier print("\n"); 267*219b2ee8SDavid du Colombier } 268*219b2ee8SDavid du Colombier 269*219b2ee8SDavid du Colombier n = 0; 270*219b2ee8SDavid du Colombier if(ctlr && *ctlr) 271*219b2ee8SDavid du Colombier n = print("%s ", ctlr); 272*219b2ee8SDavid du Colombier print("%-*s", 20-n, item); 273*219b2ee8SDavid du Colombier } 274*219b2ee8SDavid du Colombier 275*219b2ee8SDavid du Colombier void 276*219b2ee8SDavid du Colombier printreg(ulong data) 277*219b2ee8SDavid du Colombier { 278*219b2ee8SDavid du Colombier int width; 279*219b2ee8SDavid du Colombier 280*219b2ee8SDavid du Colombier width = 3; 281*219b2ee8SDavid du Colombier if((curindex % 16) == 0 && curindex){ 282*219b2ee8SDavid du Colombier print("\n"); 283*219b2ee8SDavid du Colombier curindex = 0; 284*219b2ee8SDavid du Colombier width = 23; 285*219b2ee8SDavid du Colombier } 286*219b2ee8SDavid du Colombier if(curindex == 8) 287*219b2ee8SDavid du Colombier print(" -"); 288*219b2ee8SDavid du Colombier print("%*.2X", width, data); 289*219b2ee8SDavid du Colombier curindex++; 290*219b2ee8SDavid du Colombier } 291*219b2ee8SDavid du Colombier 292*219b2ee8SDavid du Colombier void 293*219b2ee8SDavid du Colombier verbose(char *format, ...) 294*219b2ee8SDavid du Colombier { 295*219b2ee8SDavid du Colombier char buf[512]; 296*219b2ee8SDavid du Colombier 297*219b2ee8SDavid du Colombier if(vflag){ 298*219b2ee8SDavid du Colombier if(curindex){ 299*219b2ee8SDavid du Colombier curindex = 0; 300*219b2ee8SDavid du Colombier print("\n"); 301*219b2ee8SDavid du Colombier } 302*219b2ee8SDavid du Colombier doprint(buf, buf+sizeof(buf), format, (&format+1)); 303*219b2ee8SDavid du Colombier print(buf); 304*219b2ee8SDavid du Colombier } 305*219b2ee8SDavid du Colombier } 306