1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 5 #include "pci.h" 6 #include "vga.h" 7 8 int curprintindex; 9 10 static int iobfd = -1; 11 static int iowfd = -1; 12 static int iolfd = -1; 13 static int biosfd = -1; 14 static ulong biosoffset = 0; 15 16 enum { 17 Nctlchar = 256, 18 Nattr = 16, 19 }; 20 21 static int ctlfd = -1; 22 static char ctlbuf[Nctlchar]; 23 static int ctlclean; 24 25 static struct { 26 char* attr; 27 char* val; 28 } attr[Nattr]; 29 30 static int 31 devopen(char* device, int mode) 32 { 33 int fd; 34 35 if((fd = open(device, mode)) < 0) 36 error("devopen(%s, %d): %r\n", device, mode); 37 return fd; 38 } 39 40 uchar 41 inportb(long port) 42 { 43 uchar data; 44 45 if(iobfd == -1) 46 iobfd = devopen("#P/iob", ORDWR); 47 48 if(pread(iobfd, &data, sizeof(data), port) != sizeof(data)) 49 error("inportb(0x%4.4lx): %r\n", port); 50 return data; 51 } 52 53 void 54 outportb(long port, uchar data) 55 { 56 if(iobfd == -1) 57 iobfd = devopen("#P/iob", ORDWR); 58 59 if(pwrite(iobfd, &data, sizeof(data), port) != sizeof(data)) 60 error("outportb(0x%4.4lx, 0x%2.2uX): %r\n", port, data); 61 } 62 63 ushort 64 inportw(long port) 65 { 66 ushort data; 67 68 if(iowfd == -1) 69 iowfd = devopen("#P/iow", ORDWR); 70 71 if(pread(iowfd, &data, sizeof(data), port) != sizeof(data)) 72 error("inportw(0x%4.4lx): %r\n", port); 73 return data; 74 } 75 76 void 77 outportw(long port, ushort data) 78 { 79 if(iowfd == -1) 80 iowfd = devopen("#P/iow", ORDWR); 81 82 if(pwrite(iowfd, &data, sizeof(data), port) != sizeof(data)) 83 error("outportw(0x%4.4lx, 0x%2.2uX): %r\n", port, data); 84 } 85 86 ulong 87 inportl(long port) 88 { 89 ulong data; 90 91 if(iolfd == -1) 92 iolfd = devopen("#P/iol", ORDWR); 93 94 if(pread(iolfd, &data, sizeof(data), port) != sizeof(data)) 95 error("inportl(0x%4.4lx): %r\n", port); 96 return data; 97 } 98 99 void 100 outportl(long port, ulong data) 101 { 102 if(iolfd == -1) 103 iolfd = devopen("#P/iol", ORDWR); 104 105 if(pwrite(iolfd, &data, sizeof(data), port) != sizeof(data)) 106 error("outportl(0x%4.4lx, 0x%2.2luX): %r\n", port, data); 107 } 108 109 static void 110 vgactlinit(void) 111 { 112 int nattr; 113 char *nl, *p, *vp; 114 115 if(ctlclean) 116 return; 117 118 if(ctlfd == -1){ 119 ctlfd = devopen("#v/vgactl", ORDWR); 120 memset(attr, 0, sizeof(attr)); 121 } 122 123 seek(ctlfd, 0, 0); 124 nattr = read(ctlfd, ctlbuf, Nctlchar-1); 125 if(nattr < 0) 126 error("vgactlr: read: %r\n"); 127 ctlbuf[nattr] = 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 = strchr(vp, ' ')){ 135 *p++ = '\0'; 136 attr[nattr].attr = vp; 137 if(*p == '\0') 138 error("vgactlr: bad format: <%s>\n", vp); 139 attr[nattr].val = p; 140 } 141 else 142 error("vgactlr: bad format: <%s>\n", vp); 143 144 if(++nattr >= Nattr-2) 145 error("vgactlr: too many attributes: %d\n", nattr); 146 attr[nattr].attr = 0; 147 148 vp = ++nl; 149 } 150 151 ctlclean = 1; 152 } 153 154 char* 155 vgactlr(char* a, char* v) 156 { 157 int i; 158 159 trace("vgactlr: look for %s\n", a); 160 vgactlinit(); 161 for(i = 0; attr[i].attr; i++){ 162 if(strcmp(attr[i].attr, a) == 0){ 163 strcpy(v, attr[i].val); 164 trace("vgactlr: value %s\n", v); 165 return v; 166 } 167 } 168 trace("vgactlr: %s not found\n", a); 169 170 return 0; 171 } 172 173 void 174 vgactlw(char* attr, char* val) 175 { 176 int len; 177 char buf[128]; 178 179 if(ctlfd == -1) 180 ctlfd = devopen("#v/vgactl", ORDWR); 181 182 seek(ctlfd, 0, 0); 183 len = sprint(buf, "%s %s", attr, val); 184 trace("+vgactlw %s\n", buf); 185 if(write(ctlfd, buf, len) != len) 186 error("vgactlw: <%s>: %r\n", buf); 187 trace("-vgactlw %s\n", buf); 188 189 ctlclean = 0; 190 } 191 192 void 193 setpalette(int p, int r, int g, int b) 194 { 195 vgao(PaddrW, p); 196 vgao(Pdata, r); 197 vgao(Pdata, g); 198 vgao(Pdata, b); 199 } 200 201 static long 202 doreadbios(char* buf, long len, long offset) 203 { 204 char file[64]; 205 206 if(biosfd == -1){ 207 biosfd = open("#v/vgabios", OREAD); 208 biosoffset = 0; 209 } 210 if(biosfd == -1){ 211 snprint(file, sizeof file, "#p/%d/mem", getpid()); 212 biosfd = devopen(file, OREAD); 213 biosoffset = 0x80000000; 214 } 215 if(biosfd == -1) 216 return -1; 217 seek(biosfd, biosoffset+offset, 0); 218 return read(biosfd, buf, len); 219 } 220 221 char* 222 readbios(long len, long offset) 223 { 224 static char bios[0x10000]; 225 static long biosoffset; 226 static long bioslen; 227 int n; 228 229 if(biosoffset <= offset && offset+len <= biosoffset+bioslen) 230 return bios+(offset - biosoffset); 231 232 if(len > sizeof(bios)) 233 error("enormous bios len %ld at %lux\n", len, offset); 234 235 n = doreadbios(bios, sizeof(bios), offset); 236 if(n < len) 237 error("short bios read %ld at %lux got %d\n", len,offset, n); 238 239 biosoffset = offset; 240 bioslen = n; 241 return bios; 242 } 243 244 void 245 dumpbios(long size) 246 { 247 uchar *buf; 248 long offset; 249 int i, n; 250 char c; 251 252 buf = alloc(size); 253 offset = 0xC0000; 254 if(doreadbios((char*)buf, size, offset) != size) 255 error("short bios read in dumpbios\n"); 256 257 if(buf[0] != 0x55 || buf[1] != 0xAA){ 258 offset = 0xE0000; 259 if(doreadbios((char*)buf, size, offset) != size) 260 error("short bios read in dumpbios\n"); 261 if(buf[0] != 0x55 || buf[1] != 0xAA){ 262 free(buf); 263 return; 264 } 265 } 266 267 for(i = 0; i < size; i += 16){ 268 Bprint(&stdout, "0x%luX", offset+i); 269 for(n = 0; n < 16; n++) 270 Bprint(&stdout, " %2.2uX", buf[i+n]); 271 Bprint(&stdout, " "); 272 for(n = 0; n < 16; n++){ 273 c = buf[i+n]; 274 if(c < 0x20 || c >= 0x7F) 275 c = '.'; 276 Bprint(&stdout, "%c", c); 277 } 278 Bprint(&stdout, "\n"); 279 } 280 free(buf); 281 } 282 283 void* 284 alloc(ulong nbytes) 285 { 286 void *v; 287 288 if((v = malloc(nbytes)) == 0) 289 error("alloc: %lud bytes - %r\n", nbytes); 290 291 return memset(v, 0, nbytes); 292 } 293 294 void 295 printitem(char* ctlr, char* item) 296 { 297 int n; 298 299 if(curprintindex){ 300 curprintindex = 0; 301 Bprint(&stdout, "\n"); 302 } 303 304 n = 0; 305 if(ctlr && *ctlr) 306 n = Bprint(&stdout, "%s ", ctlr); 307 Bprint(&stdout, "%-*s", 20-n, item); 308 } 309 310 void 311 printreg(ulong data) 312 { 313 int width; 314 315 width = 3; 316 if((curprintindex % 16) == 0 && curprintindex){ 317 Bprint(&stdout, "\n"); 318 curprintindex = 0; 319 width = 23; 320 } 321 if(curprintindex == 8) 322 Bprint(&stdout, " -"); 323 Bprint(&stdout, "%*.2luX", width, data); 324 curprintindex++; 325 } 326 327 static char *flagname[32] = { 328 [0x00] "Fsnarf", 329 [0x01] "Foptions", 330 [0x02] "Finit", 331 [0x03] "Fload", 332 [0x04] "Fdump", 333 334 [0x08] "Hpclk2x8", 335 [0x09] "Upclk2x8", 336 [0x0A] "Henhanced", 337 [0x0B] "Uenhanced", 338 [0x0C] "Hpvram", 339 [0x0D] "Upvram", 340 [0x0E] "Hextsid", 341 [0x0F] "Uextsid", 342 [0x10] "Hclk2", 343 [0x11] "Uclk2", 344 [0x12] "Hlinear", 345 [0x13] "Ulinear", 346 [0x14] "Hclkdiv", 347 [0x15] "Uclkdiv", 348 [0x16] "Hsid32", 349 }; 350 351 void 352 printflag(ulong flag) 353 { 354 int i; 355 char first; 356 357 first = ' '; 358 for(i = 31; i >= 0; i--){ 359 if((flag & (1<<i)) == 0) 360 continue; 361 if(flagname[i]) 362 Bprint(&stdout, "%c%s", first, flagname[i]); 363 else 364 Bprint(&stdout, "%c0x%x", first, 1<<i); 365 first = '|'; 366 } 367 } 368