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 * 19c3aac50fSPeter Wemm * $FreeBSD$ 20df8bae1dSRodney W. Grimes */ 21df8bae1dSRodney W. Grimes 22df8bae1dSRodney W. Grimes #include <sys/param.h> 23df8bae1dSRodney W. Grimes #include <sys/systm.h> 249626b608SPoul-Henning Kamp #include <sys/bio.h> 25df8bae1dSRodney W. Grimes #include <sys/buf.h> 26df8bae1dSRodney W. Grimes #include <sys/conf.h> 27df8bae1dSRodney W. Grimes #include <sys/proc.h> 2808637435SBruce Evans #include <sys/uio.h> 2908637435SBruce Evans 3026f9a767SRodney W. Grimes #include <vm/vm.h> 31efeaf95aSDavid Greenman #include <vm/vm_extern.h> 32df8bae1dSRodney W. Grimes 337179e74fSPoul-Henning Kamp static void 347179e74fSPoul-Henning Kamp physwakeup(struct buf *bp) 35c48d1775SPoul-Henning Kamp { 367179e74fSPoul-Henning Kamp wakeup((caddr_t) bp); 37c48d1775SPoul-Henning Kamp } 38c48d1775SPoul-Henning Kamp 39c48d1775SPoul-Henning Kamp int 407179e74fSPoul-Henning Kamp physio(dev_t dev, struct uio *uio, int ioflag) 41df8bae1dSRodney W. Grimes { 4226f9a767SRodney W. Grimes int i; 4326f9a767SRodney W. Grimes int error; 4426f9a767SRodney W. Grimes int spl; 4516f62314SDavid Greenman caddr_t sa; 463b782ee9SPoul-Henning Kamp off_t blockno; 477179e74fSPoul-Henning Kamp u_int iolen; 487179e74fSPoul-Henning Kamp struct buf *bp; 49df8bae1dSRodney W. Grimes 507179e74fSPoul-Henning Kamp /* Keep the process UPAGES from being swapped. XXX: why ? */ 5157dc5948SPeter Wemm PHOLD(curproc); 5226f9a767SRodney W. Grimes 537179e74fSPoul-Henning Kamp bp = getpbuf(NULL); 547179e74fSPoul-Henning Kamp sa = bp->b_data; 5526f9a767SRodney W. Grimes error = bp->b_error = 0; 5626f9a767SRodney W. Grimes 577179e74fSPoul-Henning Kamp /* XXX: sanity check */ 587179e74fSPoul-Henning Kamp if(dev->si_iosize_max < PAGE_SIZE) { 597179e74fSPoul-Henning Kamp printf("WARNING: %s si_iosize_max=%d, using DFLTPHYS.\n", 607179e74fSPoul-Henning Kamp devtoname(dev), dev->si_iosize_max); 617179e74fSPoul-Henning Kamp dev->si_iosize_max = DFLTPHYS; 627179e74fSPoul-Henning Kamp } 637179e74fSPoul-Henning Kamp 6426f9a767SRodney W. Grimes for (i = 0; i < uio->uio_iovcnt; i++) { 6526f9a767SRodney W. Grimes while (uio->uio_iov[i].iov_len) { 6621144e3bSPoul-Henning Kamp bp->b_flags = B_PHYS; 677179e74fSPoul-Henning Kamp if (uio->uio_rw == UIO_READ) 6821144e3bSPoul-Henning Kamp bp->b_iocmd = BIO_READ; 697179e74fSPoul-Henning Kamp else 7021144e3bSPoul-Henning Kamp bp->b_iocmd = BIO_WRITE; 7150ce7ff4SJohn Dyson bp->b_dev = dev; 724b83b27fSJohn Dyson bp->b_iodone = physwakeup; 734b83b27fSJohn Dyson bp->b_data = uio->uio_iov[i].iov_base; 747179e74fSPoul-Henning Kamp bp->b_bcount = uio->uio_iov[i].iov_len; 757179e74fSPoul-Henning Kamp bp->b_offset = uio->uio_offset; 7616f62314SDavid Greenman bp->b_saveaddr = sa; 777179e74fSPoul-Henning Kamp 787179e74fSPoul-Henning Kamp /* Don't exceed drivers iosize limit */ 797179e74fSPoul-Henning Kamp if (bp->b_bcount > dev->si_iosize_max) 807179e74fSPoul-Henning Kamp bp->b_bcount = dev->si_iosize_max; 817179e74fSPoul-Henning Kamp 827179e74fSPoul-Henning Kamp /* 837179e74fSPoul-Henning Kamp * Make sure the pbuf can map the request 847179e74fSPoul-Henning Kamp * XXX: The pbuf has kvasize = MAXPHYS so a request 857179e74fSPoul-Henning Kamp * XXX: larger than MAXPHYS - PAGE_SIZE must be 867179e74fSPoul-Henning Kamp * XXX: page aligned or it will be fragmented. 877179e74fSPoul-Henning Kamp */ 887179e74fSPoul-Henning Kamp iolen = ((vm_offset_t) bp->b_data) & PAGE_MASK; 897179e74fSPoul-Henning Kamp if ((bp->b_bcount + iolen) > bp->b_kvasize) { 907179e74fSPoul-Henning Kamp bp->b_bcount = bp->b_kvasize; 917179e74fSPoul-Henning Kamp if (iolen != 0) 927179e74fSPoul-Henning Kamp bp->b_bcount -= PAGE_SIZE; 937179e74fSPoul-Henning Kamp } 947179e74fSPoul-Henning Kamp bp->b_bufsize = bp->b_bcount; 957179e74fSPoul-Henning Kamp 967179e74fSPoul-Henning Kamp blockno = bp->b_offset >> DEV_BSHIFT; 9760767bf4SPoul-Henning Kamp if ((daddr_t)blockno != blockno) { 987179e74fSPoul-Henning Kamp error = EINVAL; /* blockno overflow */ 993b782ee9SPoul-Henning Kamp goto doerror; 1003b782ee9SPoul-Henning Kamp } 10160767bf4SPoul-Henning Kamp bp->b_blkno = blockno; 10226f9a767SRodney W. Grimes 1036884d2aaSPeter Wemm if (uio->uio_segflg == UIO_USERSPACE) { 1047179e74fSPoul-Henning Kamp if (!useracc(bp->b_data, bp->b_bufsize, 10521144e3bSPoul-Henning Kamp bp->b_iocmd == BIO_READ ? 10602c58685SPoul-Henning Kamp VM_PROT_WRITE : VM_PROT_READ)) { 10726f9a767SRodney W. Grimes error = EFAULT; 10826f9a767SRodney W. Grimes goto doerror; 10926f9a767SRodney W. Grimes } 11026f9a767SRodney W. Grimes vmapbuf(bp); 1116884d2aaSPeter Wemm } 11226f9a767SRodney W. Grimes 113b99c307aSPoul-Henning Kamp DEV_STRATEGY(bp, 0); 11426f9a767SRodney W. Grimes spl = splbio(); 11526f9a767SRodney W. Grimes while ((bp->b_flags & B_DONE) == 0) 11626f9a767SRodney W. Grimes tsleep((caddr_t)bp, PRIBIO, "physstr", 0); 11726f9a767SRodney W. Grimes splx(spl); 11826f9a767SRodney W. Grimes 1196884d2aaSPeter Wemm if (uio->uio_segflg == UIO_USERSPACE) 12026f9a767SRodney W. Grimes vunmapbuf(bp); 1217179e74fSPoul-Henning Kamp iolen = bp->b_bcount - bp->b_resid; 122c244d2deSPoul-Henning Kamp if (iolen == 0 && !(bp->b_ioflags & BIO_ERROR)) 1237d7bb69dSDavid Greenman goto doerror; /* EOF */ 12426f9a767SRodney W. Grimes uio->uio_iov[i].iov_len -= iolen; 12526f9a767SRodney W. Grimes uio->uio_iov[i].iov_base += iolen; 12626f9a767SRodney W. Grimes uio->uio_resid -= iolen; 12726f9a767SRodney W. Grimes uio->uio_offset += iolen; 128c244d2deSPoul-Henning Kamp if( bp->b_ioflags & BIO_ERROR) { 12926f9a767SRodney W. Grimes error = bp->b_error; 13026f9a767SRodney W. Grimes goto doerror; 13126f9a767SRodney W. Grimes } 13226f9a767SRodney W. Grimes } 13326f9a767SRodney W. Grimes } 13426f9a767SRodney W. Grimes doerror: 1357179e74fSPoul-Henning Kamp relpbuf(bp, NULL); 13657dc5948SPeter Wemm PRELE(curproc); 13726f9a767SRodney W. Grimes return (error); 138df8bae1dSRodney W. Grimes } 139