|
|
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 <sys/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)) == NULL)
55: return;
56: lock (bp->b_gate);
57:
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: /*
71: * The dma address is 20 bits; 16 bit offset counter from a 4 bit
72: * base segment. Since io_ioc is limited to 32Kb positive, we
73: * have at most two raw transfers separated by a block which
74: * straddles the segment boundary.
75: * Life would be simpler if we assumed io_ioc % BSIZE, but
76: * flioctl comes through here with its short format buffer.
77: */
78: while (iop->io_ioc > 0 && (bp->b_flag&BFERR) == 0) {
79: /*
80: * If the first and last bytes to be read are on different
81: * dma segments, we have a stradle, and must read a fraction
82: * of the entire animal.
83: *
84: * I don't understand why a fractional block at the
85: * top of a segment is not read.
86: */
87: last = bp->b_paddr+iop->io_ioc-1;
88: if (dmaseg(last) != dmaseg(bp->b_paddr)) {
89: /*
90: * We have a straddle--read at most to the end
91: * of the next segment.
92: */
93: next_seg = dmaseg(bp->b_paddr + DMASEG_SIZE);
94: to_read = (next_seg - bp->b_paddr) & ~((long)BSIZE-1);
95: } else {
96: /* No straddle. */
97: to_read = iop->io_ioc;
98: }
99: next_block = blockn(iop->io_seek);
100: if (to_read == 0) {
101: /* Straddle block */
102: tbp = bp; /* Save the raw buffer */
103: to_read = BSIZE;
104: if (to_read > iop->io_ioc)
105: to_read = iop->io_ioc;
106: bp = bclaim (dev, next_block, BUF_SYNC);
107: bp->b_count = to_read;
108: bp->b_req = req;
109: if (req != BREAD)
110: ioread(iop, bp->b_vaddr, to_read);
111: dmabuf(bp, dev);
112: if ((bp->b_flag&BFERR) == 0) {
113: if (req == BREAD)
114: iowrite(iop, bp->b_vaddr, to_read);
115: } else {
116: tbp->b_flag = bp->b_flag;
117: tbp->b_err = bp->b_err;
118: if (req != BREAD)
119: iop->io_ioc += bp->b_resid;
120: }
121: bp->b_flag |= BFERR;
122: brelease(bp);
123: bp = tbp; /* Reclaim raw buffer */
124: } else {
125: /* Raw transfer */
126: bp->b_count = to_read;
127: bp->b_req = req;
128: bp->b_bno = next_block;
129: dmabuf(bp, dev);
130: if (bp->b_flag & BFERR)
131: to_read -= bp->b_resid;
132: iop->io_ioc -= to_read; /* cookedio do these */
133: iop->io.pbase += to_read; /* for everyone */
134: }
135: bp->b_vaddr += to_read;
136: bp->b_paddr += to_read;
137: iop->io_seek += to_read;
138: /* And continue for the next chunk */
139: }
140: sp->s_lrefc--;
141: if ( stimer.t_last != 0 )
142: wakeup((char *)&stimer);
143: if ((bp->b_flag&BFERR) && (u.u_error = bp->b_err) == 0)
144: SET_U_ERROR(EIO, "dmareq() BFERR");
145: out:
146: unlock(bp->b_gate);
147: }
148:
149: /*
150: * dmabuf()
151: *
152: * Hand off a buf request to the block handler and go to sleep.
153: */
154: static
155: dmabuf(bp, dev)
156: register BUF *bp;
157: dev_t dev;
158: {
159: register int s;
160:
161: bp->b_flag = BFRAW|BFBLK|BFIOC|BFNTP;
162: s = sphi();
163: dblock(dev, bp);
164: while (bp->b_flag&BFNTP)
165: x_sleep((char *)bp, pridisk, slpriNoSig, "dmabuf");
166: spl(s);
167: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.