2 #include "../port/lib.h"
7 #include "../port/error.h"
10 typedef struct IOMap IOMap;
24 IOMap maps[32]; // some initial free maps
26 QLock ql; // lock for reading map
40 typedef long Rdwrfn(Chan*, void*, long, vlong);
42 static Rdwrfn *readfn[Qmax];
43 static Rdwrfn *writefn[Qmax];
45 static Dirtab archdir[] = {
46 ".", { Qdir, 0, QTDIR }, 0, 0555,
47 "ioalloc", { Qioalloc, 0 }, 0, 0444,
48 "iob", { Qiob, 0 }, 0, 0660,
49 "iow", { Qiow, 0 }, 0, 0660,
50 "iol", { Qiol, 0 }, 0, 0660,
52 Lock archwlock; /* the lock is only for changing archdir */
54 int (*_pcmspecial)(char *, ISAConf *);
55 void (*_pcmspecialclose)(int);
58 * Add a file to the #P listing. Once added, you can't delete it.
59 * You can't add a file with the same name as one already there,
60 * and you get a pointer to the Dirtab entry so you can do things
61 * like change the Qid version. Changing the Qid path is disallowed.
64 addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
70 memset(&d, 0, sizeof d);
80 for(i=0; i<narchdir; i++)
81 if(strcmp(archdir[i].name, name) == 0){
86 d.qid.path = narchdir;
87 archdir[narchdir] = d;
88 readfn[narchdir] = rdfn;
89 writefn[narchdir] = wrfn;
90 dp = &archdir[narchdir++];
101 for(i = 0; i < nelem(iomap.maps)-1; i++)
102 iomap.maps[i].next = &iomap.maps[i+1];
103 iomap.maps[i].next = nil;
104 iomap.free = iomap.maps;
106 // a dummy entry at 2^17
107 ioalloc(0x20000, 1, 0, "dummy");
111 // alloc some io port space and remember who it was
112 // alloced to. if port < 0, find a free region.
115 ioalloc(int port, int size, int align, char *tag)
122 // find a free port above 0x400 and below 0x1000
124 for(l = &iomap.m; *l; l = &(*l)->next){
130 port = ((port+align-1)/align)*align;
139 // see if the space clashes with previously allocated ports
140 for(l = &iomap.m; *l; l = &(*l)->next){
144 if(m->start >= port+size)
152 print("ioalloc: out of maps");
156 iomap.free = m->next;
159 m->end = port + size;
160 strncpy(m->tag, tag, sizeof(m->tag));
161 m->tag[sizeof(m->tag)-1] = 0;
164 archdir[0].qid.vers++;
176 for(l = &iomap.m; *l; l = &(*l)->next){
177 if((*l)->start == port){
180 m->next = iomap.free;
184 if((*l)->start > port)
187 archdir[0].qid.vers++;
192 iounused(int start, int end)
196 for(m = iomap.m; m; m = m->next){
197 if(start >= m->start && start < m->end
198 || start <= m->start && end > m->start)
205 checkport(int start, int end)
207 /* standard vga regs are OK */
208 if(start >= 0x2b0 && end <= 0x2df+1)
210 if(start >= 0x3c0 && end <= 0x3da+1)
213 if(iounused(start, end))
219 archattach(char* spec)
221 return devattach('P', spec);
225 archwalk(Chan* c, Chan *nc, char** name, int nname)
227 return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
231 archstat(Chan* c, uchar* dp, int n)
233 return devstat(c, dp, n, archdir, narchdir, devgen);
237 archopen(Chan* c, int omode)
239 return devopen(c, omode, archdir, nelem(archdir), devgen);
253 archread(Chan *c, void *a, long n, vlong offset)
255 char buf[Linelen+1], *p;
262 switch((ulong)c->qid.path){
265 return devdirread(c, a, n, archdir, nelem(archdir), devgen);
269 checkport(offset, offset+n);
270 for(p = a; port < offset+n; port++)
275 if((n & 0x01) || (offset & 0x01))
277 checkport(offset, offset+n+1);
280 for(port = offset; port < offset+n; port += 2)
285 if((n & 0x03) || (offset & 0x03))
287 checkport(offset, offset+n+3);
290 for(port = offset; port < offset+n; port += 4)
298 if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
299 return fn(c, a, n, offset);
304 offset = offset/Linelen;
308 for(m = iomap.m; n > 0 && m != nil; m = m->next){
311 if(strcmp(m->tag, "dummy") == 0)
313 sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
314 memmove(p, buf, Linelen);
324 archwrite(Chan *c, void *a, long n, vlong offset)
332 switch((ulong)c->qid.path){
336 checkport(offset, offset+n);
337 for(port = offset; port < offset+n; port++)
342 if((n & 01) || (offset & 01))
344 checkport(offset, offset+n+1);
347 for(port = offset; port < offset+n; port += 2)
352 if((n & 0x03) || (offset & 0x03))
354 checkport(offset, offset+n+3);
357 for(port = offset; port < offset+n; port += 4)
362 if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
363 return fn(c, a, n, offset);
392 extern PCArch* knownarch[];
394 PCArch archgeneric = {
402 static char *sysnames[] =
404 [1] "Alpha Demo. Unit",
405 [2] "DEC 4000; Cobra",
406 [3] "DEC 7000; Ruby",
407 [4] "DEC 3000/500; Flamingo family (TC)",
408 [6] "DEC 2000/300; Jensen (EISA/ISA)",
409 [7] "DEC 3000/300; Pelican (TC)",
410 [8] "Avalon A12; Avalon Multicomputer",
411 [9] "DEC 2100/A500; Sable",
412 [10] "DEC APXVME/64; AXPvme (VME?)",
413 [11] "DEC AXPPCI/33; NoName (PCI/ISA)",
414 [12] "DEC 21000; TurboLaser (PCI/EISA)",
415 [13] "DEC 2100/A50; Avanti (PCI/ISA)",
416 [14] "DEC MUSTANG; Mustang",
417 [15] "DEC KN20AA; kn20aa (PCI/EISA)",
418 [17] "DEC 1000; Mikasa (PCI/ISA?)",
419 [19] "EB66; EB66 (PCI/ISA?)", // DEC?
420 [20] "EB64P; EB64+ (PCI/ISA?)", // DEC?
421 [21] "Alphabook1; Alphabook",
422 [22] "DEC 4100; Rawhide (PCI/EISA)",
423 [23] "DEC EV45/PBP; Lego",
424 [24] "DEC 2100A/A500; Lynx",
425 [26] "DEC AlphaPC 164", // only supported one: "EB164 (PCI/ISA)"
426 [27] "DEC 1000A; Noritake",
427 [28] "DEC AlphaVME/224; Cortex",
428 [30] "DEC 550; Miata (PCI/ISA)",
429 [32] "DEC EV56/PBP; Takara",
430 [33] "DEC AlphaVME/320; Yukon (VME?)",
431 [34] "DEC 6600; MonetGoldrush",
432 // 200 and up is Alpha Processor Inc. machines
433 // [201] "API UP1000; Nautilus",
436 static char *cpunames[] =
441 [4] "LCA4: 2106[68]",
444 [7] "21164A", /* only supported one: EV56 */
446 [9] "PCA256: 21164PC",
459 if (hwrpb->rev >= 6) {
460 dsr = (Hwdsr*)((ulong)hwrpb + hwrpb->dsroff);
462 s = (char*)dsr + dsr->sysnameoff + 8;
467 if (hwrpb->systype < nelem(sysnames))
468 s = sysnames[hwrpb->systype];
469 print("%s (%llux, %llux, %llux)\n", s, hwrpb->systype, hwrpb->sysvar, hwrpb->sysrev);
472 for (i = 0; i < hwrpb->ncpu; i++) {
473 cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + i*hwrpb->cpulen);
475 maj = (ulong)cpu->cputype;
476 min = (ulong)(cpu->cputype>>32);
477 if (maj < nelem(cpunames))
479 print("cpu%d: %s-%d (%d.%d, %llux, %llux)\n",
480 i, s, min, maj, min, cpu->cpuvar, cpu->cpurev);
487 cputyperead(Chan*, void *a, long n, vlong offset)
489 char str[32], *cputype;
493 mhz = (m->cpuhz+999999)/1000000;
494 cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff); /* NB CPU 0 */
496 maj = (ulong)cpu->cputype;
497 if (maj < nelem(cpunames))
498 cputype = cpunames[maj];
500 snprint(str, sizeof(str), "%s %lud\n", cputype, mhz);
501 return readstr(offset, a, n, str);
510 for(p = knownarch; *p; p++){
511 if((*p)->ident && (*p)->ident() == 0){
519 addarchfile("cputype", 0444, cputyperead, nil);
523 pcmspecial(char *idstr, ISAConf *isa)
525 return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
529 pcmspecialclose(int a)
531 if (_pcmspecialclose != nil)