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