|
|
1.1 root 1: /*
2: * these routines are written in C until the 386 compiler/assembler
3: * are available
4: *
5: * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
6: */
7:
8: #include <sys/coherent.h>
9: #include <sys/reg.h>
10: #include <sys/clist.h>
11: #include <errno.h>
12: #include <sys/inode.h>
13: #include <sys/proc.h>
14: #include <sys/seg.h>
15: #include <signal.h>
16: #include <sys/uproc.h>
17: #include <sys/buf.h>
18:
19: #define min(a, b) ((a) < (b) ? (a) : (b))
20:
21: /*
22: * dmacopy()
23: *
24: * Copy "npage" 4 kbyte pages from phys addr "from" to phys addr "to".
25: */
26: dmacopy(npage, from, to)
27: long npage;
28: cseg_t *from, *to;
29: {
30: int save = setspace(SEG_386_KD);
31:
32: while (npage--) {
33: int work = workAlloc(); /* Get a virtual click pair. */
34: ptable1_v[work] = *from++ | SEG_SRW;
35: ptable1_v[work + 1] = *to++ | SEG_SRW;
36: mmuupd();
37: copyseg_d(NBPC, ctob(work), ctob(work + 1));
38: workFree(work);
39: }
40: setspace(save);
41: }
42:
43: /*
44: * dmaclear()
45: *
46: * Given a byte count, a system global address, and a fill value,
47: * write the fill value through the given range of memory.
48: */
49: dmaclear(nbytes, to, fill)
50: long nbytes, fill;
51: paddr_t to;
52: {
53: unsigned off;
54: int n;
55: cseg_t *base;
56: int save = setspace(SEG_386_KD);
57: int work = workAlloc(); /* Get a virtual click pair. */
58:
59: off = to & (NBPC-1);
60: base = &sysmem.u.pbase[btocrd(to)];
61: n = min(nbytes, NBPC-off);
62: ptable1_v[work] = *base++ | SEG_SRW;
63: mmuupd();
64:
65: clearseg_d(n, ctob(work)+off, fill);
66: nbytes -= n;
67:
68: while (nbytes >= NBPC) {
69: ptable1_v[work] = *base++ | SEG_SRW;
70: mmuupd();
71: clearseg_d(NBPC, ctob(work), fill);
72: nbytes -= NBPC;
73: }
74:
75: if (nbytes) {
76: ptable1_v[work] = *base++ | SEG_SRW;
77: mmuupd();
78: clearseg_d(nbytes, ctob(work), fill);
79: }
80: setspace(save);
81: workFree(work);
82: }
83:
84: /*
85: * dmain()
86: *
87: * Copy in "nbytes" from system global address "to" to kernel address
88: * "vaddr".
89: */
90: dmain(nbytes, to, vaddr)
91: long nbytes;
92: paddr_t to;
93: caddr_t vaddr;
94: {
95: unsigned off;
96: unsigned n, n1;
97: cseg_t* base;
98: int work = workAlloc(); /* Get a virtual click pair. */
99: int save = setspace(SEG_386_KD);
100:
101: off = to & (NBPC-1);
102: base = &sysmem.u.pbase[btocrd(to)];
103:
104: n = min(nbytes, NBPC-off);
105: ptable1_v[work] = *base++ | SEG_SRW;
106: mmuupd();
107:
108: if (nbytes==n) {
109: /*
110: * only one page
111: * n = min(n & (sizeof(long)-1), n)
112: * copy n bytes; nbytes -= n;
113: * copy (nbytes >> 2) long words; nbytes &= sizeof(long)-1
114: * copy nbytes bytes
115: */
116: if (n >= sizeof(long))
117: n &= sizeof(long)-1;
118: if (n)
119: copyseg_b(n, ctob(work)+off, vaddr);
120: off += n;
121: vaddr += n;
122: nbytes -= n;
123: if (n = nbytes & ~(sizeof(long)-1)) {
124: copyseg_d(n, ctob(work)+off, vaddr);
125: off += n;
126: vaddr += n;
127: nbytes -= n;
128: }
129: } else {
130: /*
131: * more than one page
132: * copy n&3 bytes
133: * copy n >> 2 long words
134: * in the first page
135: */
136: if (n1 = n & 3)
137: copyseg_b(n1, ctob(work)+off, vaddr);
138: off += n1;
139: vaddr += n1;
140: nbytes -= n1;
141: if (n = n & ~(sizeof(long)-1)) {
142: copyseg_d(n, ctob(work)+off, vaddr);
143: off += n;
144: vaddr += n;
145: nbytes -= n;
146: }
147:
148: /*
149: * copy nbytes>>BPCSHIFT full pages
150: */
151: while (nbytes >= NBPC) {
152: ptable1_v[work] = *base++ | SEG_SRW;
153: mmuupd();
154:
155: copyseg_d(NBPC, ctob(work), vaddr);
156: vaddr += NBPC;
157: nbytes -= NBPC;
158: }
159: /*
160: * page n-1 (last one)
161: *
162: * copy nbytes>>2 long words
163: * copy nbytes & 3 bytes
164: */
165: ptable1_v[work] = *base++ | SEG_SRW;
166: mmuupd();
167:
168: if (n = nbytes & ~(sizeof(long)-1)) {
169: copyseg_d(n, ctob(work), vaddr);
170: vaddr += n;
171: nbytes -= n;
172: }
173: if (nbytes)
174: copyseg_b(nbytes, ctob(work)+n, vaddr);
175: }
176:
177: setspace(save);
178: workFree(work);
179: }
180:
181: /*
182: * dmaout()
183: *
184: * Copy out "nbytes" from kernel address "vaddr" to system global address
185: * "to".
186: */
187: dmaout(nbytes, to, vaddr)
188: long nbytes;
189: paddr_t to;
190: caddr_t vaddr;
191: {
192: unsigned off;
193: unsigned n, n1;
194: cseg_t *base;
195: int work = workAlloc(); /* Get a virtual click pair. */
196: int save = setspace(SEG_386_KD);
197:
198: off = to & (NBPC-1);
199: base = &sysmem.u.pbase[btocrd(to)];
200:
201: n = min(nbytes, NBPC-off);
202: ptable1_v[work] = *base++ | SEG_SRW;
203: mmuupd();
204:
205: if (nbytes==n) {
206: /*
207: * only one page
208: * n = min(n & (sizeof(long)-1), n)
209: * copy n bytes; nbytes -= n;
210: * copy (nbytes >> 2) long words; nbytes &= sizeof(long)-1
211: * copy nbytes bytes
212: */
213: if (n1 = n & (sizeof(long)-1))
214: copyseg_b(n1, vaddr, ctob(work)+off);
215: off += n1;
216: vaddr += n1;
217: nbytes -= n1;
218: if (n = nbytes & ~(sizeof(long)-1)) {
219: copyseg_d(n, vaddr, ctob(work)+off);
220: off += n;
221: vaddr += n;
222: nbytes -= n;
223: }
224: } else {
225: /*
226: * more than one page
227: * copy n&3 bytes
228: * copy n >> 2 long words
229: * in the first page
230: */
231: if (n1 = n & (sizeof(long)-1))
232: copyseg_b(n1, vaddr, ctob(work)+off);
233: off += n1;
234: vaddr += n1;
235: nbytes -= n1;
236: if (n = n & ~(sizeof(long)-1)) {
237: copyseg_d(n, vaddr, ctob(work)+off);
238: off += n;
239: vaddr += n;
240: nbytes -= n;
241: }
242:
243: /*
244: * copy nbytes>>BPCSHIFT full pages
245: */
246: while (nbytes >= NBPC) {
247: ptable1_v[work] = *base++ | SEG_SRW;
248: mmuupd();
249: copyseg_d(NBPC, vaddr, ctob(work));
250: vaddr += NBPC;
251: nbytes -= NBPC;
252: }
253:
254: /* now the transfer to memory is click-aligned */
255: off = 0;
256:
257: /*
258: * page n-1 (last one)
259: *
260: * copy nbytes>>2 long words
261: * copy nbytes & 3 bytes
262: */
263: ptable1_v[work] = *base++ | SEG_SRW;
264: mmuupd();
265:
266: if (n = nbytes & ~(sizeof(long)-1)) {
267: copyseg_d(n, vaddr, ctob(work));
268: vaddr += n;
269: off += n;
270: nbytes -= n;
271: }
272: if (nbytes)
273: copyseg_b(nbytes, vaddr, ctob(work)+off);
274: }
275:
276: setspace(save);
277: workFree(work);
278: }
279:
280: /*
281: * dmaio2()
282: *
283: * Copy in "nbytes" from an I/O port "port" to the system global address
284: * "to".
285: */
286: dmaio2(nbytes, to, port)
287: long nbytes, port;
288: paddr_t to;
289: {
290: unsigned off;
291: int n;
292: cseg_t *base;
293: int save = setspace(SEG_386_KD);
294: int work = workAlloc(); /* Get a virtual click pair. */
295:
296: off = to & (NBPC-1);
297: base = &sysmem.u.pbase[btocrd(to)];
298:
299: n = min(nbytes, NBPC-off);
300: ptable1_v[work] = *base++ | SEG_SRW;
301: mmuupd();
302:
303: io2seg(n, ctob(work)+off, port);
304: nbytes -= n;
305:
306: while (nbytes >= NBPC) {
307: ptable1_v[work] = *base++ | SEG_SRW;
308: mmuupd();
309: io2seg(NBPC, ctob(work), port);
310: nbytes -= NBPC;
311: }
312:
313: if (nbytes) {
314: ptable1_v[work] = *base++ | SEG_SRW;
315: mmuupd();
316: io2seg(nbytes, ctob(work), port);
317: }
318: setspace(save);
319: workFree(work);
320: }
321:
322: /*
323: * dma2io()
324: *
325: * Copy out "nbytes" from the system global address "from" to an I/O port
326: * "port".
327: */
328: dma2io(nbytes, to, port)
329: long nbytes, port;
330: paddr_t to;
331: {
332: unsigned off;
333: int n;
334: cseg_t *base;
335: int save = setspace(SEG_386_KD);
336: int work = workAlloc(); /* Get a virtual click pair. */
337:
338: off = to & (NBPC-1);
339: base = &sysmem.u.pbase[btocrd(to)];
340:
341: n = min(nbytes, NBPC-off);
342: ptable1_v[work] = *base++ | SEG_SRW;
343: mmuupd();
344:
345: seg2io(n, ctob(work)+off, port);
346: nbytes -= n;
347:
348: while (nbytes >= NBPC) {
349: ptable1_v[work] = *base++ | SEG_SRW;
350: mmuupd();
351: seg2io(NBPC, ctob(work), port);
352: nbytes -= NBPC;
353: }
354:
355: if (nbytes) {
356: ptable1_v[work] = *base++ | SEG_SRW;
357: mmuupd();
358: seg2io(nbytes, ctob(work), port);
359: }
360: setspace(save);
361: workFree(work);
362: }
363:
364: /*
365: * pxcopy()
366: *
367: * copy "n" bytes of data at kernel address "v" from address "uo" in:
368: * system global address space (space&SEG_VIRT)
369: * physical memory !(space&SEG_VIRT)
370: * Rights are determined by (space&~SEG_VIRT):
371: * "v" can be anywhere in kernel address space SEG_386_KD
372: * "v" must be an address accessible to the user SEG_386_UD
373: * Up to one click of data can be copied. No alignment restrictions
374: * on "uo" apply.
375: */
376: pxcopy(uo, v, n, space)
377: unsigned uo;
378: char *v;
379: register int n;
380: {
381: cseg_t *base;
382: register int save, err;
383: int work;
384:
385: if (n > NBPC)
386: return 0;
387:
388: work = workAlloc();
389: if (space & SEG_VIRT) {
390: space &= ~SEG_VIRT;
391: base = &sysmem.u.pbase[btocrd(uo)];
392: ptable1_v[work] = *base++ | SEG_SRW;
393: ptable1_v[work + 1] = *base++ | SEG_SRW;
394: } else {
395: ptable1_v[work] = (uo&~(NBPC-1)) + SEG_SRW;
396: ptable1_v[work + 1] = (uo&~(NBPC-1)) + NBPC + SEG_SRW;
397: }
398: mmuupd();
399: save = setspace(space);
400:
401: err = ukcopy(ctob(work) + (uo&(NBPC-1)), v, n);
402: setspace(save);
403: workFree(work);
404: return err;
405: }
406:
407: /*
408: * xpcopy()
409: *
410: * copy "n" bytes of data from kernel address "v" to address "uo" in:
411: * system global address space (space&SEG_VIRT)
412: * physical memory !(space&SEG_VIRT)
413: * Rights are determined by (space&~SEG_VIRT):
414: * "v" can be anywhere in kernel address space SEG_386_KD
415: * "v" must be an address accessible to the user SEG_386_UD
416: * Up to one click of data can be copied. No alignment restrictions on "uo"
417: * apply.
418: */
419: xpcopy(v, uo, n, space)
420: char *v;
421: unsigned uo;
422: register int n;
423: {
424: register cseg_t *base;
425: register int save, err;
426: int work;
427:
428: if (n > NBPC)
429: return 0;
430:
431: work = workAlloc();
432: if (space & SEG_VIRT) {
433: space &= ~SEG_VIRT;
434: base = &sysmem.u.pbase[btocrd(uo)];
435: ptable1_v[work] = *base++ | SEG_SRW;
436: ptable1_v[work + 1] = *base++ | SEG_SRW;
437: } else {
438: ptable1_v[work] = (uo&~(NBPC-1)) + SEG_SRW;
439: ptable1_v[work + 1] = (uo&~(NBPC-1)) + NBPC + SEG_SRW;
440: }
441: mmuupd();
442: save = setspace(space);
443:
444: err = kucopy(v, ctob(work) + (uo&(NBPC-1)), n);
445: setspace(save);
446: workFree(work);
447: return err;
448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.