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