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