|
|
1.1 root 1: /* $Header: /kernel/kersrc/io.386/RCS/dmareq.c,v 1.2 92/08/04 12:52:39 bin Exp Locker: bin $ */
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 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
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: * $Log: dmareq.c,v $
22: * Revision 1.2 92/08/04 12:52:39 bin
23: * update for ker59
24: *
25: * Revision 1.2 92/01/06 12:26:52 hal
26: * Compile with cc.mwc.
27: *
28: * Revision 2.1 88/09/03 13:03:47 src
29: * *** empty log message ***
30: *
31: * Revision 1.1 88/03/24 17:04:28 src
32: * Initial revision
33: *
34: * 87/11/25 Allan Cornish /usr/src/sys/i8086/drv/dmareq.c
35: * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
36: *
37: * 87/01/05 Allan Cornish /usr/src/sys/i8086/drv/dmareq.c
38: * dmareq() now wakes &stimer only if the swap timer is active.
39: */
40: #include <sys/coherent.h>
41: #include <sys/buf.h>
42: #include <sys/con.h>
43: #include <errno.h>
44: #include <sys/io.h>
45: #include <sys/proc.h>
46: #include <sys/sched.h>
47: #include <sys/seg.h>
48: #include <sys/stat.h>
49: #include <sys/dmac.h>
50:
51: dmareq(bp, iop, dev, req)
52: register BUF *bp;
53: register IO *iop;
54: dev_t dev;
55: {
56: register int to_read;
57: register SEG *sp;
58: register CON *cp;
59: dold_t dold;
60: long next_block; /* Next block to be read. */
61: paddr_t last; /* Address of last byte we will read. */
62: paddr_t next_seg; /* Beginning of next dma segment. */
63: BUF *tbp;
64:
65: if ((cp=drvmap(dev, &dold)) == NULL)
66: return;
67: lock(bp->b_gate);
68: drest(dold);
69: if (blocko(iop->io_seek) != 0) {
70: u.u_error = EIO;
71: goto out;
72: }
73: if ((sp=iomapvp(iop, bp)) == NULL) {
74: u.u_error = EIO;
75: goto out;
76: }
77: bp->b_dev = dev;
78: bp->b_flag = 0;
79: sp->s_lrefc++;
80: /*
81: * The dma address is 20 bits; 16 bit offset counter from a 4 bit
82: * base segment. Since io_ioc is limited to 32Kb positive, we
83: * have at most two raw transfers separated by a block which
84: * straddles the segment boundary.
85: * Life would be simpler if we assumed io_ioc % BSIZE, but
86: * flioctl comes through here with it's short format buffer.
87: */
88: while (iop->io_ioc > 0 && (bp->b_flag&BFERR) == 0) {
89: /*
90: * If the first and last bytes to be read are on different
91: * dma segments, we have a stradle, and must read a fraction
92: * of the entire animal.
93: *
94: * I don't understand why a fractional block at the
95: * top of a segment is not read.
96: */
97: last = bp->b_paddr+iop->io_ioc-1;
98: if (dmaseg(last) != dmaseg(bp->b_paddr)) {
99: /*
100: * We have a straddle--read at most to the end
101: * of the next segment.
102: */
103: next_seg = dmaseg(bp->b_paddr + DMASEG_SIZE);
104: to_read = (next_seg - bp->b_paddr) & ~((long)BSIZE-1);
105: } else {
106: /* No straddle. */
107: to_read = iop->io_ioc;
108: }
109: next_block = blockn(iop->io_seek);
110: if (to_read == 0) {
111: /* Straddle block */
112: tbp = bp; /* Save the raw buffer */
113: to_read = BSIZE;
114: if (to_read > iop->io_ioc)
115: to_read = iop->io_ioc;
116: bp = bclaim(dev, next_block);
117: bp->b_count = to_read;
118: bp->b_req = req;
119: if (req != BREAD)
120: ioread(iop, bp->b_vaddr, to_read);
121: dmabuf(bp, dev);
122: if ((bp->b_flag&BFERR) == 0) {
123: if (req == BREAD)
124: iowrite(iop, bp->b_vaddr, to_read);
125: } else {
126: tbp->b_flag = bp->b_flag;
127: tbp->b_err = bp->b_err;
128: if (req != BREAD)
129: iop->io_ioc += bp->b_resid;
130: }
131: bp->b_flag |= BFERR;
132: brelease(bp);
133: bp = tbp; /* Reclaim raw buffer */
134: } else {
135: /* Raw transfer */
136: bp->b_count = to_read;
137: bp->b_req = req;
138: bp->b_bno = next_block;
139: dmabuf(bp, dev);
140: if ((bp->b_flag&BFERR) != 0)
141: to_read -= bp->b_resid;
142: iop->io_ioc -= to_read; /* cookedio do these */
143: iop->io.pbase += to_read; /* for everyone */
144: }
145: bp->b_vaddr += to_read;
146: bp->b_paddr += to_read;
147: iop->io_seek += to_read;
148: /* And continue for the next chunk */
149: }
150: sp->s_lrefc--;
151: if ( stimer.t_last != 0 )
152: wakeup((char *)&stimer);
153: if ((bp->b_flag&BFERR) != 0 && (u.u_error = bp->b_err) == 0)
154: u.u_error = EIO;
155: out:
156: unlock(bp->b_gate);
157: }
158:
159: static
160: dmabuf(bp, dev)
161: register BUF *bp;
162: dev_t dev;
163: {
164: register int s;
165: bp->b_flag = BFRAW|BFBLK|BFIOC|BFNTP;
166: s = sphi();
167: dblock(dev, bp);
168: while ((bp->b_flag&BFNTP) != 0)
169: sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
170: spl(s);
171: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.