|
|
1.1 root 1: /* dmareq.c */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 4.1.0
11: * Copyright (c) 1993.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15:
16: /*
17: * Like ioreq, but guarantee that no DMA straddle occurs.
18: * And assume we are called by fl.c, xt.c, dv.c or someone
19: * else who obeys the parameter rules that they do.
20: *
21: */
22: #include <sys/coherent.h>
23: #include <sys/buf.h>
24: #include <sys/con.h>
25: #include <errno.h>
26: #include <sys/io.h>
27: #include <sys/proc.h>
28: #include <sys/sched.h>
29: #include <sys/seg.h>
30: #include <sys/stat.h>
31: #include <sys/dmac.h>
32:
33: /*
34: * NIGEL: Why the hell is this routine not in bio.c? It would be a whole lot
35: * nicer if it was. "dold_t" is obsolete, by the way, and all instances of it
36: * will disappear from "bio.c" sometime. I should merge this in as well then.
37: */
38: typedef unsigned char dold_t;
39:
40: dmareq(bp, iop, dev, req)
41: register BUF *bp;
42: register IO *iop;
43: dev_t dev;
44: {
45: register int to_read;
46: register SEG *sp;
47: register CON *cp;
48: dold_t dold;
49: long next_block; /* Next block to be read. */
50: paddr_t last; /* Address of last byte we will read. */
51: paddr_t next_seg; /* Beginning of next dma segment. */
52: BUF *tbp;
53:
54: if ((cp=drvmap(dev, &dold)) == NULL)
55: return;
56: lock(bp->b_gate);
57: drest(dold);
58: if (blocko(iop->io_seek)) {
59: SET_U_ERROR(EIO, "dmareq() seek");
60: goto out;
61: }
62: if ((sp=iomapvp(iop, bp)) == NULL) {
63: SET_U_ERROR(EIO, "dmareq() iomapvp");
64: goto out;
65: }
66: bp->b_dev = dev;
67: bp->b_flag = 0;
68: sp->s_lrefc++;
69: /*
70: * The dma address is 20 bits; 16 bit offset counter from a 4 bit
71: * base segment. Since io_ioc is limited to 32Kb positive, we
72: * have at most two raw transfers separated by a block which
73: * straddles the segment boundary.
74: * Life would be simpler if we assumed io_ioc % BSIZE, but
75: * flioctl comes through here with its short format buffer.
76: */
77: while (iop->io_ioc > 0 && (bp->b_flag&BFERR) == 0) {
78: /*
79: * If the first and last bytes to be read are on different
80: * dma segments, we have a stradle, and must read a fraction
81: * of the entire animal.
82: *
83: * I don't understand why a fractional block at the
84: * top of a segment is not read.
85: */
86: last = bp->b_paddr+iop->io_ioc-1;
87: if (dmaseg(last) != dmaseg(bp->b_paddr)) {
88: /*
89: * We have a straddle--read at most to the end
90: * of the next segment.
91: */
92: next_seg = dmaseg(bp->b_paddr + DMASEG_SIZE);
93: to_read = (next_seg - bp->b_paddr) & ~((long)BSIZE-1);
94: } else {
95: /* No straddle. */
96: to_read = iop->io_ioc;
97: }
98: next_block = blockn(iop->io_seek);
99: if (to_read == 0) {
100: /* Straddle block */
101: tbp = bp; /* Save the raw buffer */
102: to_read = BSIZE;
103: if (to_read > iop->io_ioc)
104: to_read = iop->io_ioc;
105: bp = bclaim(dev, next_block);
106: bp->b_count = to_read;
107: bp->b_req = req;
108: if (req != BREAD)
109: ioread(iop, bp->b_vaddr, to_read);
110: dmabuf(bp, dev);
111: if ((bp->b_flag&BFERR) == 0) {
112: if (req == BREAD)
113: iowrite(iop, bp->b_vaddr, to_read);
114: } else {
115: tbp->b_flag = bp->b_flag;
116: tbp->b_err = bp->b_err;
117: if (req != BREAD)
118: iop->io_ioc += bp->b_resid;
119: }
120: bp->b_flag |= BFERR;
121: brelease(bp);
122: bp = tbp; /* Reclaim raw buffer */
123: } else {
124: /* Raw transfer */
125: bp->b_count = to_read;
126: bp->b_req = req;
127: bp->b_bno = next_block;
128: dmabuf(bp, dev);
129: if (bp->b_flag & BFERR)
130: to_read -= bp->b_resid;
131: iop->io_ioc -= to_read; /* cookedio do these */
132: iop->io.pbase += to_read; /* for everyone */
133: }
134: bp->b_vaddr += to_read;
135: bp->b_paddr += to_read;
136: iop->io_seek += to_read;
137: /* And continue for the next chunk */
138: }
139: sp->s_lrefc--;
140: if ( stimer.t_last != 0 )
141: wakeup((char *)&stimer);
142: if ((bp->b_flag&BFERR) && (u.u_error = bp->b_err) == 0)
143: SET_U_ERROR(EIO, "dmareq() BFERR");
144: out:
145: unlock(bp->b_gate);
146: }
147:
148: /*
149: * dmabuf()
150: *
151: * Hand off a buf request to the block handler and go to sleep.
152: */
153: static
154: dmabuf(bp, dev)
155: register BUF *bp;
156: dev_t dev;
157: {
158: register int s;
159:
160: bp->b_flag = BFRAW|BFBLK|BFIOC|BFNTP;
161: s = sphi();
162: dblock(dev, bp);
163: while (bp->b_flag&BFNTP)
164: x_sleep((char *)bp, pridisk, slpriNoSig, "dmabuf");
165: spl(s);
166: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.