]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/mtx/devarch.c
ether8169: support rtl8402 variant
[plan9front.git] / sys / src / 9 / mtx / devarch.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8
9 enum {
10         Qdir = 0,
11         Qiob,
12         Qiow,
13         Qiol,
14         Qbase,
15
16         Qmax = 16,
17 };
18
19 typedef long Rdwrfn(Chan*, void*, long, vlong);
20
21 static Rdwrfn *readfn[Qmax];
22 static Rdwrfn *writefn[Qmax];
23
24 static Dirtab archdir[] = {
25         ".",    { Qdir, 0, QTDIR },     0,      0555,
26         "iob",          { Qiob, 0 },            0,      0660,
27         "iow",          { Qiow, 0 },            0,      0660,
28         "iol",          { Qiol, 0 },            0,      0660,
29 };
30 Lock archwlock; /* the lock is only for changing archdir */
31 int narchdir = Qbase;
32 int (*_pcmspecial)(char *, ISAConf *);
33 void (*_pcmspecialclose)(int);
34
35 /*
36  * Add a file to the #P listing.  Once added, you can't delete it.
37  * You can't add a file with the same name as one already there,
38  * and you get a pointer to the Dirtab entry so you can do things
39  * like change the Qid version.  Changing the Qid path is disallowed.
40  */
41 Dirtab*
42 addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
43 {
44         int i;
45         Dirtab d;
46         Dirtab *dp;
47
48         memset(&d, 0, sizeof d);
49         strcpy(d.name, name);
50         d.perm = perm;
51
52         lock(&archwlock);
53         if(narchdir >= Qmax){
54                 unlock(&archwlock);
55                 return nil;
56         }
57
58         for(i=0; i<narchdir; i++)
59                 if(strcmp(archdir[i].name, name) == 0){
60                         unlock(&archwlock);
61                         return nil;
62                 }
63
64         d.qid.path = narchdir;
65         archdir[narchdir] = d;
66         readfn[narchdir] = rdfn;
67         writefn[narchdir] = wrfn;
68         dp = &archdir[narchdir++];
69         unlock(&archwlock);
70
71         return dp;
72 }
73
74 void
75 ioinit(void)
76 {
77         iomapinit(IOSIZE-1);
78
79         // a dummy entry at 2^17
80         ioalloc(0x20000, 1, 0, "dummy");
81 }
82
83 static void
84 checkport(int start, int end)
85 {
86         /* standard vga regs are OK */
87         if(start >= 0x2b0 && end <= 0x2df+1)
88                 return;
89         if(start >= 0x3c0 && end <= 0x3da+1)
90                 return;
91
92         if(iounused(start, end))
93                 return;
94         error(Eperm);
95 }
96
97 static Chan*
98 archattach(char* spec)
99 {
100         return devattach('P', spec);
101 }
102
103 Walkqid*
104 archwalk(Chan* c, Chan *nc, char** name, int nname)
105 {
106         return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
107 }
108
109 static int
110 archstat(Chan* c, uchar* dp, int n)
111 {
112         return devstat(c, dp, n, archdir, narchdir, devgen);
113 }
114
115 static Chan*
116 archopen(Chan* c, int omode)
117 {
118         return devopen(c, omode, archdir, nelem(archdir), devgen);
119 }
120
121 static void
122 archclose(Chan*)
123 {
124 }
125
126 static long
127 archread(Chan *c, void *a, long n, vlong offset)
128 {
129         int port;
130         uchar *cp;
131         ushort *sp;
132         ulong *lp;
133         IOMap *m;
134         Rdwrfn *fn;
135
136         switch((ulong)c->qid.path){
137
138         case Qdir:
139                 return devdirread(c, a, n, archdir, nelem(archdir), devgen);
140
141         case Qiob:
142                 port = offset;
143                 checkport(offset, offset+n);
144                 for(cp = a; port < offset+n; port++)
145                         *cp++ = inb(port);
146                 return n;
147
148         case Qiow:
149                 if((n & 0x01) || (offset & 0x01))
150                         error(Ebadarg);
151                 checkport(offset, offset+n+1);
152                 n /= 2;
153                 sp = a;
154                 for(port = offset; port < offset+n; port += 2)
155                         *sp++ = ins(port);
156                 return n*2;
157
158         case Qiol:
159                 if((n & 0x03) || (offset & 0x03))
160                         error(Ebadarg);
161                 checkport(offset, offset+n+3);
162                 n /= 4;
163                 lp = a;
164                 for(port = offset; port < offset+n; port += 4)
165                         *lp++ = inl(port);
166                 return n*4;
167
168         default:
169                 if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
170                         return fn(c, a, n, offset);
171                 error(Eperm);
172                 break;
173         }
174         return 0;
175 }
176
177 static long
178 archwrite(Chan *c, void *a, long n, vlong offset)
179 {
180         int port;
181         uchar *cp;
182         ushort *sp;
183         ulong *lp;
184         Rdwrfn *fn;
185
186         switch((ulong)c->qid.path){
187
188         case Qiob:
189                 cp = a;
190                 checkport(offset, offset+n);
191                 for(port = offset; port < offset+n; port++)
192                         outb(port, *cp++);
193                 return n;
194
195         case Qiow:
196                 if((n & 01) || (offset & 01))
197                         error(Ebadarg);
198                 checkport(offset, offset+n+1);
199                 n /= 2;
200                 sp = a;
201                 for(port = offset; port < offset+n; port += 2)
202                         outs(port, *sp++);
203                 return n*2;
204
205         case Qiol:
206                 if((n & 0x03) || (offset & 0x03))
207                         error(Ebadarg);
208                 checkport(offset, offset+n+3);
209                 n /= 4;
210                 lp = a;
211                 for(port = offset; port < offset+n; port += 4)
212                         outl(port, *lp++);
213                 return n*4;
214
215         default:
216                 if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
217                         return fn(c, a, n, offset);
218                 error(Eperm);
219                 break;
220         }
221         return 0;
222 }
223
224 Dev archdevtab = {
225         'P',
226         "arch",
227
228         devreset,
229         devinit,
230         devshutdown,
231         archattach,
232         archwalk,
233         archstat,
234         archopen,
235         devcreate,
236         archclose,
237         archread,
238         devbread,
239         archwrite,
240         devbwrite,
241         devremove,
242         devwstat,
243 };
244
245 int
246 pcmspecial(char *idstr, ISAConf *isa)
247 {
248         return (_pcmspecial  != nil)? _pcmspecial(idstr, isa): -1;
249 }
250
251 void
252 pcmspecialclose(int a)
253 {
254         if (_pcmspecialclose != nil)
255                 _pcmspecialclose(a);
256 }