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