1 /* mem.c 6.2 84/08/28 */ 2 3 /* 4 * Memory special file 5 */ 6 7 #include "pte.h" 8 9 #include "param.h" 10 #include "dir.h" 11 #include "user.h" 12 #include "conf.h" 13 #include "buf.h" 14 #include "systm.h" 15 #include "vm.h" 16 #include "cmap.h" 17 #include "uio.h" 18 19 #include "mtpr.h" 20 21 mmread(dev, uio) 22 dev_t dev; 23 struct uio *uio; 24 { 25 26 return (mmrw(dev, uio, UIO_READ)); 27 } 28 29 mmwrite(dev, uio) 30 dev_t dev; 31 struct uio *uio; 32 { 33 34 return (mmrw(dev, uio, UIO_WRITE)); 35 } 36 37 mmrw(dev, uio, rw) 38 dev_t dev; 39 struct uio *uio; 40 enum uio_rw rw; 41 { 42 register int o; 43 register u_int c, v; 44 register struct iovec *iov; 45 int error = 0; 46 extern int umbabeg, umbaend; 47 48 49 while (uio->uio_resid > 0 && error == 0) { 50 iov = uio->uio_iov; 51 if (iov->iov_len == 0) { 52 uio->uio_iov++; 53 uio->uio_iovcnt--; 54 if (uio->uio_iovcnt < 0) 55 panic("mmrw"); 56 continue; 57 } 58 switch (minor(dev)) { 59 60 /* minor device 0 is physical memory */ 61 case 0: 62 v = btop(uio->uio_offset); 63 if (v >= physmem) 64 goto fault; 65 *(int *)mmap = v | PG_V | 66 (rw == UIO_READ ? PG_KR : PG_KW); 67 mtpr(TBIS, vmmap); 68 o = (int)uio->uio_offset & PGOFSET; 69 c = min((u_int)(NBPG - o), (u_int)iov->iov_len); 70 c = min(c, (u_int)(NBPG - ((int)iov->iov_base&PGOFSET))); 71 error = uiomove((caddr_t)&vmmap[o], (int)c, rw, uio); 72 continue; 73 74 /* minor device 1 is kernel memory */ 75 case 1: 76 if ((caddr_t)uio->uio_offset < (caddr_t)&umbabeg && 77 (caddr_t)uio->uio_offset + uio->uio_resid >= (caddr_t)&umbabeg) 78 goto fault; 79 if ((caddr_t)uio->uio_offset >= (caddr_t)&umbabeg && 80 (caddr_t)uio->uio_offset < (caddr_t)&umbaend) 81 goto fault; 82 c = iov->iov_len; 83 if (!kernacc((caddr_t)uio->uio_offset, c, rw == UIO_READ ? B_READ : B_WRITE)) 84 goto fault; 85 error = uiomove((caddr_t)uio->uio_offset, (int)c, rw, uio); 86 continue; 87 88 /* minor device 2 is EOF/RATHOLE */ 89 case 2: 90 if (rw == UIO_READ) 91 return (0); 92 c = iov->iov_len; 93 break; 94 95 /* minor device 3 is unibus memory (addressed by shorts) */ 96 case 3: 97 c = iov->iov_len; 98 if (!kernacc((caddr_t)uio->uio_offset, c, rw == UIO_READ ? B_READ : B_WRITE)) 99 goto fault; 100 if (!useracc(iov->iov_base, c, rw == UIO_READ ? B_WRITE : B_READ)) 101 goto fault; 102 error = UNIcpy((caddr_t)uio->uio_offset, iov->iov_base, 103 (int)c, rw); 104 break; 105 } 106 if (error) 107 break; 108 iov->iov_base += c; 109 iov->iov_len -= c; 110 uio->uio_offset += c; 111 uio->uio_resid -= c; 112 } 113 return (error); 114 fault: 115 return (EFAULT); 116 } 117 118 /* 119 * UNIBUS Address Space <--> User Space transfer 120 */ 121 UNIcpy(uniadd, usradd, n, rw) 122 caddr_t uniadd, usradd; 123 register int n; 124 enum uio_rw rw; 125 { 126 register short *from, *to; 127 128 if (rw == UIO_READ) { 129 from = (short *)uniadd; 130 to = (short *)usradd; 131 } else { 132 from = (short *)usradd; 133 to = (short *)uniadd; 134 } 135 for (n >>= 1; n > 0; n--) 136 *to++ = *from++; 137 return (0); 138 } 139