1: /*
   2:  *	SCCS id	@(#)du.c	2.1 (Berkeley)	8/5/83
   3:  */
   4: 
   5: /*
   6:  * DU-11 and DUP-11 synchronous line interface driver
   7:  */
   8: 
   9: 
  10: #include "du.h"
  11: #if NDU > 0
  12: #include "param.h"
  13: #include <sys/conf.h>
  14: #include <sys/buf.h>
  15: #include <sys/proc.h>
  16: #include <sys/dir.h>
  17: #include <sys/user.h>
  18: #include <sys/systm.h>
  19: #include <sys/dureg.h>
  20: 
  21: extern  struct  dudevice *DUADDR;
  22: 
  23: /*
  24:  * receiver interrupt code state definitions
  25:  */
  26: #define RIDLE   0       /* idle, waiting for a message */
  27: #define RRUN    1       /* running, message in progress */
  28: #define RQUIT1  2       /* quit, trashing all until carrier drop */
  29: #define RQUIT2  3       /* same as above, but return error */
  30: 
  31: /*
  32:  * transmitter interrupt code state definitions
  33:  */
  34: #define TIDLE   0       /* idle, waiting for a message */
  35: #define TRUN    1       /* running, message in progress */
  36: #define TLAST   2       /* sending last character */
  37: #define TCARDRP 3       /* waiting for carrier hold-down delay */
  38: 
  39: /*
  40:  * miscellaneous defintions
  41:  */
  42: #define SYN 026     /* sync character */
  43: #define MSGN    5       /* number of message buffers each direction */
  44: #define MSGLEN  102     /* length of each message buffer */
  45: #define TIMEOUT 3       /* number of seconds before receive timeout */
  46: #define TDELAY  2       /* number ticks to hold down xmit carrier */
  47: #define DUPRI   5       /* du11 sleep priority */
  48: 
  49: /*
  50:  * message buffer descriptor
  51:  */
  52: struct  msgbuf  {
  53:     caddr_t msgbufp;    /* pointer to message buffer */
  54:     char    msgbc;      /* message byte count */
  55:     char    msgerr;     /* nonzero if error in message */
  56: };
  57: 
  58: /*
  59:  * du11 control info
  60:  */
  61: struct  {
  62:     struct  proc    *duproc;    /* process adr of caller, 0 if closed */
  63:     /*
  64: 	 * Transmit info
  65: 	 */
  66:     struct  buf *dutbufp;   /* pointer to transmit buffer */
  67:     struct  msgbuf  dutbuff[MSGN]; /* message buffer descriptors */
  68:     struct  msgbuf  *dutbufi; /* in pointer */
  69:     struct  msgbuf  *dutbufo; /* out pointer */
  70:     short   dutbufn;    /* number of message buffers that are full */
  71:     short   dutstate;   /* state of transmitter interrupt code */
  72:     caddr_t dutbufc;    /* char ptr for message in progress */
  73:     short   dutbc;      /* byte count of message in progress */
  74:     short   dutdna;     /* number of times data not available */
  75:     /*
  76: 	 * Receive info
  77: 	 */
  78: #ifndef UCB_NKB
  79:     struct  buf *durbufp;   /* pointer to receive buffer */
  80: #endif
  81:     struct  msgbuf  durbuff[MSGN]; /* message buffer descriptors */
  82:     struct  msgbuf  *durbufi; /* in pointer */
  83:     struct  msgbuf  *durbufo; /* out pointer */
  84:     short   durbufn;    /* number of message buffers that are full */
  85:     short   durstate;   /* state of receiver interrupt code */
  86:     caddr_t durbufc;    /* char ptr for message in progress */
  87:     short   durbc;      /* byte count of message in progress */
  88:     short   durtimer;   /* seconds left until timeout */
  89:     short   durover;    /* number of receiver data overruns */
  90:     short   durfull;    /* number of times receive buffer full */
  91:     short   durlong;    /* number of messages > 255 bytes */
  92: } du11;
  93: 
  94: #define MAINTDEV    1   /* minor device for maintenance mode */
  95: int     maint;          /* nonzero if open for maintenance */
  96: 
  97: /*ARGSUSED*/
  98: duopen(dev, flag)
  99: dev_t   dev;
 100: {
 101:     register struct dudevice *duaddr = DUADDR;
 102:     register n;
 103:     extern  durtimeout();
 104: 
 105:     if (du11.duproc == u.u_procp)
 106:         return;
 107:     if (du11.duproc) {
 108:         u.u_error = ENXIO;
 109:         return;
 110:     }
 111: 
 112:     /*
 113: 	 * Check whether opening for maintenance mode
 114: 	 */
 115:     if (minor(dev) == MAINTDEV)
 116:         maint = 1;
 117:     else
 118:         maint = 0;
 119: 
 120:     /*
 121: 	 * reset device
 122: 	 */
 123:     duaddr->dutcsr = DUTCSR_MR;
 124: 
 125:     /*
 126: 	 * Allocate transmit buffer
 127: 	 */
 128:     du11.dutbufp = geteblk();
 129:     du11.dutbufi = du11.dutbufo = du11.dutbuff;
 130:     du11.dutbufn = 0;
 131:     for(n = 0; n < MSGN; n++)
 132:         du11.dutbuff[n].msgbufp = du11.dutbufp->b_un.b_addr + MSGLEN*n;
 133:     du11.dutstate = TIDLE;
 134: 
 135:     /*
 136: 	 * Allocate receive buffer
 137: 	 */
 138: #ifndef UCB_NKB
 139:     du11.durbufp = geteblk();
 140:     for(n = 0; n < MSGN; n++)
 141:         du11.durbuff[n].msgbufp = du11.durbufp->b_un.b_addr+(MSGLEN*n);
 142: #else
 143: #if UCB_NKB >= 1
 144:     for(n = 0; n < MSGN; n++)
 145:         du11.durbuff[n].msgbufp = (du11.dutbufp->b_un.b_addr+(BSIZE/2))
 146:                         + (MSGLEN * n);
 147: #else
 148:     THIS IS AN ERROR!;
 149: #endif
 150: #endif
 151:     du11.durbufi = du11.durbufo = du11.durbuff;
 152:     du11.durbufn = 0;
 153:     du11.durstate = RIDLE;
 154: 
 155:     /*
 156: 	 * Start 1 second receiver timeout clock
 157: 	 */
 158:     du11.durtimer = 0;
 159:     timeout(durtimeout, 0, hz);
 160:     du11.duproc = u.u_procp;
 161: 
 162:     /*
 163: 	 * Set parameters according to whether du11 or dup11
 164: 	 */
 165: #ifdef  DU11
 166:     duaddr->durdbuf = DUPARCSR_8BITS | DUPARCSR_ISYNC | SYN;
 167: #else
 168:     duaddr->durdbuf = DUPARCSR_DEC | DUPARCSR_CRCINH | SYN;
 169:     if (maint)
 170:         duaddr->dutcsr = DUTCSR_MPSYSTST;
 171: #endif
 172:     /*
 173: 	 * Start receiver
 174: 	 */
 175:     duaddr->durcsr = DU_STSYNC | DU_DTR | DU_SSYNC;
 176: }
 177: 
 178: duclose()
 179: {
 180:     register struct dudevice *duaddr = DUADDR;
 181: 
 182:     /*
 183: 	 * Stop device and disable interrupts
 184: 	 */
 185:     duaddr->durcsr = 0;
 186:     duaddr->dutcsr = 0;
 187: 
 188:     /*
 189: 	 * Stop timer
 190: 	 */
 191:     du11.durtimer = -1;
 192:     while (du11.durtimer)
 193:         sleep(&du11.durstate, DUPRI);
 194: 
 195:     /*
 196: 	 * Stop interrupt code for sure
 197: 	 */
 198:     du11.duproc = 0;
 199: 
 200:     /*
 201: 	 * Release buffers
 202: 	 */
 203: #ifdef  UCB_BUFOUT
 204: #define brelse  abrelse
 205: #endif
 206:     brelse(du11.dutbufp);
 207: #ifndef UCB_NKB
 208:     brelse(du11.durbufp);
 209: #endif
 210: 
 211:     /*
 212: 	 * clear maintenance mode flag
 213: 	 */
 214:     maint = 0;
 215: }
 216: 
 217: duread()
 218: {
 219:     register nbytes;
 220: 
 221:     /*
 222: 	 * wait for a message to appear in the receive buffer or for TIMEOUT
 223: 	 * seconds to elapse
 224: 	 */
 225:     du11.durtimer = TIMEOUT;
 226:     (void) _spl6();
 227:     while (du11.durbufn == 0) {
 228:         if (du11.durtimer == 0) {
 229:             (void) _spl0();
 230:             return;
 231:         }
 232:         sleep(&du11.durstate, DUPRI);
 233:     }
 234:     (void) _spl0();
 235:     du11.durtimer = 0;
 236: 
 237:     /*
 238: 	 * if an error was detected on this message, throw it away and return
 239: 	 * an error to the caller
 240: 	 */
 241:     if (du11.durbufo->msgerr) {
 242:         if (++du11.durbufo == du11.durbuff + MSGN)
 243:             du11.durbufo = du11.durbuff;
 244:         du11.durbufn--;
 245:         u.u_error = EIO;
 246:         return;
 247:     }
 248: 
 249:     /*
 250: 	 * Copy the message to the caller's buffer
 251: 	 */
 252:     nbytes = min(u.u_count, du11.durbufo->msgbc);
 253:     iomove(du11.durbufo->msgbufp, nbytes, B_READ);
 254:     if (++du11.durbufo == du11.durbuff + MSGN)
 255:         du11.durbufo = du11.durbuff;
 256:     du11.durbufn--;
 257: }
 258: 
 259: duwrite()
 260: {
 261:     register nbytes;
 262: 
 263:     /*
 264: 	 * Wait for there to be room for the message in the buffer
 265: 	 */
 266:     while (du11.dutbufn == MSGN)
 267:         sleep(&du11.dutstate, DUPRI);
 268: 
 269:     /*
 270: 	 * Transfer  the message from the caller's buffer to ours
 271: 	 */
 272:     nbytes = min(u.u_count, MSGLEN);
 273:     du11.dutbufi->msgbc = nbytes;
 274:     iomove(du11.dutbufi->msgbufp, nbytes, B_WRITE);
 275:     if (++du11.dutbufi == du11.dutbuff + MSGN)
 276:         du11.dutbufi = du11.dutbuff;
 277:     du11.dutbufn++;
 278: 
 279:     /*
 280: 	 * If the interrupt code is not running, start it up
 281: 	 */
 282:     if (du11.dutstate == TIDLE)
 283:         duxstart();
 284: }
 285: 
 286: durint()
 287: {
 288:     register c, dustat;
 289:     register struct dudevice *duaddr = DUADDR;
 290: 
 291:     dustat = duaddr->durcsr;
 292:     if (du11.duproc == 0) {
 293:         duaddr->dutcsr = DUTCSR_MR;
 294:         if (maint)
 295: #ifdef  DU11
 296:             duaddr->dutcsr |= DUTCSR_MSYSTST;
 297: #ifdef  UCB_DEVERR
 298:         printf("durint: er=%b\n", dustat, DU_BITS);
 299: #else
 300:         printf("durint err %o\n", dustat);
 301: #endif
 302: #else
 303:             duaddr->dutcsr |= DUTCSR_MPSYSTST;
 304: #ifdef  UCB_DEVERR
 305:         printf("durint: er=%b\n", dustat, DU_PBITS);
 306: #else
 307:         printf("durint err %o\n", dustat);
 308: #endif
 309: #endif	DU11
 310:         return;
 311:     }
 312:     switch(du11.durstate) {
 313: 
 314:     /*
 315: 	 * Wait for the first char to be rcvd, ignoring carrier changes
 316: 	 */
 317:     case RIDLE:
 318:         if ((dustat & DU_RDONE) == 0)
 319:             return;
 320:         if (du11.durbufn == MSGN)
 321:             goto rfull;
 322:         du11.durbufc = du11.durbufi->msgbufp; /* set up char ptr */
 323:         du11.durbufi->msgerr = 0;   /* set no error in msg */
 324:         du11.durbc = 0;         /* set byte count */
 325:         du11.durstate = RRUN;       /* set message in progress */
 326: 
 327:     /*
 328: 	 * A message is in progress
 329: 	 */
 330:     case RRUN:
 331:         if (dustat & DU_RDONE) {    /* a character has arrived */
 332:             c = duaddr->durdbuf;
 333: 
 334:             /*
 335: 			 * End message if lost character or message too long
 336: 			 */
 337:             if (c & DURDBUF_OVERRUN) {
 338:                 du11.durover++;
 339:                 goto rerror;
 340:             }
 341:             if (du11.durbc++ == MSGLEN) {
 342:                 du11.durlong++;
 343:                 goto rerror;
 344:             }
 345:             *du11.durbufc++ = c;
 346:         }
 347:         if ((dustat & DU_CAR) == 0) /* carrier drop means */
 348:             break;          /* end of message */
 349:         return;
 350: 
 351:     /*
 352: 	 * We have used up all the message buffers. Throw the
 353: 	 * message away.
 354: 	 */
 355: rfull:
 356:         du11.durfull++;
 357:         du11.durstate = RQUIT1;
 358:     case RQUIT1:
 359:         if ((dustat & DU_CAR) == 0) {
 360:             du11.durstate = RIDLE;
 361:             duaddr->durcsr &= ~DU_SSYNC;    /* desync receiver */
 362:             duaddr->durcsr |= DU_SSYNC;
 363:         }
 364:         c = duaddr->durdbuf;
 365:         return;
 366: 
 367:     /*
 368: 	 * Flag the message no good and junk the rest of it
 369: 	 */
 370: rerror:
 371:         du11.durbufi->msgerr++;
 372:         du11.durstate = RQUIT2;
 373: 
 374:     case RQUIT2:
 375:         c = duaddr->durdbuf;
 376:         if (dustat & DU_CAR)
 377:             return;
 378:     }
 379: 
 380:     /*
 381: 	 * The message is finished. Set up the byte count and advance
 382: 	 * the in pointer to pass the message to the upper-level code.
 383: 	 */
 384:     du11.durbufi->msgbc = du11.durbc;
 385:     if (++du11.durbufi == du11.durbuff + MSGN)
 386:         du11.durbufi = du11.durbuff;
 387:     du11.durbufn++;
 388:     du11.durstate = RIDLE;
 389:     duaddr->durcsr &= ~DU_SSYNC;        /* desync receiver */
 390:     duaddr->durcsr |= DU_SSYNC;
 391:     c = duaddr->durdbuf;
 392:     wakeup(&du11.durstate);
 393: }
 394: 
 395: duxint()
 396: {
 397:     register dustat;
 398:     register struct dudevice *duaddr = DUADDR;
 399:     extern duxfin();
 400: 
 401:     dustat = duaddr->dutcsr;
 402:     if (du11.duproc == 0) {
 403:         duaddr->dutcsr = DUTCSR_MR;
 404:         if (maint)
 405: #ifdef  DU11
 406:             duaddr->dutcsr |= DUTCSR_MSYSTST;
 407: #ifdef  UCB_DEVERR
 408:         printf("duxint:  er=%b\n", dustat, DUTCSR_BITS);
 409: #else
 410:         printf("duxint err %o\n", dustat);
 411: #endif
 412: #else
 413:             duaddr->dutcsr |= DUTCSR_MPSYSTST;
 414: #ifdef  UCB_DEVERR
 415:         printf("duxint:  er=%b\n", dustat, DUTCSR_PBITS);
 416: #else
 417:         printf("duxint err %o\n", dustat);
 418: #endif
 419: #endif
 420:         return;
 421:     }
 422:     switch(du11.dutstate) {
 423: 
 424:     /*
 425: 	 * A message is in progress
 426: 	 */
 427:     case TRUN:
 428:         /*
 429: 		 * Count number of times data not available
 430: 		 */
 431:         if (dustat & DUTCSR_NODATA)
 432:             du11.dutdna++;
 433:         if (dustat & DUTCSR_TDONE) {
 434:             if (--du11.dutbc) { /* if there are more chars */
 435:                 duaddr->dutdbuf = *du11.dutbufc++ & 0377;
 436: #ifndef DU11
 437:                 if (du11.dutbc == 1) {
 438:                     duaddr->dutdbuf = DURDBUF_REOM;
 439:                     duaddr->dutcsr &= ~DUTCSR_SEND;
 440:                     du11.dutstate = TLAST;
 441:                 }
 442: #endif
 443:             }
 444: #ifdef  DU11
 445:             else            /* wait for the last one */
 446:                 {
 447:                 duaddr->dutcsr = DUTCSR_SEND | DUTCSR_DNAIE;
 448:                 if (maint)
 449:                     duaddr->dutcsr |= DUTCSR_MSYSTST;
 450:                 du11.dutstate = TLAST;
 451:             }
 452: #endif
 453:         }
 454:         return;
 455: 
 456:     /*
 457: 	 * Wait for the data not available flag, signifying that the
 458: 	 * last char has been completely sent
 459: 	 */
 460:     case TLAST:
 461: #ifdef  DU11
 462:         if (dustat & DUTCSR_NODATA)
 463: #endif
 464:             {
 465:             du11.dutstate = TCARDRP;
 466:             duaddr->dutcsr = 0; /* drop carrier */
 467:             if (maint)
 468: #ifdef  DU11
 469:                 duaddr->dutcsr |= DUTCSR_MSYSTST;
 470: #else
 471:                 duaddr->dutcsr |= DUTCSR_MPSYSTST;
 472: #endif
 473:             duaddr->durcsr &= ~DU_RTS;
 474:             timeout(duxfin, 0, TDELAY);
 475:         }
 476:     }
 477: }
 478: 
 479: /*
 480:  * Carrier hold-down delay completed
 481:  */
 482: duxfin()
 483: {
 484:     if (++du11.dutbufo == du11.dutbuff + MSGN)
 485:         du11.dutbufo = du11.dutbuff;
 486:     du11.dutbufn--;
 487:     du11.dutstate = TIDLE;
 488: 
 489:     /*
 490: 	 * If there is another message in the buffer, start sending it
 491: 	 */
 492:     if (du11.dutbufi != du11.dutbufo)
 493:         duxstart();
 494:     wakeup(&du11.dutstate);
 495: }
 496: 
 497: /*
 498:  * Start transmitting a new message
 499:  */
 500: duxstart()
 501: {
 502:     register struct dudevice *duaddr = DUADDR;
 503: 
 504:     du11.dutbc = du11.dutbufo->msgbc;
 505:     du11.dutbufc = du11.dutbufo->msgbufp;
 506:     du11.dutstate = TRUN;
 507:     duaddr->durcsr |= DU_RTS;
 508: 
 509:     duaddr->dutcsr = DUTCSR_SEND;
 510:     if (maint)
 511: #ifdef  DU11
 512:         duaddr->dutcsr |= DUTCSR_MSYSTST;
 513: #else
 514:         duaddr->dutcsr |= DUTCSR_MPSYSTST;
 515: #endif
 516:     duaddr->dutdbuf = DURDBUF_RSOM | (*du11.dutbufc++ & 0377);
 517: 
 518:     /*
 519: 	 * Turn on interrupts
 520: 	 */
 521:     duaddr->durcsr |= DU_RIE;
 522:     duaddr->dutcsr |= DUTCSR_TIE;
 523: }
 524: 
 525: /*
 526:  * Exit if being closed
 527:  */
 528: durtimeout()
 529: {
 530:     if (du11.durtimer < 0) {
 531:         du11.durtimer = 0;
 532:         wakeup(&du11.durstate);
 533:         return;
 534:     }
 535: 
 536:     /*
 537: 	 * If duread is sleeping, decrement timer and wakeup if time's up
 538: 	 */
 539:     if (du11.durtimer > 0)
 540:         if (--du11.durtimer == 0)
 541:             wakeup(&du11.durstate);
 542:     timeout(durtimeout, 0, hz);
 543: }
 544: #endif	NDU

Defined functions

duclose defined in line 178; never used
duopen defined in line 98; never used
duread defined in line 217; never used
durint defined in line 286; never used
durtimeout defined in line 528; used 3 times
duwrite defined in line 259; never used
duxfin defined in line 482; used 2 times
duxint defined in line 395; never used
duxstart defined in line 500; used 2 times

Defined variables

maint defined in line 95; used 9 times

Defined struct's

msgbuf defined in line 52; used 12 times

Defined macros

DUPRI defined in line 47; used 3 times
MAINTDEV defined in line 94; used 1 times
MSGLEN defined in line 44; used 5 times
MSGN defined in line 43; used 12 times
RIDLE defined in line 26; used 3 times
RQUIT1 defined in line 28; used 1 times
RQUIT2 defined in line 29; used 1 times
RRUN defined in line 27; used 1 times
SYN defined in line 42; used 2 times
TCARDRP defined in line 37; used 1 times
TDELAY defined in line 46; used 1 times
TIDLE defined in line 34; used 3 times
TIMEOUT defined in line 45; used 1 times
TLAST defined in line 36; used 2 times
TRUN defined in line 35; used 1 times
brelse defined in line 204; used 2 times
Last modified: 1983-08-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1479
Valid CSS Valid XHTML 1.0 Strict