|
|
1.1 root 1: /*
2: * Copyright (c) 1987, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: *
17: * @(#)vba.c 7.4 (Berkeley) 5/5/89
18: */
19:
20: /*
21: * Tahoe VERSAbus adapator support routines.
22: */
23:
24: #include "param.h"
25: #include "buf.h"
26: #include "cmap.h"
27: #include "conf.h"
28: #include "dk.h"
29: #include "map.h"
30: #include "systm.h"
31: #include "dir.h"
32: #include "user.h"
33: #include "vmparam.h"
34: #include "vmmac.h"
35: #include "proc.h"
36: #include "syslog.h"
37: #include "malloc.h"
38:
39: #include "../tahoe/mtpr.h"
40: #include "../tahoe/pte.h"
41:
42: #include "../tahoevba/vbavar.h"
43:
44: /*
45: * Allocate private page map and intermediate buffer
46: * for a VERSAbus device, large enough for maximum transfer size.
47: * Intermediate buffer
48: * Make intermediate buffer uncacheable.
49: */
50: vbainit(vb, xsize, flags)
51: register struct vb_buf *vb;
52: int xsize, flags;
53: {
54: register struct pte *pte;
55: register n;
56:
57: vb->vb_flags = flags;
58: if (vbmapalloc((int)btoc(xsize) + 1, &vb->vb_map, &vb->vb_utl) == 0) {
59: printf("vbmap exhausted\n");
60: return (0);
61: }
62: n = roundup(xsize, NBPG);
63: vb->vb_bufsize = n;
64: if (vb->vb_rawbuf == 0)
65: vb->vb_rawbuf = (caddr_t)malloc((u_long)n, M_DEVBUF, M_NOWAIT);
66: if (vb->vb_rawbuf == 0) {
67: printf("no memory for device buffer\n");
68: return (0);
69: }
70: if ((int)vb->vb_rawbuf & PGOFSET)
71: panic("vbinit pgoff");
72: vb->vb_physbuf = (u_long)kvtophys(vb->vb_rawbuf);
73: if (flags & VB_20BIT)
74: vb->vb_maxphys = btoc(VB_MAXADDR20);
75: else if (flags & VB_24BIT)
76: vb->vb_maxphys = btoc(VB_MAXADDR24);
77: else
78: vb->vb_maxphys = btoc(VB_MAXADDR32);
79: if (btoc(vb->vb_physbuf + n) > vb->vb_maxphys)
80: panic("vbinit physbuf");
81:
82: /*
83: * Make raw buffer pages uncacheable.
84: */
85: pte = kvtopte(vb->vb_rawbuf);
86: for (n = btoc(n); n--; pte++)
87: pte->pg_nc = 1;
88: mtpr(TBIA, 0);
89: return (1);
90: }
91:
92: /*
93: * Due to unknown hardware or software errors, some sites have problems
94: * with strange crashes or corruption of text images when DMA is attempted
95: * to kernel addresses spanning a page boundary, or to user addresses
96: * (even if the buffer is physically contiguous). To avoid this behavior,
97: * the following toggles inhibit such transfers when set.
98: * vba_copyk: copy transfers to kernel address that span a page boundary
99: * vba_copyu: copy transfers to user addresses
100: */
101: #ifndef VBA_TRICKY
102: int vba_copyk = 1;
103: int vba_copyu = 1;
104: #else
105: int vba_copyk = 0;
106: int vba_copyu = 0;
107: #endif
108:
109: /*
110: * Check a transfer to see whether it can be done directly
111: * to the destination buffer, or whether it must be copied.
112: * On Tahoe, the lack of a bus I/O map forces data to be copied
113: * to a physically-contiguous buffer whenever one of the following is true:
114: * 1) The data length is not a multiple of sector size.
115: * (The swapping code does this, unfortunately.)
116: * 2) The buffer is not physically contiguous and the controller
117: * does not support scatter-gather operations.
118: * 3) The physical address for I/O is higher than addressible
119: * by the device.
120: * This routine is called by the start routine.
121: * If copying is necessary, the intermediate buffer is mapped;
122: * if the operation is a write, the data is copied into the buffer.
123: * It returns the physical address of the first byte for DMA, to
124: * be presented to the controller.
125: */
126: u_long
127: vbasetup(bp, vb, sectsize)
128: register struct buf *bp;
129: register struct vb_buf *vb;
130: int sectsize;
131: {
132: register struct pte *spte, *dpte;
133: register int p, i;
134: int npf, o, v;
135:
136: o = (int)bp->b_un.b_addr & PGOFSET;
137: npf = btoc(bp->b_bcount + o);
138: vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);
139: if (vb->vb_iskernel) {
140: spte = kvtopte(bp->b_un.b_addr);
141: if (vba_copyk && (o != 0 || npf > 1)) goto copy;
142: } else {
143: spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,
144: btop(bp->b_un.b_addr));
145: if (vba_copyu) goto copy;
146: }
147: if (bp->b_bcount % sectsize != 0 || (o & (sizeof(long) - 1)) != 0)
148: goto copy;
149: else if ((vb->vb_flags & VB_SCATTER) == 0 ||
150: vb->vb_maxphys != btoc(VB_MAXADDR32)) {
151: dpte = spte;
152: p = (dpte++)->pg_pfnum;
153: for (i = npf; --i > 0; dpte++) {
154: if ((v = dpte->pg_pfnum) != p + CLSIZE &&
155: (vb->vb_flags & VB_SCATTER) == 0)
156: goto copy;
157: if (p >= vb->vb_maxphys)
158: goto copy;
159: p = v;
160: }
161: if (p >= vb->vb_maxphys)
162: goto copy;
163: }
164: vb->vb_copy = 0;
165: if (vb->vb_iskernel)
166: vbastat.k_raw++;
167: else
168: vbastat.u_raw++;
169: return ((spte->pg_pfnum << PGSHIFT) + o);
170:
171: copy:
172: vb->vb_copy = 1;
173: if (bp->b_bcount > vb->vb_bufsize)
174: panic("vba xfer too large");
175: if (vb->vb_iskernel) {
176: if ((bp->b_flags & B_READ) == 0)
177: bcopy(bp->b_un.b_addr, vb->vb_rawbuf,
178: (unsigned)bp->b_bcount);
179: vbastat.k_copy++;
180: } else {
181: dpte = vb->vb_map;
182: for (i = npf, p = (int)vb->vb_utl; i--; p += NBPG) {
183: *(int *)dpte++ = (spte++)->pg_pfnum |
184: PG_V | PG_KW | PG_N;
185: mtpr(TBIS, p);
186: }
187: if ((bp->b_flags & B_READ) == 0)
188: bcopy(vb->vb_utl + o, vb->vb_rawbuf,
189: (unsigned)bp->b_bcount);
190: vbastat.u_copy++;
191: }
192: return (vb->vb_physbuf);
193: }
194:
195: /*
196: * Called by the driver's interrupt routine, after DMA is completed.
197: * If the operation was a read, copy data to final buffer if necessary
198: * or invalidate data cache for cacheable direct buffers.
199: * Similar to the vbastart routine, but in the reverse direction.
200: */
201: vbadone(bp, vb)
202: register struct buf *bp;
203: register struct vb_buf *vb;
204: {
205: register npf;
206: register caddr_t v;
207: int o;
208:
209: if (bp->b_flags & B_READ) {
210: o = (int)bp->b_un.b_addr & PGOFSET;
211: if (vb->vb_copy) {
212: if (vb->vb_iskernel)
213: bcopy(vb->vb_rawbuf, bp->b_un.b_addr,
214: (unsigned)(bp->b_bcount - bp->b_resid));
215: else {
216: bcopy(vb->vb_rawbuf, vb->vb_utl + o,
217: (unsigned)(bp->b_bcount - bp->b_resid));
218: dkeyinval(bp->b_proc);
219: }
220: } else {
221: if (vb->vb_iskernel) {
222: npf = btoc(bp->b_bcount + o);
223: for (v = bp->b_un.b_addr; npf--; v += NBPG)
224: mtpr(P1DC, (int)v);
225: } else
226: dkeyinval(bp->b_proc);
227: }
228: }
229: }
230:
231: /*
232: * Set up a scatter-gather operation for SMD/E controller.
233: * This code belongs half-way between {hd,vd}.c and this file.
234: */
235:
236: #include "dk.h"
237: #if NVD > 0
238: #include "vdreg.h"
239:
240: vd_sgsetup(bp, vb, sg)
241: register struct buf *bp;
242: struct vb_buf *vb;
243: struct trsg *sg;
244: {
245: register struct pte *spte;
246: register struct addr_chain *adr;
247: register int i;
248: int o;
249:
250: vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);
251: vb->vb_copy = 0;
252: if (vb->vb_iskernel) {
253: spte = kvtopte(bp->b_un.b_addr);
254: vbastat.k_sg++;
255: } else {
256: spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,
257: btop(bp->b_un.b_addr));
258: vbastat.u_sg++;
259: }
260:
261: o = (int)bp->b_un.b_addr & PGOFSET;
262: i = min(NBPG - o, bp->b_bcount);
263: sg->start_addr.wcount = i >> 1;
264: sg->start_addr.memadr = ((spte++)->pg_pfnum << PGSHIFT) + o;
265: i = bp->b_bcount - i;
266: if (i > VDMAXPAGES * NBPG)
267: panic("vba xfer too large");
268: i = i >> 1;
269: for (adr = sg->addr_chain; i > 0; adr++, i -= NBPG / 2) {
270: adr->nxt_addr = (spte++)->pg_pfnum << PGSHIFT;
271: adr->nxt_len = imin(i, NBPG / 2);
272: }
273: adr->nxt_addr = 0;
274: adr++->nxt_len = 0;
275: return ((adr - sg->addr_chain) * sizeof(*adr) / sizeof(long));
276: }
277: #endif
278:
279: #include "hd.h"
280: #if NHD > 0
281: #include "hdreg.h"
282:
283: hd_sgsetup(bp, vb, sg)
284: register struct buf *bp;
285: struct vb_buf *vb;
286: struct chain *sg;
287: {
288: register struct pte *spte;
289: register struct addr_chain *adr;
290: register int i, cnt;
291: int o;
292:
293: if (bp->b_bcount > HDC_MAXBC ||
294: bp->b_bcount % sizeof(long) - 1 ||
295: (u_int)bp->b_un.b_addr % sizeof(long) - 1)
296: return(0);
297:
298: vb->vb_iskernel = (((int)bp->b_un.b_addr & KERNBASE) == KERNBASE);
299: vb->vb_copy = 0;
300: if (vb->vb_iskernel) {
301: spte = kvtopte(bp->b_un.b_addr);
302: vbastat.k_sg++;
303: } else {
304: spte = vtopte((bp->b_flags&B_DIRTY) ? &proc[2] : bp->b_proc,
305: btop(bp->b_un.b_addr));
306: vbastat.u_sg++;
307: }
308:
309: o = (int)bp->b_un.b_addr & PGOFSET;
310: i = min(NBPG - o, bp->b_bcount);
311: sg->wcount = i >> 2;
312: sg->memadr = ((spte++)->pg_pfnum << PGSHIFT) + o;
313: cnt = 0;
314: for (i = (bp->b_bcount - i) >> 2; i > 0; i -= NBPG / sizeof(long)) {
315: if (++cnt == HDC_MAXCHAIN)
316: return(0);
317: sg->wcount |= LWC_DATA_CHAIN;
318: ++sg;
319: sg->wcount = imin(i, NBPG / sizeof(long));
320: sg->memadr = (spte++)->pg_pfnum << PGSHIFT;
321: }
322: return(1);
323: }
324: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.