19454b2d8SWarner Losh /*- 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. 18df8bae1dSRodney W. Grimes */ 19df8bae1dSRodney W. Grimes 20677b542eSDavid E. O'Brien #include <sys/cdefs.h> 21677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 22677b542eSDavid E. O'Brien 23df8bae1dSRodney W. Grimes #include <sys/param.h> 24df8bae1dSRodney W. Grimes #include <sys/systm.h> 259626b608SPoul-Henning Kamp #include <sys/bio.h> 26df8bae1dSRodney W. Grimes #include <sys/buf.h> 27df8bae1dSRodney W. Grimes #include <sys/conf.h> 28df8bae1dSRodney W. Grimes #include <sys/proc.h> 2908637435SBruce Evans #include <sys/uio.h> 3008637435SBruce Evans 3126f9a767SRodney W. Grimes #include <vm/vm.h> 32efeaf95aSDavid Greenman #include <vm/vm_extern.h> 33df8bae1dSRodney W. Grimes 34c48d1775SPoul-Henning Kamp int 3589c9c53dSPoul-Henning Kamp physio(struct cdev *dev, struct uio *uio, int ioflag) 36df8bae1dSRodney W. Grimes { 3726f9a767SRodney W. Grimes int i; 3826f9a767SRodney W. Grimes int error; 3916f62314SDavid Greenman caddr_t sa; 407179e74fSPoul-Henning Kamp u_int iolen; 417179e74fSPoul-Henning Kamp struct buf *bp; 42df8bae1dSRodney W. Grimes 437179e74fSPoul-Henning Kamp /* Keep the process UPAGES from being swapped. XXX: why ? */ 4457dc5948SPeter Wemm PHOLD(curproc); 4526f9a767SRodney W. Grimes 467179e74fSPoul-Henning Kamp bp = getpbuf(NULL); 477179e74fSPoul-Henning Kamp sa = bp->b_data; 48ef38cda1SAlan Cox error = 0; 4926f9a767SRodney W. Grimes 507179e74fSPoul-Henning Kamp /* XXX: sanity check */ 517179e74fSPoul-Henning Kamp if(dev->si_iosize_max < PAGE_SIZE) { 527179e74fSPoul-Henning Kamp printf("WARNING: %s si_iosize_max=%d, using DFLTPHYS.\n", 537179e74fSPoul-Henning Kamp devtoname(dev), dev->si_iosize_max); 547179e74fSPoul-Henning Kamp dev->si_iosize_max = DFLTPHYS; 557179e74fSPoul-Henning Kamp } 567179e74fSPoul-Henning Kamp 5726f9a767SRodney W. Grimes for (i = 0; i < uio->uio_iovcnt; i++) { 5826f9a767SRodney W. Grimes while (uio->uio_iov[i].iov_len) { 5900cbe31bSPoul-Henning Kamp bp->b_flags = 0; 607179e74fSPoul-Henning Kamp if (uio->uio_rw == UIO_READ) 6121144e3bSPoul-Henning Kamp bp->b_iocmd = BIO_READ; 627179e74fSPoul-Henning Kamp else 6321144e3bSPoul-Henning Kamp bp->b_iocmd = BIO_WRITE; 64749ffa4eSJeff Roberson bp->b_iodone = bdone; 654b83b27fSJohn Dyson bp->b_data = uio->uio_iov[i].iov_base; 667179e74fSPoul-Henning Kamp bp->b_bcount = uio->uio_iov[i].iov_len; 677179e74fSPoul-Henning Kamp bp->b_offset = uio->uio_offset; 6801758670SPoul-Henning Kamp bp->b_iooffset = uio->uio_offset; 6916f62314SDavid Greenman bp->b_saveaddr = sa; 707179e74fSPoul-Henning Kamp 717179e74fSPoul-Henning Kamp /* Don't exceed drivers iosize limit */ 727179e74fSPoul-Henning Kamp if (bp->b_bcount > dev->si_iosize_max) 737179e74fSPoul-Henning Kamp bp->b_bcount = dev->si_iosize_max; 747179e74fSPoul-Henning Kamp 757179e74fSPoul-Henning Kamp /* 767179e74fSPoul-Henning Kamp * Make sure the pbuf can map the request 777179e74fSPoul-Henning Kamp * XXX: The pbuf has kvasize = MAXPHYS so a request 787179e74fSPoul-Henning Kamp * XXX: larger than MAXPHYS - PAGE_SIZE must be 797179e74fSPoul-Henning Kamp * XXX: page aligned or it will be fragmented. 807179e74fSPoul-Henning Kamp */ 817179e74fSPoul-Henning Kamp iolen = ((vm_offset_t) bp->b_data) & PAGE_MASK; 827179e74fSPoul-Henning Kamp if ((bp->b_bcount + iolen) > bp->b_kvasize) { 837179e74fSPoul-Henning Kamp bp->b_bcount = bp->b_kvasize; 847179e74fSPoul-Henning Kamp if (iolen != 0) 857179e74fSPoul-Henning Kamp bp->b_bcount -= PAGE_SIZE; 867179e74fSPoul-Henning Kamp } 877179e74fSPoul-Henning Kamp bp->b_bufsize = bp->b_bcount; 887179e74fSPoul-Henning Kamp 89e96d018dSPoul-Henning Kamp bp->b_blkno = btodb(bp->b_offset); 9026f9a767SRodney W. Grimes 91cdb06edaSAlan Cox if (uio->uio_segflg == UIO_USERSPACE) 922d5c7e45SMatthew Dillon if (vmapbuf(bp) < 0) { 932d5c7e45SMatthew Dillon error = EFAULT; 942d5c7e45SMatthew Dillon goto doerror; 952d5c7e45SMatthew Dillon } 9626f9a767SRodney W. Grimes 976afb3b1cSPoul-Henning Kamp dev_strategy(dev, bp); 98749ffa4eSJeff Roberson if (uio->uio_rw == UIO_READ) 99749ffa4eSJeff Roberson bwait(bp, PRIBIO, "physrd"); 100749ffa4eSJeff Roberson else 101749ffa4eSJeff Roberson bwait(bp, PRIBIO, "physwr"); 10226f9a767SRodney W. Grimes 1036884d2aaSPeter Wemm if (uio->uio_segflg == UIO_USERSPACE) 10426f9a767SRodney W. Grimes vunmapbuf(bp); 1057179e74fSPoul-Henning Kamp iolen = bp->b_bcount - bp->b_resid; 106c244d2deSPoul-Henning Kamp if (iolen == 0 && !(bp->b_ioflags & BIO_ERROR)) 1077d7bb69dSDavid Greenman goto doerror; /* EOF */ 10826f9a767SRodney W. Grimes uio->uio_iov[i].iov_len -= iolen; 1092b7f24d2SMike Barcroft uio->uio_iov[i].iov_base = 1102b7f24d2SMike Barcroft (char *)uio->uio_iov[i].iov_base + iolen; 11126f9a767SRodney W. Grimes uio->uio_resid -= iolen; 11226f9a767SRodney W. Grimes uio->uio_offset += iolen; 113c244d2deSPoul-Henning Kamp if( bp->b_ioflags & BIO_ERROR) { 11426f9a767SRodney W. Grimes error = bp->b_error; 11526f9a767SRodney W. Grimes goto doerror; 11626f9a767SRodney W. Grimes } 11726f9a767SRodney W. Grimes } 11826f9a767SRodney W. Grimes } 11926f9a767SRodney W. Grimes doerror: 1207179e74fSPoul-Henning Kamp relpbuf(bp, NULL); 12157dc5948SPeter Wemm PRELE(curproc); 12226f9a767SRodney W. Grimes return (error); 123df8bae1dSRodney W. Grimes } 124