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