126f9a767SRodney W. Grimes /* 226f9a767SRodney W. Grimes * Copyright (c) 1994 John S. Dyson 326f9a767SRodney W. Grimes * All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 6df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 7df8bae1dSRodney W. Grimes * are met: 8df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 926f9a767SRodney W. Grimes * notice immediately at the beginning of the file, without modification, 1026f9a767SRodney W. Grimes * this list of conditions, and the following disclaimer. 11df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 12df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 13df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1426f9a767SRodney W. Grimes * 3. Absolutely no warranty of function or purpose is made by the author 1526f9a767SRodney W. Grimes * John S. Dyson. 1626f9a767SRodney W. Grimes * 4. Modifications may be freely made to this file if the above conditions 1726f9a767SRodney W. Grimes * are met. 183c4dd356SDavid Greenman * 197d7bb69dSDavid Greenman * $Id: kern_physio.c,v 1.5 1994/08/07 13:10:31 davidg Exp $ 20df8bae1dSRodney W. Grimes */ 21df8bae1dSRodney W. Grimes 22df8bae1dSRodney W. Grimes #include <sys/param.h> 23df8bae1dSRodney W. Grimes #include <sys/systm.h> 24df8bae1dSRodney W. Grimes #include <sys/buf.h> 25df8bae1dSRodney W. Grimes #include <sys/conf.h> 26df8bae1dSRodney W. Grimes #include <sys/proc.h> 2726f9a767SRodney W. Grimes #include <vm/vm.h> 28df8bae1dSRodney W. Grimes 2926f9a767SRodney W. Grimes static void physwakeup(); 30a481f200SDavid Greenman u_int minphys(struct buf *bp); 3126f9a767SRodney W. Grimes 3226f9a767SRodney W. Grimes int 3326f9a767SRodney W. Grimes physio(strategy, bp, dev, rw, minp, uio) 3426f9a767SRodney W. Grimes int (*strategy)(); 3526f9a767SRodney W. Grimes struct buf *bp; 3626f9a767SRodney W. Grimes dev_t dev; 3726f9a767SRodney W. Grimes int rw; 3826f9a767SRodney W. Grimes u_int (*minp)(); 3926f9a767SRodney W. Grimes struct uio *uio; 40df8bae1dSRodney W. Grimes { 4126f9a767SRodney W. Grimes int i; 4226f9a767SRodney W. Grimes int bufflags = rw?B_READ:0; 4326f9a767SRodney W. Grimes int error; 4426f9a767SRodney W. Grimes int spl; 4516f62314SDavid Greenman caddr_t sa; 4616f62314SDavid Greenman int bp_alloc = (bp == 0); 4716f62314SDavid Greenman struct buf *bpa; 48df8bae1dSRodney W. Grimes 49df8bae1dSRodney W. Grimes /* 5026f9a767SRodney W. Grimes * keep the process from being swapped 51df8bae1dSRodney W. Grimes */ 5226f9a767SRodney W. Grimes curproc->p_flag |= P_PHYSIO; 5326f9a767SRodney W. Grimes 5426f9a767SRodney W. Grimes /* create and build a buffer header for a transfer */ 5516f62314SDavid Greenman bpa = (struct buf *)getpbuf(); 5616f62314SDavid Greenman if (!bp_alloc) { 5726f9a767SRodney W. Grimes spl = splbio(); 5826f9a767SRodney W. Grimes while (bp->b_flags & B_BUSY) { 5926f9a767SRodney W. Grimes bp->b_flags |= B_WANTED; 6026f9a767SRodney W. Grimes tsleep((caddr_t)bp, PRIBIO, "physbw", 0); 6126f9a767SRodney W. Grimes } 6226f9a767SRodney W. Grimes bp->b_flags |= B_BUSY; 6326f9a767SRodney W. Grimes splx(spl); 6416f62314SDavid Greenman } else { 6516f62314SDavid Greenman bp = bpa; 6626f9a767SRodney W. Grimes } 6726f9a767SRodney W. Grimes 6816f62314SDavid Greenman /* 6916f62314SDavid Greenman * get a copy of the kva from the physical buffer 7016f62314SDavid Greenman */ 7116f62314SDavid Greenman sa = bpa->b_data; 7226f9a767SRodney W. Grimes bp->b_proc = curproc; 7326f9a767SRodney W. Grimes bp->b_dev = dev; 7426f9a767SRodney W. Grimes error = bp->b_error = 0; 7526f9a767SRodney W. Grimes 7626f9a767SRodney W. Grimes for(i=0;i<uio->uio_iovcnt;i++) { 7726f9a767SRodney W. Grimes while( uio->uio_iov[i].iov_len) { 7826f9a767SRodney W. Grimes vm_offset_t v, lastv, pa; 7926f9a767SRodney W. Grimes caddr_t adr; 8026f9a767SRodney W. Grimes 8126f9a767SRodney W. Grimes bp->b_bcount = uio->uio_iov[i].iov_len; 82a481f200SDavid Greenman bp->b_bcount = minp( bp); 83a481f200SDavid Greenman if( minp != minphys) 84a481f200SDavid Greenman bp->b_bcount = minphys( bp); 8526f9a767SRodney W. Grimes bp->b_bufsize = bp->b_bcount; 8626f9a767SRodney W. Grimes bp->b_flags = B_BUSY | B_PHYS | B_CALL | bufflags; 8726f9a767SRodney W. Grimes bp->b_iodone = physwakeup; 8826f9a767SRodney W. Grimes bp->b_data = uio->uio_iov[i].iov_base; 8916f62314SDavid Greenman /* 9016f62314SDavid Greenman * pass in the kva from the physical buffer 9116f62314SDavid Greenman * for the temporary kernel mapping. 9216f62314SDavid Greenman */ 9316f62314SDavid Greenman bp->b_saveaddr = sa; 9426f9a767SRodney W. Grimes bp->b_blkno = btodb(uio->uio_offset); 9526f9a767SRodney W. Grimes 9626f9a767SRodney W. Grimes 9726f9a767SRodney W. Grimes if (rw && !useracc(bp->b_data, bp->b_bufsize, B_WRITE)) { 9826f9a767SRodney W. Grimes error = EFAULT; 9926f9a767SRodney W. Grimes goto doerror; 10026f9a767SRodney W. Grimes } 10126f9a767SRodney W. Grimes if (!rw && !useracc(bp->b_data, bp->b_bufsize, B_READ)) { 10226f9a767SRodney W. Grimes error = EFAULT; 10326f9a767SRodney W. Grimes goto doerror; 10426f9a767SRodney W. Grimes } 10526f9a767SRodney W. Grimes 10626f9a767SRodney W. Grimes vmapbuf(bp); 10726f9a767SRodney W. Grimes 10826f9a767SRodney W. Grimes /* perform transfer */ 10926f9a767SRodney W. Grimes (*strategy)(bp); 11026f9a767SRodney W. Grimes 11126f9a767SRodney W. Grimes spl = splbio(); 11226f9a767SRodney W. Grimes while ((bp->b_flags & B_DONE) == 0) 11326f9a767SRodney W. Grimes tsleep((caddr_t)bp, PRIBIO, "physstr", 0); 11426f9a767SRodney W. Grimes splx(spl); 11526f9a767SRodney W. Grimes 11626f9a767SRodney W. Grimes vunmapbuf(bp); 11726f9a767SRodney W. Grimes 11826f9a767SRodney W. Grimes /* 11926f9a767SRodney W. Grimes * update the uio data 12026f9a767SRodney W. Grimes */ 12126f9a767SRodney W. Grimes { 12226f9a767SRodney W. Grimes int iolen = bp->b_bcount - bp->b_resid; 1237d7bb69dSDavid Greenman 1247d7bb69dSDavid Greenman if (iolen == 0 && !(bp->b_flags & B_ERROR)) 1257d7bb69dSDavid Greenman goto doerror; /* EOF */ 12626f9a767SRodney W. Grimes uio->uio_iov[i].iov_len -= iolen; 12726f9a767SRodney W. Grimes uio->uio_iov[i].iov_base += iolen; 12826f9a767SRodney W. Grimes uio->uio_resid -= iolen; 12926f9a767SRodney W. Grimes uio->uio_offset += iolen; 13026f9a767SRodney W. Grimes } 13126f9a767SRodney W. Grimes 13226f9a767SRodney W. Grimes /* 13326f9a767SRodney W. Grimes * check for an error 13426f9a767SRodney W. Grimes */ 13526f9a767SRodney W. Grimes if( bp->b_flags & B_ERROR) { 13626f9a767SRodney W. Grimes error = bp->b_error; 13726f9a767SRodney W. Grimes goto doerror; 13826f9a767SRodney W. Grimes } 13926f9a767SRodney W. Grimes } 14026f9a767SRodney W. Grimes } 14126f9a767SRodney W. Grimes 14226f9a767SRodney W. Grimes 14326f9a767SRodney W. Grimes doerror: 14416f62314SDavid Greenman relpbuf(bpa); 14516f62314SDavid Greenman if (!bp_alloc) { 14626f9a767SRodney W. Grimes bp->b_flags &= ~(B_BUSY|B_PHYS); 14726f9a767SRodney W. Grimes if( bp->b_flags & B_WANTED) { 14826f9a767SRodney W. Grimes bp->b_flags &= ~B_WANTED; 14926f9a767SRodney W. Grimes wakeup((caddr_t)bp); 15026f9a767SRodney W. Grimes } 15126f9a767SRodney W. Grimes } 15226f9a767SRodney W. Grimes /* 15326f9a767SRodney W. Grimes * allow the process to be swapped 15426f9a767SRodney W. Grimes */ 15526f9a767SRodney W. Grimes curproc->p_flag &= ~P_PHYSIO; 15626f9a767SRodney W. Grimes 15726f9a767SRodney W. Grimes return (error); 158df8bae1dSRodney W. Grimes } 159df8bae1dSRodney W. Grimes 160df8bae1dSRodney W. Grimes u_int 16126f9a767SRodney W. Grimes minphys(struct buf *bp) 162df8bae1dSRodney W. Grimes { 163df8bae1dSRodney W. Grimes 16426f9a767SRodney W. Grimes if( bp->b_bcount > MAXBSIZE) { 16526f9a767SRodney W. Grimes bp->b_bcount = MAXBSIZE; 16626f9a767SRodney W. Grimes } 16726f9a767SRodney W. Grimes return bp->b_bcount; 168df8bae1dSRodney W. Grimes } 169df8bae1dSRodney W. Grimes 17026f9a767SRodney W. Grimes int 17126f9a767SRodney W. Grimes rawread(dev_t dev, struct uio *uio) 172df8bae1dSRodney W. Grimes { 173df8bae1dSRodney W. Grimes return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 17426f9a767SRodney W. Grimes dev, 1, minphys, uio)); 175df8bae1dSRodney W. Grimes } 176df8bae1dSRodney W. Grimes 17726f9a767SRodney W. Grimes int 17826f9a767SRodney W. Grimes rawwrite(dev_t dev, struct uio *uio) 179df8bae1dSRodney W. Grimes { 180df8bae1dSRodney W. Grimes return (physio(cdevsw[major(dev)].d_strategy, (struct buf *)NULL, 18126f9a767SRodney W. Grimes dev, 0, minphys, uio)); 18226f9a767SRodney W. Grimes } 18326f9a767SRodney W. Grimes 18426f9a767SRodney W. Grimes static void 18526f9a767SRodney W. Grimes physwakeup(bp) 18626f9a767SRodney W. Grimes struct buf *bp; 18726f9a767SRodney W. Grimes { 18826f9a767SRodney W. Grimes wakeup((caddr_t) bp); 18926f9a767SRodney W. Grimes bp->b_flags &= ~B_CALL; 190df8bae1dSRodney W. Grimes } 191