2 #include "../port/lib.h"
7 #include "../port/error.h"
9 typedef struct IOMap IOMap;
23 IOMap maps[32]; // some initial free maps
25 QLock ql; // lock for reading map
39 typedef long Rdwrfn(Chan*, void*, long, vlong);
41 static Rdwrfn *readfn[Qmax];
42 static Rdwrfn *writefn[Qmax];
44 static Dirtab archdir[] = {
45 ".", { Qdir, 0, QTDIR }, 0, 0555,
46 "ioalloc", { Qioalloc, 0 }, 0, 0444,
47 "iob", { Qiob, 0 }, 0, 0660,
48 "iow", { Qiow, 0 }, 0, 0660,
49 "iol", { Qiol, 0 }, 0, 0660,
51 Lock archwlock; /* the lock is only for changing archdir */
53 int (*_pcmspecial)(char *, ISAConf *);
54 void (*_pcmspecialclose)(int);
57 * Add a file to the #P listing. Once added, you can't delete it.
58 * You can't add a file with the same name as one already there,
59 * and you get a pointer to the Dirtab entry so you can do things
60 * like change the Qid version. Changing the Qid path is disallowed.
63 addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
69 memset(&d, 0, sizeof d);
79 for(i=0; i<narchdir; i++)
80 if(strcmp(archdir[i].name, name) == 0){
85 d.qid.path = narchdir;
86 archdir[narchdir] = d;
87 readfn[narchdir] = rdfn;
88 writefn[narchdir] = wrfn;
89 dp = &archdir[narchdir++];
100 for(i = 0; i < nelem(iomap.maps)-1; i++)
101 iomap.maps[i].next = &iomap.maps[i+1];
102 iomap.maps[i].next = nil;
103 iomap.free = iomap.maps;
105 // a dummy entry at 2^17
106 ioalloc(0x20000, 1, 0, "dummy");
110 // alloc some io port space and remember who it was
111 // alloced to. if port < 0, find a free region.
114 ioalloc(int port, int size, int align, char *tag)
121 // find a free port above 0x400 and below 0x1000
123 for(l = &iomap.m; *l; l = &(*l)->next){
129 port = ((port+align-1)/align)*align;
138 // see if the space clashes with previously allocated ports
139 for(l = &iomap.m; *l; l = &(*l)->next){
143 if(m->start >= port+size)
151 print("ioalloc: out of maps");
155 iomap.free = m->next;
158 m->end = port + size;
159 strncpy(m->tag, tag, sizeof(m->tag));
160 m->tag[sizeof(m->tag)-1] = 0;
163 archdir[0].qid.vers++;
175 for(l = &iomap.m; *l; l = &(*l)->next){
176 if((*l)->start == port){
179 m->next = iomap.free;
183 if((*l)->start > port)
186 archdir[0].qid.vers++;
191 iounused(int start, int end)
195 for(m = iomap.m; m; m = m->next){
196 if(start >= m->start && start < m->end
197 || start <= m->start && end > m->start)
204 checkport(int start, int end)
206 /* standard vga regs are OK */
207 if(start >= 0x2b0 && end <= 0x2df+1)
209 if(start >= 0x3c0 && end <= 0x3da+1)
212 if(iounused(start, end))
218 archattach(char* spec)
220 return devattach('P', spec);
224 archwalk(Chan* c, Chan *nc, char** name, int nname)
226 return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
230 archstat(Chan* c, uchar* dp, int n)
232 return devstat(c, dp, n, archdir, narchdir, devgen);
236 archopen(Chan* c, int omode)
238 return devopen(c, omode, archdir, nelem(archdir), devgen);
252 archread(Chan *c, void *a, long n, vlong offset)
254 char buf[Linelen+1], *p;
261 switch((ulong)c->qid.path){
264 return devdirread(c, a, n, archdir, nelem(archdir), devgen);
268 checkport(offset, offset+n);
269 for(p = a; port < offset+n; port++)
274 if((n & 0x01) || (offset & 0x01))
276 checkport(offset, offset+n+1);
279 for(port = offset; port < offset+n; port += 2)
284 if((n & 0x03) || (offset & 0x03))
286 checkport(offset, offset+n+3);
289 for(port = offset; port < offset+n; port += 4)
297 if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
298 return fn(c, a, n, offset);
303 offset = offset/Linelen;
307 for(m = iomap.m; n > 0 && m != nil; m = m->next){
310 if(strcmp(m->tag, "dummy") == 0)
312 sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
313 memmove(p, buf, Linelen);
323 archwrite(Chan *c, void *a, long n, vlong offset)
331 switch((ulong)c->qid.path){
335 checkport(offset, offset+n);
336 for(port = offset; port < offset+n; port++)
341 if((n & 01) || (offset & 01))
343 checkport(offset, offset+n+1);
346 for(port = offset; port < offset+n; port += 2)
351 if((n & 0x03) || (offset & 0x03))
353 checkport(offset, offset+n+3);
356 for(port = offset; port < offset+n; port += 4)
361 if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
362 return fn(c, a, n, offset);
391 pcmspecial(char *idstr, ISAConf *isa)
393 return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
397 pcmspecialclose(int a)
399 if (_pcmspecialclose != nil)