|
|
1.1 ! root 1: /* (-lgl ! 2: * COHERENT Device Driver Kit version 1.2.0 ! 3: * Copyright (c) 1982, 1991 by Mark Williams Company. ! 4: * All rights reserved. May not be copied without permission. ! 5: -lgl) */ ! 6: /* ! 7: * Block or character device RAM disk driver. ! 8: */ ! 9: ! 10: #include <sys/coherent.h> ! 11: #include <sys/buf.h> ! 12: #include <errno.h> ! 13: #ifndef _I386 ! 14: #include <sys/uproc.h> ! 15: #include <sys/devices.h> ! 16: #endif ! 17: #include <sys/seg.h> ! 18: #include <sys/con.h> ! 19: #include <sys/inode.h> ! 20: #include <sys/stat.h> ! 21: ! 22: #if _I386 ! 23: /* ! 24: * Patchable variables for 386. ! 25: * Starting addresses in kernel data and size for each ram disk. ! 26: */ ! 27: int RAM0=0x88000000; ! 28: int RAMSIZE=0x800000; ! 29: #define RAM1 (RAM0 + RAMSIZE) ! 30: #endif ! 31: ! 32: /* ! 33: * Minor number encoding: dsssssss ! 34: * d drive number (0 or 1) ! 35: * sssssss allocation size: 0 to free, 1-127 allocsize (n*ASIZE*BSIZE bytes) ! 36: */ ! 37: #define rm_drive(dev) (minor(dev) >> 7) ! 38: #define rm_asize(dev) (minor(dev) & 0x7F) ! 39: #define ASIZE 128 /* allocation chunk size in blocks (64KB) */ ! 40: #define NUM_RM 2 /* number of ram disks */ ! 41: /* - tied to dev encoding (see above) */ ! 42: #ifdef _I386 ! 43: #define RMMAJ 8 /* major # for driver */ ! 44: #endif ! 45: ! 46: int nulldev(); ! 47: int nonedev(); ! 48: int rmload(); ! 49: int rmuload(); ! 50: int rmopen(); ! 51: int rmclose(); ! 52: int rmread(); ! 53: int rmwrite(); ! 54: int rmblock(); ! 55: ! 56: CON rmcon = { ! 57: DFBLK|DFCHR, ! 58: #ifndef _I386 ! 59: RM_MAJOR, ! 60: #else ! 61: RMMAJ, ! 62: #endif ! 63: rmopen, /* Open */ ! 64: rmclose, /* Close */ ! 65: rmblock, /* Block */ ! 66: rmread, /* Read */ ! 67: rmwrite, /* Write */ ! 68: nonedev, ! 69: nulldev, ! 70: nulldev, ! 71: rmload, /* Load */ ! 72: rmuload /* Unload */ ! 73: }; ! 74: ! 75: typedef struct rm { ! 76: #ifndef _I386 ! 77: fsize_t rm_size; /* Size in allocation chunks */ ! 78: paddr_t rm_paddr; /* Physical base of ram disc segment */ ! 79: SEG *rm_segp; /* Segment pointer of ram device */ ! 80: #else ! 81: off_t rm_size; /* Size in allocation chunks */ ! 82: SR rm_sr; ! 83: #endif ! 84: BUF rm_buf; /* Static buffer for raw requests */ ! 85: int rm_nopen; /* Open count to avoid blowups */ ! 86: } RM; ! 87: static RM rm[NUM_RM]; ! 88: ! 89: /* ! 90: * Load. ! 91: */ ! 92: static ! 93: rmload() ! 94: { ! 95: } ! 96: ! 97: /* ! 98: * Unload. ! 99: * Release the allocated buffers. ! 100: */ ! 101: static ! 102: rmuload() ! 103: { ! 104: int i; ! 105: ! 106: for (i = 0; i < NUM_RM; i++){ ! 107: #ifndef _I386 ! 108: if (rm[i].rm_size != 0) ! 109: sfree(rm[i].rm_segp); ! 110: #else ! 111: if (rm[i].rm_size != 0) { ! 112: unload(&rm[i].rm_sr); ! 113: sfree(rm[i].rm_sr.sr_segp); ! 114: } ! 115: #endif ! 116: } ! 117: } ! 118: ! 119: /* ! 120: * Open. ! 121: * Allocate on the first call. ! 122: * Increment the open count. ! 123: */ ! 124: static ! 125: rmopen(dev, mode) dev_t dev; int mode; ! 126: { ! 127: register RM *rmp; ! 128: #ifndef _I386 ! 129: register fsize_t asize, osize; ! 130: register SEG *segp; ! 131: #else ! 132: register off_t asize, osize; ! 133: #endif ! 134: ! 135: rmp = &rm[rm_drive(dev)]; ! 136: asize = rm_asize(dev); ! 137: osize = rmp->rm_size; ! 138: ! 139: /* Fail on read before creation or bogus size. */ ! 140: if ((mode == IPR && osize == 0) ! 141: || (asize != 0 && osize != 0 && asize != osize) ! 142: || (asize == 0 && osize == 0)) { ! 143: SET_U_ERROR( ENXIO, ! 144: "can not read ram disk yet or bogus size" ); ! 145: return; ! 146: } ! 147: ! 148: #ifdef _I386 ! 149: if (ASIZE*BSIZE*asize > RAMSIZE) { ! 150: SET_U_ERROR( ENOMEM, "Ram disk too big" ); ! 151: return; ! 152: } ! 153: #endif ! 154: ! 155: /* ! 156: * Allocate as required. ! 157: * Ignore case asize==0 && osize!=0, handled by rmclose(). ! 158: * If asize!=0 && asize==osize, just bump the open count. ! 159: */ ! 160: if (asize != 0 && osize == 0) { ! 161: #ifndef _I386 ! 162: segp = rmp->rm_segp = salloc((fsize_t)ASIZE*BSIZE*asize, ! 163: SFSYST|SFNSWP|SFNCLR|SFHIGH); ! 164: if (segp == NULL) { ! 165: SET_U_ERROR( ENOMEM, ! 166: "can not allocate segment for ram disk" ); ! 167: return; ! 168: } ! 169: #else ! 170: rmp->rm_sr.sr_segp = ! 171: salloc((off_t)ASIZE*BSIZE*asize, SFSYST|SFNSWP|SFNCLR); ! 172: if (rmp->rm_sr.sr_segp == NULL) { ! 173: SET_U_ERROR( ENOMEM, ! 174: "can not allocate segment for ram disk" ); ! 175: return; ! 176: } ! 177: #endif ! 178: rmp->rm_size = asize; ! 179: #ifndef _I386 ! 180: rmp->rm_paddr = segp->s_paddr; ! 181: rmp->rm_nopen = 0; ! 182: pclear(rmp->rm_paddr, 1024L); /* clear 1st 2 blocks */ ! 183: #else ! 184: rmp->rm_sr.sr_base = rm_drive(dev)==0 ? RAM0 : RAM1; ! 185: rmp->rm_sr.sr_size = rmp->rm_sr.sr_segp->s_size; ! 186: doload(&rmp->rm_sr); ! 187: #endif ! 188: } ! 189: rmp->rm_nopen++; ! 190: } ! 191: ! 192: /* ! 193: * Close. ! 194: * Decrement the open count. ! 195: * Release the allocated buffer if minor number is 0. ! 196: */ ! 197: static ! 198: rmclose(dev) dev_t dev; ! 199: { ! 200: register RM *rmp; ! 201: #ifndef _I386 ! 202: register fsize_t asize, osize; ! 203: #else ! 204: register off_t asize, osize; ! 205: #endif ! 206: ! 207: rmp = &rm[rm_drive(dev)]; ! 208: asize = rm_asize(dev); ! 209: osize = rmp->rm_size; ! 210: ! 211: if (osize == 0 ! 212: || (asize != 0 && asize != osize) ! 213: || rmp->rm_nopen == 0) { ! 214: u.u_error = ENXIO; ! 215: return; ! 216: } ! 217: rmp->rm_nopen--; ! 218: if (asize == 0) { ! 219: if (rmp->rm_nopen != 0) { ! 220: #ifndef _I386 ! 221: u.u_error = EDBUSY; ! 222: #else ! 223: u.u_error = EBUSY; ! 224: #endif ! 225: return; ! 226: } ! 227: #ifndef _I386 ! 228: sfree(rmp->rm_segp); ! 229: #else ! 230: unload(&rmp->rm_sr); ! 231: sfree(rmp->rm_sr.sr_segp); ! 232: #endif ! 233: rmp->rm_size = 0; ! 234: } ! 235: } ! 236: ! 237: static ! 238: rmblock(bp) register BUF *bp; ! 239: { ! 240: #ifndef _I386 ! 241: paddr_t base; ! 242: register fsize_t asize, osize; ! 243: #else ! 244: caddr_t base; ! 245: register off_t asize, osize; ! 246: #endif ! 247: dev_t dev; ! 248: register RM *rmp; ! 249: ! 250: dev = bp->b_dev; ! 251: rmp = &rm[rm_drive(dev)]; ! 252: asize = rm_asize(dev); ! 253: osize = rmp->rm_size; ! 254: if (osize == 0 || asize != osize) ! 255: #ifndef _I386 ! 256: bp->b_flag |= BFERR; ! 257: /* ! 258: * Make sure last block requested is within range of device. ! 259: */ ! 260: else if ((bp->b_bno + bp->b_count/BSIZE - 1) >= asize*ASIZE) ! 261: bp->b_flag |= BFERR; ! 262: #else ! 263: u.u_error = ENXIO; ! 264: else if (bp->b_bno >= asize*ASIZE) ! 265: u.u_error = EIO; ! 266: #endif ! 267: else { ! 268: #ifndef _I386 ! 269: base = rmp->rm_paddr + (paddr_t)bp->b_bno * BSIZE; ! 270: #else ! 271: base = rmp->rm_sr.sr_base + (paddr_t)bp->b_bno * BSIZE; ! 272: #endif ! 273: if (bp->b_req == BREAD) ! 274: #ifndef _I386 ! 275: plrcopy(base, bp->b_paddr, (fsize_t)bp->b_count); ! 276: #else ! 277: dmaout(bp->b_count, bp->b_paddr, base); ! 278: #endif ! 279: else ! 280: #ifndef _I386 ! 281: plrcopy(bp->b_paddr, base, (fsize_t)bp->b_count); ! 282: #else ! 283: dmain(bp->b_count, bp->b_paddr, base); ! 284: #endif ! 285: } ! 286: bdone(bp); ! 287: } ! 288: ! 289: /* ! 290: * The read routine calls the common raw I/O processing code, ! 291: * using a static buffer header in the driver. ! 292: */ ! 293: static ! 294: rmread(dev, iop) register dev_t dev; IO *iop; ! 295: { ! 296: register BUF *bufp; ! 297: ! 298: bufp = &rm[rm_drive(dev)].rm_buf; ! 299: ioreq(bufp, iop, dev, BREAD, BFIOC|BFRAW); ! 300: } ! 301: ! 302: /* ! 303: * The write routine is just like the read routine, ! 304: * except that the function code is write instead of read. ! 305: */ ! 306: static ! 307: rmwrite(dev, iop) register dev_t dev; IO *iop; ! 308: { ! 309: register BUF *bufp; ! 310: ! 311: bufp = &rm[rm_drive(dev)].rm_buf; ! 312: ioreq(bufp, iop, dev, BWRITE, BFIOC|BFRAW); ! 313: } ! 314: ! 315: /* end of rm.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.