|
|
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.