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