|
|
1.1 ! root 1: /* ! 2: * Ram Pipe Device Driver ! 3: */ ! 4: ! 5: #include <coherent.h> ! 6: #include <con.h> ! 7: #include <seg.h> ! 8: #include <stat.h> ! 9: #include <sched.h> ! 10: #include <termio.h> ! 11: #include <v7sgtty.h> ! 12: #include <uproc.h> ! 13: #include <errno.h> ! 14: ! 15: #define MAXNRP 30 /* Maximum number of ram pipes (must be < 32) */ ! 16: #define NCPQ 2048 /* Size of pipe in bytes */ ! 17: #define RPMAJOR 22 /* Major device for ram pipes */ ! 18: ! 19: /* ! 20: * function definitions ! 21: */ ! 22: int rpopen(); ! 23: int rpread(); ! 24: int rpwrite(); ! 25: int rpioctl(); ! 26: int rppoll(); ! 27: void rpuload(); ! 28: int nulldev(); ! 29: int nonedev(); ! 30: ! 31: ! 32: /* ! 33: * configuration table ! 34: */ ! 35: CON rpcon = { ! 36: DFCHR|DFPOL, /* flags */ ! 37: RPMAJOR, /* major index */ ! 38: rpopen, /* open */ ! 39: nulldev, /* close */ ! 40: nonedev, /* block */ ! 41: rpread, /* read */ ! 42: rpwrite, /* write */ ! 43: rpioctl, /* ioctl */ ! 44: nulldev, /* power fail */ ! 45: nulldev, /* timeout */ ! 46: nulldev, /* load */ ! 47: rpuload, /* unload */ ! 48: rppoll /* poll */ ! 49: }; ! 50: ! 51: /* ! 52: * Ram Pipe Headers ! 53: */ ! 54: static ! 55: struct ring { ! 56: unsigned short q_size; /* Number of characters in queue */ ! 57: unsigned short q_mask; /* Ring buffer Mask: NCPQ-1 */ ! 58: faddr_t q_ifaddr; /* Input virtual address */ ! 59: faddr_t q_ofaddr; /* Output virtual address */ ! 60: GATE q_igate; /* Read lock */ ! 61: GATE q_ogate; /* Write lock */ ! 62: event_t q_ipoll; /* Input polls */ ! 63: event_t q_opoll; /* Output polls */ ! 64: ! 65: } rpq[MAXNRP]; ! 66: ! 67: static SEG * rpsegp; ! 68: unsigned NRP = MAXNRP; ! 69: ! 70: /* ! 71: * Initialization Routine ! 72: */ ! 73: static ! 74: rpinit() ! 75: { ! 76: register struct ring *rp; ! 77: faddr_t faddr; ! 78: paddr_t paddr; ! 79: ! 80: /* ! 81: * Ensure valid number of ram pipes ! 82: */ ! 83: if ( NRP > MAXNRP ) ! 84: NRP = MAXNRP; ! 85: ! 86: /* ! 87: * Allocate ram pipe segment, initialize ram pipe queues ! 88: */ ! 89: if ( NRP != 0 ) { ! 90: rpsegp = salloc((fsize_t)NRP*NCPQ, SFSYST|SFHIGH|SFNSWP|SFNCLR); ! 91: ! 92: if ( rpsegp == NULL ) ! 93: return -1; ! 94: ! 95: paddr = rpsegp->s_paddr; ! 96: ! 97: for ( rp = &rpq[0]; rp < &rpq[NRP]; rp++, paddr += NCPQ ) { ! 98: ! 99: faddr = ptov( paddr, (fsize_t)NCPQ ); ! 100: rp->q_size = 0; ! 101: rp->q_mask = NCPQ - 1; ! 102: ! 103: rp->q_ifaddr = faddr; ! 104: rp->q_ofaddr = faddr; ! 105: } ! 106: } ! 107: return 0; ! 108: } ! 109: ! 110: /* ! 111: * Unload Routine. ! 112: */ ! 113: static void ! 114: rpuload() ! 115: { ! 116: register struct ring *rp; ! 117: ! 118: /* ! 119: * Release virtual address mappers. ! 120: */ ! 121: for ( rp = &rpq[0]; rp < &rpq[NRP]; rp++ ) { ! 122: if ( rp->q_ifaddr ) ! 123: vrelse( rp->q_ifaddr ); ! 124: } ! 125: ! 126: /* ! 127: * Release ring buffer storage. ! 128: */ ! 129: if ( rpsegp != NULL ) { ! 130: sfree( rpsegp ); ! 131: rpsegp = NULL; ! 132: } ! 133: ! 134: /* ! 135: * Erase private data. ! 136: */ ! 137: memset( &rpq[0], 0, sizeof(rpq) ); ! 138: } ! 139: ! 140: /* ! 141: * Open Routine ! 142: */ ! 143: static ! 144: rpopen( dev, mode ) ! 145: dev_t dev; ! 146: { ! 147: int s; ! 148: ! 149: s = sphi(); ! 150: if ( rpq[0].q_mask == 0 ) ! 151: if ( rpinit() < 0 ) ! 152: u.u_error = ENOSPC; ! 153: spl( s ); ! 154: if ( minor(dev) >= NRP ) ! 155: u.u_error = ENXIO; ! 156: } ! 157: ! 158: /* ! 159: * Ioctl Routine ! 160: */ ! 161: static ! 162: rpioctl( dev, com, vec ) ! 163: dev_t dev; ! 164: { ! 165: switch ( com ) { ! 166: ! 167: case TIOCQUERY: ! 168: putuwd( vec, rpq[ minor(dev) ].q_size ); ! 169: return; ! 170: ! 171: case TIOCOUTQ: ! 172: putuwd( vec, rpq[ minor(dev) ].q_size ); ! 173: return; ! 174: ! 175: case TIOCFLUSH: ! 176: case TCFLSH: ! 177: rpflush( &rpq[minor(dev)] ); ! 178: return; ! 179: ! 180: default: ! 181: u.u_error = EINVAL; ! 182: return; ! 183: } ! 184: } ! 185: ! 186: /* ! 187: * Read Routine ! 188: */ ! 189: static ! 190: rpread( dev, iop ) ! 191: dev_t dev; ! 192: register IO *iop; ! 193: { ! 194: register struct ring *rp; ! 195: unsigned n; ! 196: int s; ! 197: ! 198: rp = &rpq[ minor(dev) ]; ! 199: s = sphi(); ! 200: ! 201: /* ! 202: * Wait until read is unlocked, and there is data to read ! 203: */ ! 204: while ( (rp->q_igate[0] != 0) || ((n = rp->q_size) == 0) ) { ! 205: ! 206: /* ! 207: * Non-blocking reads. ! 208: */ ! 209: if ( iop->io_flag & IONDLY ) { ! 210: u.u_error = EAGAIN; ! 211: return; ! 212: } ! 213: ! 214: ++rp->q_igate[1]; ! 215: sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT ); ! 216: --rp->q_igate[1]; ! 217: ! 218: if ( SELF->p_ssig && nondsig() ) { /* signal received */ ! 219: ! 220: spl( s ); ! 221: u.u_error = EINTR; ! 222: return; ! 223: } ! 224: } ! 225: rp->q_igate[0] = 1; /* lock read gate */ ! 226: spl( s ); ! 227: ! 228: if ( n > iop->io_ioc ) /* more data than requested */ ! 229: n = iop->io_ioc; ! 230: ! 231: rucopy( rp, iop->io_base, n ); /* copy data to user space */ ! 232: iop->io_base += n; ! 233: iop->io_ioc -= n; ! 234: ! 235: if ( rp->q_ogate[1] != 0 ) /* someone waiting to write */ ! 236: wakeup( rp->q_ogate ); ! 237: if ( rp->q_opoll.e_procp ) /* someone polling to write */ ! 238: pollwake( &rp->q_opoll ); ! 239: ! 240: rp->q_igate[0] = 0; /* unlock read gate */ ! 241: ! 242: if ( rp->q_igate[1] != 0 ) /* others waiting to read */ ! 243: wakeup( rp->q_igate ); ! 244: } ! 245: ! 246: /* ! 247: * Write Routine ! 248: */ ! 249: static ! 250: rpwrite( dev, iop ) ! 251: dev_t dev; ! 252: register IO *iop; ! 253: { ! 254: register struct ring *rp; ! 255: unsigned n; ! 256: int s; ! 257: ! 258: rp = &rpq[ minor(dev) ]; ! 259: ! 260: do { ! 261: s = sphi(); ! 262: /* ! 263: * Wait until write is unlocked and 512 free slots exist ! 264: */ ! 265: ! 266: while ((rp->q_ogate[0] != 0) || ((n = NCPQ-rp->q_size) < 512)) { ! 267: ! 268: /* ! 269: * Non-blocking writes. ! 270: */ ! 271: if ( iop->io_flag & IONDLY ) { ! 272: u.u_error = EAGAIN; ! 273: return; ! 274: } ! 275: ! 276: ++rp->q_ogate[1]; ! 277: sleep( rp->q_ogate, CVTTOUT, IVTTOUT, SVTTOUT ); ! 278: --rp->q_ogate[1]; ! 279: ! 280: if (SELF->p_ssig && nondsig()) { /* received signal */ ! 281: ! 282: spl( s ); ! 283: u.u_error = EINTR; ! 284: return; ! 285: } ! 286: } ! 287: rp->q_ogate[0] = 1; /* lock write gate */ ! 288: spl( s ); ! 289: ! 290: if ( n > iop->io_ioc ) ! 291: n = iop->io_ioc; ! 292: ! 293: urcopy( iop->io_base, rp, n ); /* copy data from user space */ ! 294: iop->io_base += n; ! 295: iop->io_ioc -= n; ! 296: ! 297: rp->q_ogate[0] = 0; /* unlock write gate */ ! 298: ! 299: if ( rp->q_igate[1] != 0 ) /* someone waiting to read */ ! 300: wakeup( rp->q_igate ); ! 301: ! 302: if ( rp->q_ipoll.e_procp ) /* someone polling to read */ ! 303: pollwake( &rp->q_ipoll ); ! 304: ! 305: } while ( iop->io_ioc != 0 ); /* until all data copied */ ! 306: ! 307: if (rp->q_ogate[1] != 0) /* someone waiting to write */ ! 308: wakeup( rp->q_ogate ); ! 309: } ! 310: ! 311: /* ! 312: * Poll. ! 313: */ ! 314: rppoll( dev, ev, msec ) ! 315: dev_t dev; ! 316: int ev; ! 317: int msec; ! 318: { ! 319: register struct ring *rp = &rpq[ minor(dev) ]; ! 320: ! 321: ev &= ~POLLPRI; ! 322: ! 323: /* ! 324: * Input poll. ! 325: */ ! 326: if ( ev & POLLIN ) { ! 327: ! 328: /* ! 329: * Pipe empty. ! 330: */ ! 331: if ( FP_OFF(rp->q_ifaddr) == FP_OFF(rp->q_ofaddr) ) { ! 332: if ( msec != 0 ) ! 333: pollopen( &rp->q_ipoll ); ! 334: ev &= ~POLLIN; ! 335: } ! 336: } ! 337: ! 338: /* ! 339: * Output poll. ! 340: */ ! 341: if ( ev & POLLOUT ) { ! 342: ! 343: /* ! 344: * Pipe not empty. ! 345: */ ! 346: if ( FP_OFF(rp->q_ifaddr) != FP_OFF(rp->q_ofaddr) ) { ! 347: if ( msec != 0 ) ! 348: pollopen( &rp->q_opoll ); ! 349: ev &= ~POLLOUT; ! 350: } ! 351: } ! 352: ! 353: return ev; ! 354: } ! 355: ! 356: /* ! 357: * Flush queue ! 358: */ ! 359: static ! 360: rpflush( rp ) ! 361: register struct ring *rp; ! 362: { ! 363: register int s; ! 364: ! 365: s = sphi(); ! 366: ! 367: /* ! 368: * Wait until read is unlocked, or nothing in queue ! 369: */ ! 370: ! 371: while ((rp->q_size != 0) && (rp->q_igate[0] != 0) ) { ! 372: ! 373: ++rp->q_igate[1]; ! 374: sleep( rp->q_igate, CVTTOUT, IVTTOUT, SVTTOUT ); ! 375: --rp->q_igate[1]; ! 376: ! 377: if (SELF->p_ssig && nondsig()) { /* received signal */ ! 378: ! 379: spl( s ); ! 380: u.u_error = EINTR; ! 381: return; ! 382: } ! 383: } ! 384: ! 385: if (rp->q_size != 0) { /* flush ram pipe */ ! 386: ! 387: rp->q_ofaddr = rp->q_ifaddr; ! 388: rp->q_size = 0; ! 389: } ! 390: spl( s ); ! 391: ! 392: if (rp->q_ogate[1] != 0) /* someone waiting to write */ ! 393: wakeup( rp->q_ogate ); ! 394: ! 395: if ( rp->q_opoll.e_procp ) /* someone polling to write */ ! 396: pollwake( &rp->q_opoll ); ! 397: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.