|
|
1.1 root 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: #include "devtab.h"
10:
11: #define ROMADDR 0x40000000
12: #define ROMSIZE ((256*1024)/8)
13:
14: #define P_qlock(sel) if(sel >= 0){\
15: qlock(&portpage);\
16: PORTSELECT = portpage.select = sel;\
17: }else
18:
19: #define P_qunlock(sel) if(sel >= 0){\
20: qunlock(&portpage);\
21: }else
22:
23: #define P_oper(sel, inst) P_qlock(sel); inst; P_qunlock(sel)
24: #define P_read(sel, addr, val, type) P_oper(sel, val = *(type *)(PORT+addr))
25: #define P_write(sel, addr, val, type) P_oper(sel, *(type *)(PORT+addr) = val)
26:
27: enum
28: {
29: Qdir,
30: Qdata,
31: Qrom
32: };
33:
34: Dirtab portdir[]={
35: "data", {Qdata}, 0, 0666,
36: "rom", {Qrom}, ROMSIZE, 0444,
37: };
38:
39: #define NPORT (sizeof portdir/sizeof(Dirtab))
40:
41: #define Nportservice 8
42: static int (*portservice[Nportservice])(void);
43: Portpage portpage;
44: static Lock intrlock;
45:
46: int
47: portprobe(char *what, int select, int addr, int rw, long val)
48: {
49: int time;
50: if (!conf.portispaged)
51: return 0;
52: P_qlock(select);
53: switch (rw) {
54: case -1:
55: val = *(uchar *)(PORT+addr);
56: break;
57: case -2:
58: val = *(ushort *)(PORT+addr);
59: break;
60: case -4:
61: val = *(long *)(PORT+addr);
62: break;
63: case 1:
64: *(uchar *)(PORT+addr) = val;
65: break;
66: case 2:
67: *(ushort *)(PORT+addr) = val;
68: break;
69: case 4:
70: *(long *)(PORT+addr) = val;
71: break;
72: default:
73: panic("portprobe");
74: }
75: time = PORTSELECT & 0x1f;
76: P_qunlock(select);
77: if (what) {
78: print("%s at %d, %d", what, select, addr);
79: print("%s", time & 0x10 ? " -- NOT FOUND\n" : "\n");
80: }
81: if (time & 0x10)
82: return -1;
83: return val;
84: }
85:
86: void
87: portreset(void)
88: {
89: portpage.select = -1;
90: lock(&portpage);
91: unlock(&portpage);
92: }
93:
94: void
95: portinit(void)
96: {
97: }
98:
99: Chan *
100: portattach(char *param)
101: {
102: return devattach('x', param);
103: }
104:
105: Chan *
106: portclone(Chan *c, Chan *nc)
107: {
108: return devclone(c, nc);
109: }
110:
111: int
112: portwalk(Chan *c, char *name)
113: {
114: return devwalk(c, name, portdir, NPORT, devgen);
115: }
116:
117: void
118: portstat(Chan *c, char *db)
119: {
120: devstat(c, db, portdir, NPORT, devgen);
121: }
122:
123: Chan *
124: portopen(Chan *c, int omode)
125: {
126: return devopen(c, omode, portdir, NPORT, devgen);
127: }
128:
129: void
130: portcreate(Chan *c, char *name, int omode, ulong perm)
131: {
132: USED(c, name, omode, perm);
133: error(Eperm);
134: }
135:
136: void
137: portclose(Chan *c)
138: {
139: USED(c);
140: }
141:
142: long
143: portread(Chan *c, char *a, long n, ulong offset)
144: {
145: long s, k;
146: if (n == 0)
147: return 0;
148: switch (c->qid.path & ~CHDIR) {
149: case Qdir:
150: return devdirread(c, a, n, portdir, NPORT, devgen);
151: case Qdata:
152: if (!conf.portispaged || (s = offset >> PORTSHIFT) > 0xff)
153: s = -1;
154: k = offset % PORTSIZE;
155: P_qlock(s);
156: switch ((int)n) {
157: case 1:
158: *a = PORT[k]; break;
159: case 2:
160: *(short *)a = *(short *)(PORT+k); break;
161: case 4:
162: *(long *)a = *(long *)(PORT+k); break;
163: default:
164: P_qunlock(s);
165: error(Ebadarg);
166: }
167: P_qunlock(s);
168: break;
169: case Qrom:
170: if(offset >= ROMSIZE)
171: return 0;
172: if(offset+n > ROMSIZE)
173: n = ROMSIZE - offset;
174: memmove(a, ((char*)ROMADDR)+offset, n);
175: return n;
176: break;
177: default:
178: panic("portread");
179: }
180: return n;
181: }
182:
183: long
184: portwrite(Chan *c, char *a, long n, ulong offset)
185: {
186: long s, k;
187: if (n == 0)
188: return 0;
189: switch ((int)c->qid.path) {
190: case Qdata:
191: if (!conf.portispaged || (s = offset >> PORTSHIFT) > 0xff)
192: s = -1;
193: k = offset % PORTSIZE;
194: P_qlock(s);
195: switch ((int)n) {
196: case 1:
197: PORT[k] = *a; break;
198: case 2:
199: *(short *)(PORT+k) = *(short *)a;
200: break;
201: case 4:
202: *(long *)(PORT+k) = *(long *)a;
203: break;
204: default:
205: P_qunlock(s);
206: error(Ebadarg);
207: }
208: P_qunlock(s);
209: break;
210: default:
211: panic("portwrite");
212: }
213: return n;
214: }
215:
216: void
217: portremove(Chan *c)
218: {
219: USED(c);
220: error(Eperm);
221: }
222:
223: void
224: portwstat(Chan *c, char *dp)
225: {
226: USED(c, dp);
227: error(Eperm);
228: }
229:
230: void
231: addportintr(int (*f)(void))
232: {
233: int s = splhi();
234: int (**p)(void);
235:
236: lock(&intrlock);
237: for (p=portservice; *p; p++)
238: if (*p == f)
239: goto out;
240: if (p >= &portservice[Nportservice-1])
241: panic("addportintr");
242: *p = f;
243: out:
244: unlock(&intrlock);
245: splx(s);
246: }
247:
248: void
249: devportintr(void)
250: {
251: int (**p)(void);
252: int i = 0;
253:
254: for (p=portservice; *p; p++)
255: i |= (**p)();
256:
257: if (!i)
258: /*putstring("spurious portintr\n");*/
259: panic("portintr");
260: if (portpage.select >= 0)
261: PORTSELECT = portpage.select;
262: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.