|
|
1.1 ! root 1: /* ! 2: * stream driver for DK via KMC-11/KDI board ! 3: * delicately intertwined with kmc.c ! 4: */ ! 5: ! 6: #include "sys/param.h" ! 7: #include "sys/stream.h" ! 8: #include "sys/ttyio.h" ! 9: #include "sys/dkio.h" ! 10: #include "sys/conf.h" ! 11: #include "sys/dkstat.h" ! 12: #include "sys/dkmod.h" ! 13: #include "sys/ubaddr.h" ! 14: #include "sys/kmc.h" ! 15: #include "sys/kdi.h" ! 16: #include "sys/buf.h" ! 17: #include "sys/dkwindow.h" ! 18: ! 19: #define KDIPRI 28 ! 20: ! 21: /* ! 22: * flags ! 23: */ ! 24: #define KMBUSY 0x01 ! 25: #define KMSTOP 0x02 ! 26: #define KMINC 0x04 ! 27: #define KMBIG 0x3c /* rcvd lots last time, use big rcv buffer */ ! 28: #define KMXCL 0x40 /* exclusive use */ ! 29: #define KMXBIG 0x80 /* tell KMC to use large messages */ ! 30: #define BIGSET(c) ((((c)<<1)|KMINC)&KMBIG | ((c)&~KMBIG)) ! 31: #define BIGCLR(c) (((c)<<1)&KMBIG | ((c)&~KMBIG)) ! 32: ! 33: /* ! 34: * device structure ! 35: */ ! 36: struct device { ! 37: char sts; ! 38: char x1; ! 39: union { ! 40: struct { ! 41: u_short lo; ! 42: u_char hi; ! 43: } a; ! 44: struct { ! 45: u_char x2; ! 46: u_char x3; ! 47: u_char ch; ! 48: u_char ct; ! 49: u_char sh; ! 50: u_char st; ! 51: } q; ! 52: } u; ! 53: }; ! 54: ! 55: /* ! 56: * KMC commands ! 57: */ ! 58: #define KC_INIT 1 ! 59: #define KC_SEND 2 ! 60: #define KC_RCVB 3 ! 61: #define KC_CLOSE 4 ! 62: #define KC_XINIT 5 ! 63: #define KC_CMD 6 ! 64: #define KC_FLAG 7 ! 65: #define KC_SOI 8 ! 66: ! 67: /* ! 68: * subcommands of KC_CMD or KC_SEND ! 69: */ ! 70: #define OFLUSH 02 /* flush output */ ! 71: #define OSPND 04 /* suspend output */ ! 72: #define ORSME 010 /* resume output */ ! 73: #define OBOTM 0200 /* send BOTM trailer, not BOT */ ! 74: ! 75: /* ! 76: * KMC reports ! 77: */ ! 78: #define KS_SEND 024 ! 79: #define KS_RDB 025 ! 80: #define KS_EOI 026 ! 81: #define KS_CNTL 027 ! 82: #define KS_ERR 030 ! 83: ! 84: /* ! 85: * KC_RCV modes ! 86: */ ! 87: #define CBLOCK 0040 /* return on block boundary */ ! 88: #define CTIME 0100 /* return when time expires */ ! 89: ! 90: /* ! 91: * KS_RDB mode ! 92: */ ! 93: #define SFULL 0001 /* buffer full */ ! 94: #define SCNTL 0002 /* cntl char recv */ ! 95: #define SABORT 0010 /* rcv aborted */ ! 96: #define SBLOCK 0040 /* block boundary */ ! 97: #define STIME 0100 /* time limit expired */ ! 98: ! 99: /* ! 100: * URP control characters ! 101: */ ! 102: #define D_DELAY 0100 ! 103: #define D_BREAK 0110 ! 104: ! 105: /* ! 106: * KMC errors ! 107: */ ! 108: #define E_NOQB 4 /* internal buffer runout */ ! 109: #define E_DUP 5 /* duplicate send (shouldn't but does happen) */ ! 110: #define E_UMETA 7 /* unknown control character */ ! 111: ! 112: /* ! 113: * tracing ! 114: */ ! 115: #define DEBUG ! 116: #ifdef DEBUG ! 117: struct kin ktrbuf[256]; ! 118: struct kin *ktrp = ktrbuf; ! 119: #define TRACE(x) *ktrp++ = x; if (ktrp >= &ktrbuf[256]) ktrp = ktrbuf; ! 120: #else ! 121: #define TRACE(x) ; ! 122: #endif ! 123: ! 124: int kdiclose(), kdiput(), kdiisrv(); ! 125: long kdiopen(); ! 126: struct qinit kdirinit = { noput, kdiisrv, kdiopen, kdiclose, 0, 0 }; ! 127: struct qinit kdiwinit = { kdiput, NULL, kdiopen, kdiclose, 512, 128 }; ! 128: struct streamtab kdiinfo = { &kdirinit, &kdiwinit }; ! 129: struct cdevsw kdicdev = cstrinit(&kdiinfo); ! 130: ! 131: struct kmaddr kmcubaddr(); ! 132: extern struct kdikmc kdikmc[]; ! 133: extern struct kmcdk k[]; ! 134: extern int kdicnt; ! 135: extern struct kmc kmc[]; ! 136: extern struct ubaddr kmcaddr[]; ! 137: extern int kmccnt; ! 138: struct dkstat dkstat; ! 139: ! 140: #define KDICHAN 96 /* channels per kdi (== per kmc) */ ! 141: #define KMC(d) ((d)/KDICHAN) ! 142: #define CHAN(d) ((d)%KDICHAN) ! 143: ! 144: /* ! 145: * open channel ! 146: */ ! 147: long ! 148: kdiopen(q, dev) ! 149: register struct queue *q; ! 150: dev_t dev; ! 151: { ! 152: register struct kdi *kp; ! 153: register struct block *bp; ! 154: register struct kdikmc *xp; ! 155: register int kno, chan; ! 156: ! 157: kno = KMC(minor(dev)); ! 158: chan = CHAN(minor(dev)); ! 159: if (kno >= kdicnt || kno >= kmccnt || chan >= KDICHAN) ! 160: return (0); ! 161: xp = &kdikmc[kno]; ! 162: if (xp->bad) ! 163: return (0); ! 164: if (xp->init == 0) ! 165: if (kdiinit(dev) == 0) ! 166: return (0); ! 167: kp = &xp->kdi[chan]; ! 168: if (xp->state[chan] != DKCLOSED) { ! 169: if (kp->ostate&KMXCL) /* exclusive use until reset */ ! 170: return(0); ! 171: if (xp->state[chan] != DKOPEN) ! 172: return(0); /* closing channels cannot reopen */ ! 173: return(1); ! 174: } ! 175: kp->dkrq = q; ! 176: q->ptr = (caddr_t)kp; ! 177: WR(q)->flag |= QDELIM|QBIGB; ! 178: q->flag |= QDELIM; ! 179: WR(q)->ptr = (caddr_t)kp; ! 180: xp->state[chan] = DKOPEN; ! 181: kp->ostate = KMXCL; ! 182: kcmd(kno, KC_INIT, kp->chan, 0, 0, 0, (uaddr_t)NULL); ! 183: if ((bp = allocb(64)) == NULL) { ! 184: xp->state[chan] = 0; ! 185: return(0); ! 186: } ! 187: kp->lastctl = 0; ! 188: kp->ibp = bp; ! 189: kp->imap = ubmblk(xp->ubno, bp, 0); ! 190: kcmd(kno, KC_RCVB, chan, bp->lim-bp->wptr, 50, ! 191: CBLOCK|CTIME, ubadwptr(xp->ubno, bp, kp->imap)); ! 192: return(1); ! 193: } ! 194: ! 195: kdiclose(q) ! 196: register struct queue *q; ! 197: { ! 198: register struct kdi *kp = (struct kdi *)q->ptr; ! 199: register s, i; ! 200: register struct kdikmc *xp; ! 201: ! 202: xp = &kdikmc[kp->kno]; ! 203: if (xp->modp == NULL || xp->modp->listnrq == NULL ! 204: || xp->state[kp->chan]==DKRCLOSE) ! 205: xp->state[kp->chan] = DKCLOSED; ! 206: else if (xp->state[kp->chan] == DKOPEN) { ! 207: xp->state[kp->chan] = DKLCLOSE; ! 208: for (i=0; i<30 && (WR(q)->count || kp->obp); i++) ! 209: tsleep((caddr_t)kp, KDIPRI, 1); ! 210: } ! 211: kp->dkrq = NULL; ! 212: if (xp->modp && xp->modp->listnrq) ! 213: putctl2(RD(xp->modp->listnrq), M_PRICTL, DKMCLOSE, kp->chan); ! 214: s = spl6(); ! 215: if (kp->obp) { ! 216: freeb(kp->obp); ! 217: kp->obp = NULL; ! 218: } ! 219: splx(s); ! 220: kp->ostate &= ~KMXCL; ! 221: kcmd(kp->kno, KC_CLOSE, kp->chan, 0, 0, 0, (uaddr_t)NULL); ! 222: } ! 223: ! 224: kdiput(q, bp) ! 225: register struct queue *q; ! 226: register struct block *bp; ! 227: { ! 228: register struct kdi *kdp = (struct kdi *)q->ptr; ! 229: register char *sp; ! 230: register s; ! 231: register struct kdikmc *xp; ! 232: struct block *xbp; ! 233: int t; ! 234: ! 235: xp = &kdikmc[kdp->kno]; ! 236: switch(bp->type) { ! 237: ! 238: case M_CTL: ! 239: case M_DATA: ! 240: case M_DELAY: ! 241: case M_BREAK: ! 242: if (xp->state[kdp->chan] < DKLCLOSE) { ! 243: freeb(bp); ! 244: return; ! 245: } ! 246: putq(q, bp); ! 247: if ((kdp->ostate&KMBUSY)==0) ! 248: kmstart(kdp); ! 249: return; ! 250: ! 251: case M_PRICTL: ! 252: switch (*bp->rptr) { ! 253: case DKMCLOSE: ! 254: s = bp->rptr[1]; ! 255: if (s < KDICHAN) { ! 256: flushq(q, 1); ! 257: if (xp->state[s] == DKOPEN) { ! 258: xp->state[s] = DKRCLOSE; ! 259: putctl(xp->kdi[s].dkrq->next, M_HANGUP); ! 260: } else if (xp->state[s] == DKLCLOSE) ! 261: xp->state[s] = DKCLOSED; ! 262: kcmd(kdp->kno, KC_CLOSE, s, 0, 0, 0, (uaddr_t)NULL); ! 263: } ! 264: break; ! 265: ! 266: case DKMXINIT: ! 267: /* retrieve channel number */ ! 268: bp->rptr++; ! 269: s = *bp->rptr++; ! 270: ! 271: /* forget it if this isn't a valid channel */ ! 272: if (s >= KDICHAN || xp->state[s] != DKOPEN) ! 273: break; ! 274: ! 275: /* next two bytes (if there) are the traffic type */ ! 276: if(bp->wptr-bp->rptr>=2){ ! 277: t = (*bp->rptr++<<8) & 0xff00; ! 278: t |= *bp->rptr++ & 0xff; ! 279: ! 280: /* check window sizes */ ! 281: if (W_VALID(t)) { ! 282: ! 283: /* kmc has only two possible window sizes */ ! 284: t = W_VALUE(W_ORIG(t)); ! 285: if(t<1024) ! 286: xp->kdi[s].ostate &= ~KMXBIG; ! 287: else ! 288: xp->kdi[s].ostate |= KMXBIG; ! 289: } ! 290: } ! 291: ! 292: /* restart urp on the channel, with the correct window */ ! 293: kdixinit(&xp->kdi[s]); ! 294: break; ! 295: ! 296: default: ! 297: break; ! 298: } ! 299: break; /* and freeb */ ! 300: ! 301: case M_IOCTL: ! 302: sp = stiodata(bp); ! 303: bp->type = M_IOCACK; ! 304: switch (stiocom(bp)) { ! 305: ! 306: case TIOCSDEV: ! 307: if (((struct ttydevb *)sp)->ispeed == 0) ! 308: putctl2(q, M_PRICTL, DKMCLOSE, kdp->chan); ! 309: case KIOCISURP: ! 310: bp->wptr = bp->rptr; ! 311: break; ! 312: ! 313: case DIOCSCTL: ! 314: bp->wptr = bp->rptr; ! 315: if (*sp == 0) ! 316: break; ! 317: if ((xbp = allocb(1)) == NULL) ! 318: bp->type = M_IOCNAK; ! 319: else { ! 320: xbp->type = M_CTL; ! 321: *xbp->wptr++ = *sp; ! 322: putq(q, xbp); ! 323: if ((kdp->ostate&KMBUSY) == 0) ! 324: kmstart(kdp); ! 325: } ! 326: break; ! 327: ! 328: case DIOCRCTL: ! 329: *sp = kdp->lastctl; ! 330: kdp->lastctl = 0; ! 331: bp->wptr = (unsigned char *)sp + 1; ! 332: break; ! 333: ! 334: case DIOCNXCL: ! 335: kdp->ostate &= ~KMXCL; ! 336: bp->wptr = bp->rptr; ! 337: break; ! 338: ! 339: case TIOCGDEV: ! 340: ((struct ttydevb *)sp)->ispeed = ! 341: ((struct ttydevb *)sp)->ospeed = B9600; ! 342: break; ! 343: ! 344: case KIOCINIT: ! 345: kdixinit(kdp); ! 346: bp->rptr = bp->wptr; ! 347: break; ! 348: ! 349: case KIOCSHUT: ! 350: if (kdp->chan > 2) { /* hackish security attempt */ ! 351: bp->type = M_IOCNAK; ! 352: break; ! 353: } ! 354: kdireset(kdp->kno); ! 355: bp->rptr = bp->wptr; ! 356: break; ! 357: ! 358: case DIOCSTREAM: ! 359: RD(q)->flag &= ~QDELIM; ! 360: bp->rptr = bp->wptr; ! 361: break; ! 362: ! 363: case DIOCRECORD: ! 364: RD(q)->flag |= QDELIM; ! 365: bp->rptr = bp->wptr; ! 366: break; ! 367: ! 368: case DIOCXWIN: { ! 369: unsigned int wins; ! 370: /* KMC does big (756) or small (84) windows currently */ ! 371: wins = (sp[0] + (sp[1]<<8))*sp[4]; ! 372: kdp->ostate &= ~KMXBIG; ! 373: if (wins>=756) ! 374: kdp->ostate |= KMXBIG; ! 375: /* will take effect next XINIT */ ! 376: bp->rptr = bp->wptr; ! 377: break; ! 378: } ! 379: ! 380: default: ! 381: bp->wptr = bp->rptr; ! 382: bp->type = M_IOCNAK; ! 383: break; ! 384: } ! 385: qreply(q, bp); ! 386: return; ! 387: ! 388: case M_STOP: ! 389: s = OSPND; ! 390: kdp->ostate |= KMSTOP; ! 391: goto dontcmd; ! 392: ! 393: case M_FLUSH: ! 394: flushq(q, 0); ! 395: s = spl6(); ! 396: if (kdp->obp) { ! 397: freeb(kdp->obp); /* this cannot be right -- too early */ ! 398: kdp->obp = 0; ! 399: } ! 400: kdp->ostate &= ~(KMSTOP|KMBUSY); ! 401: splx(s); ! 402: s = OFLUSH|ORSME; ! 403: goto docmd; ! 404: ! 405: case M_START: ! 406: case M_HANGUP: ! 407: s = ORSME; ! 408: kdp->ostate &= ~KMSTOP; ! 409: goto dontcmd; ! 410: docmd: ! 411: kcmd(kdp->kno, KC_CMD, kdp->chan, 0, s, 0, (uaddr_t)NULL); ! 412: dontcmd: ! 413: kmstart(kdp); ! 414: break; ! 415: ! 416: default: /* not handled; just toss */ ! 417: break; ! 418: } ! 419: freeb(bp); ! 420: } ! 421: ! 422: /* ! 423: * restart URP on some channel: ! 424: * send XINIT to KMC; ! 425: * discard any pending transmit block ! 426: * ! 427: * should pending block really be discarded, or requeued? ! 428: * former seems to match real cases ! 429: */ ! 430: ! 431: kdixinit(kp) ! 432: register struct kdi *kp; ! 433: { ! 434: register int s; ! 435: ! 436: s = spl6(); ! 437: kcmd(kp->kno, KC_XINIT, kp->chan, 0, 0, (kp->ostate&KMXBIG)!=0, (uaddr_t)NULL); ! 438: if (kp->obp) { ! 439: freeb(kp->obp); ! 440: kp->obp = NULL; ! 441: } ! 442: if (kp->omap) { ! 443: ubmfree(kdikmc[kp->kno].ubno, kp->omap); ! 444: kp->omap = 0; ! 445: } ! 446: kp->ostate &=~ (KMSTOP|KMBUSY); ! 447: splx(s); ! 448: } ! 449: ! 450: kdiisrv(q) ! 451: register struct queue *q; ! 452: { ! 453: register struct kdi *kp = (struct kdi *)q->ptr; ! 454: register int ubno; ! 455: register struct block *bp; ! 456: ! 457: if ((q->next->flag&QFULL)==0 && kp->ibp==NULL) { ! 458: bp = allocb(kp->ostate&KMBIG? 1024:64); ! 459: if (bp == NULL) ! 460: panic("kdi: can't alloc"); ! 461: kp->ibp = bp; ! 462: ubno = kdikmc[kp->kno].ubno; ! 463: kp->imap = ubmblk(ubno, bp, 0); ! 464: kcmd(kp->kno, KC_RCVB, kp->chan, bp->lim - bp->wptr, ! 465: 50, CBLOCK|CTIME, ubadwptr(ubno, bp, kp->imap)); ! 466: } ! 467: } ! 468: ! 469: kmstart(kdp) ! 470: register struct kdi *kdp; ! 471: { ! 472: register s = spl5(); ! 473: register struct block *bp; ! 474: register struct queue *qp; ! 475: register c; ! 476: register struct kdikmc *xp; ! 477: ! 478: if (kdp->ostate&(KMBUSY|KMSTOP)) { ! 479: splx(s); ! 480: return; ! 481: } ! 482: if ((qp = kdp->dkrq)==NULL || (qp = WR(qp))==NULL) { ! 483: splx(s); ! 484: return; ! 485: } ! 486: xp = &kdikmc[kdp->kno]; ! 487: if (bp = getq(qp)) switch (bp->type) { ! 488: ! 489: case M_DATA: ! 490: c = OBOTM; ! 491: if (bp->class&S_DELIM) ! 492: c = 0; ! 493: kdp->omap = ubmblk(xp->ubno, bp, 0); ! 494: kcmd(kdp->kno, KC_SEND, kdp->chan, bp->wptr-bp->rptr, ! 495: 0, c, ubadrptr(xp->ubno, bp, kdp->omap)); ! 496: kdp->ostate |= KMBUSY; ! 497: dkstat.output += bp->wptr - bp->rptr; ! 498: kdp->obp = bp; ! 499: break; ! 500: ! 501: case M_DELAY: ! 502: c = D_DELAY; ! 503: while (*bp->rptr>0) { ! 504: c++; ! 505: *bp->rptr >>= 1; ! 506: } ! 507: kdp->omap = ubmblk(xp->ubno, bp, 0); ! 508: kcmd(kdp->kno, KC_SEND, kdp->chan, 1, c, 0, ubadrptr(xp->ubno, bp, kdp->omap)); ! 509: kdp->ostate |= KMBUSY; ! 510: kdp->obp = bp; ! 511: break; ! 512: ! 513: case M_CTL: ! 514: kdp->omap = ubmblk(xp->ubno, bp, 0); ! 515: kcmd(kdp->kno, KC_SEND, kdp->chan, 0, *bp->rptr, 0, ubadrptr(xp->ubno, bp, kdp->omap)); ! 516: kdp->ostate |= KMBUSY; ! 517: kdp->obp = bp; ! 518: break; ! 519: ! 520: case M_BREAK: ! 521: kdp->omap = ubmblk(xp->ubno, bp, 0); ! 522: kcmd(kdp->kno, KC_SEND, kdp->chan, 0, D_BREAK, 0, ubadrptr(xp->ubno, bp, kdp->omap)); ! 523: kdp->ostate |= KMBUSY; ! 524: kdp->obp = bp; ! 525: break; ! 526: ! 527: default: ! 528: printf("mesg %o in kdi\n", bp->type); ! 529: freeb(bp); ! 530: break; ! 531: } ! 532: splx(s); ! 533: } ! 534: ! 535: int kcmdovern[10]; ! 536: long kcmdovert[10]; ! 537: ! 538: kcmd(kno, type, chan, len, ctl, mode, addr) ! 539: uaddr_t addr; ! 540: { ! 541: register i; ! 542: register struct device *dp = kmc[kno].k_addr; ! 543: register struct kin *kp; ! 544: register s; ! 545: static struct kmaddr nulladr = {0, 0}; ! 546: static serno; ! 547: register long loop; ! 548: ! 549: /* ! 550: * if the kmc is dead, don't ask it to do things ! 551: */ ! 552: if(dp->sts ==3) ! 553: return; ! 554: ! 555: if (dp->u.q.x3) ! 556: dp->u.q.x3 = 0; ! 557: busywait: ! 558: /* ! 559: * wait at low priority till there's a free command. No ! 560: * sense slowing all processes down. ! 561: */ ! 562: if(((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) { ! 563: loop = 0; ! 564: while (((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) { ! 565: if (loop == 1000) ! 566: printf("waiting for kdi%d\n", kno); ! 567: if(loop++>1000000) { ! 568: printf("kmc%d died, restart\n", kno); ! 569: kdireset(kno); ! 570: return; ! 571: } ! 572: } ! 573: kcmdovern[kno]++; ! 574: if(kcmdovert[kno]<loop) ! 575: kcmdovert[kno] = loop; ! 576: } ! 577: s = spl5(); ! 578: /* ! 579: * someone else might have gotten in at low priority. check ! 580: * again. ! 581: */ ! 582: if(((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) { ! 583: splx(s); ! 584: goto busywait; ! 585: } ! 586: i = dp->u.q.ch; ! 587: if (i >= NKMB) ! 588: panic("kcmd"); ! 589: kp = &k[kno].cmd[i]; ! 590: kp->type = type; ! 591: kp->serno = ++serno; ! 592: kp->chan = chan; ! 593: kp->len = len; ! 594: kp->ctl = ctl; ! 595: kp->mode = mode; ! 596: kp->addr.hi = addr>>16; ! 597: kp->addr.lo = addr; ! 598: i++; ! 599: if (i >= NKMB) ! 600: i = 0; ! 601: dp->u.q.ch = i; ! 602: TRACE(*kp); ! 603: splx(s); ! 604: } ! 605: ! 606: u_char kdiseqno[10]; ! 607: ! 608: /* ! 609: * Interrupt routine-- unload status buffer: ! 610: * release write blocks, collect input ! 611: */ ! 612: kdiintr(kno) ! 613: { ! 614: register struct device *dp = kmc[kno].k_addr; ! 615: register struct kin *sp; ! 616: register struct kdi *kp; ! 617: register struct block *bp; ! 618: register c; ! 619: register struct kdikmc *xp; ! 620: ! 621: xp = &kdikmc[kno]; ! 622: if (dp->u.q.x3) ! 623: dp->u.q.x3 = 0; ! 624: for ( ; (c = dp->u.q.st) != dp->u.q.sh; dp->u.q.st = c) { ! 625: if (c >= NKMB) { ! 626: printf("kdi stat buf is %d\n", c); ! 627: panic("kdiintr"); ! 628: } ! 629: sp = &k[kno].stat[c]; ! 630: TRACE(*sp); ! 631: c++; ! 632: if (c >= NKMB) ! 633: c = 0; ! 634: if (sp->chan >= KDICHAN) { ! 635: printf("kdi%d stat chan is 0%o\n", kno, sp->chan); ! 636: printf("type: %o len: 0%o mode: 0%o\n"); ! 637: continue; ! 638: } ! 639: if(sp->serno!=kdiseqno[kno]){ ! 640: printf("kdi%d stat chan is 0%o\n", kno, sp->chan); ! 641: printf("seqno is %d, should be %d\n",sp->serno, ! 642: kdiseqno[kno]); ! 643: } ! 644: kdiseqno[kno]=(sp->serno+1)%256; ! 645: kp = &xp->kdi[sp->chan]; ! 646: switch (sp->type) { ! 647: ! 648: case KS_SEND: ! 649: if (kp->obp) { ! 650: freeb(kp->obp); ! 651: kp->obp = NULL; ! 652: } ! 653: kp->ostate &= ~KMBUSY; ! 654: if (kp->omap) { ! 655: ubmfree(xp->ubno, kp->omap); ! 656: kp->omap = 0; ! 657: } ! 658: if (kp->dkrq && WR(kp->dkrq)->first) ! 659: kmstart(kp); ! 660: break; ! 661: ! 662: case KS_RDB: ! 663: if (kp->imap) { ! 664: ubmfree(xp->ubno, kp->imap); ! 665: kp->imap = 0; ! 666: } ! 667: bp = kp->ibp; ! 668: kp->ibp = NULL; ! 669: if (kp->dkrq==NULL || xp->state[kp->chan]!=DKOPEN) { ! 670: if (bp) ! 671: freeb(bp); ! 672: break; ! 673: } ! 674: if (sp->mode & SABORT) { ! 675: printf("kdi%d rcv abort chan %d mode %o bp %x\n", ! 676: kno, kp->chan, sp->mode, bp); ! 677: if (bp) ! 678: kp->ibp = bp; ! 679: kp->rsize = 0; ! 680: kp->ostate &= ~KMBIG; ! 681: break; ! 682: } ! 683: if (bp == NULL) { ! 684: printf("kdi%d: no ibp\n", kno); ! 685: break; ! 686: } ! 687: /* special hacks */ ! 688: if (sp->mode&020 ! 689: || sp->mode==0100 && bp->wptr+sp->len==bp->lim) { ! 690: /* ! 691: * Something no one understands. Print out ! 692: * some info so that we might figure out ! 693: * why this freeb is in the code. ! 694: */ ! 695: printf("kdi%d rcv chan %d mode %o bp %x len %d\n", ! 696: kno, kp->chan, sp->mode, bp, sp->len); ! 697: freeb(bp); ! 698: } else { ! 699: bp->wptr = bp->lim - sp->len; ! 700: kp->rsize += bp->wptr - bp->rptr; ! 701: dkstat.input += bp->wptr - bp->rptr; ! 702: if(sp->mode&(SBLOCK|STIME)) { ! 703: bp->class |= S_DELIM; ! 704: if (kp->rsize >= 512) ! 705: kp->ostate = BIGSET(kp->ostate); ! 706: else ! 707: kp->ostate = BIGCLR(kp->ostate); ! 708: kp->rsize = 0; ! 709: } ! 710: (*kp->dkrq->next->qinfo->putp) ! 711: (kp->dkrq->next, bp); ! 712: kp->ibp = NULL; ! 713: if (sp->mode&SCNTL) { ! 714: switch (sp->ctl) { ! 715: ! 716: case D_BREAK: ! 717: putctl(kp->dkrq->next, M_BREAK); ! 718: break; ! 719: ! 720: default: ! 721: kp->lastctl = sp->ctl; ! 722: putctl1(kp->dkrq->next, M_CTL, sp->ctl); ! 723: break; ! 724: ! 725: } ! 726: } ! 727: } ! 728: if ((kp->dkrq->next->flag&QFULL) == 0) { ! 729: bp = allocb(kp->ostate&KMBIG? 1024:64); ! 730: if (bp == NULL) ! 731: panic("kdi: can't alloc"); ! 732: kp->ibp = bp; ! 733: kp->imap = ubmblk(xp->ubno, bp, 0); ! 734: kcmd(kno, KC_RCVB, kp->chan, bp->lim - bp->wptr, ! 735: 50, CBLOCK|CTIME, ubadwptr(xp->ubno, bp, kp->imap)); ! 736: } ! 737: break; ! 738: ! 739: case KS_EOI: ! 740: printf("kdi%d chan %d rcv EOI %x\n", kno, sp->chan, sp->len); ! 741: break; ! 742: ! 743: case KS_CNTL: ! 744: /* ! 745: printf("kdi%d chan %d rcv ctl %x\n", kno, sp->chan, sp->len); ! 746: */ ! 747: break; ! 748: ! 749: case KS_ERR: ! 750: printf("kdi%d chan %d error %d\n", kno, sp->chan, sp->len); ! 751: if (sp->len==E_NOQB || sp->len==E_UMETA ! 752: || sp->len==E_DUP) { ! 753: printf("ignored\n"); ! 754: break; ! 755: } ! 756: kdireset(kno); ! 757: break; ! 758: ! 759: } ! 760: } ! 761: } ! 762: ! 763: /* ! 764: * init things, including data structures ! 765: * -- assume KDICHAN struct kdis and KDICHAN chars for state ! 766: * will fit in a buffer. when BSIZE is 4096, it's true. ! 767: */ ! 768: int kdireload(); ! 769: ! 770: kdiinit(dev) ! 771: int dev; ! 772: { ! 773: register struct device *kp; ! 774: register i; ! 775: register struct kdikmc *xp; ! 776: register int kno; ! 777: struct kmaddr ka; ! 778: extern time_t time; ! 779: ! 780: kno = KMC(minor(dev)); ! 781: /* close all open channels? */ ! 782: if ((kp = kmc[kno].k_addr) == NULL) ! 783: return (0); ! 784: xp = &kdikmc[kno]; ! 785: if (xp->badtime+30 > time) /* UGH */ ! 786: return(0); ! 787: kp->sts = 0; /* initialize KMC */ ! 788: if (xp->buf == NULL) { ! 789: if ((xp->buf = geteblk()) == NULL) ! 790: return (0); ! 791: clrbuf(xp->buf); ! 792: xp->kdi = (struct kdi *)xp->buf->b_un.b_addr; ! 793: xp->state = (char *)&xp->kdi[KDICHAN]; ! 794: for (i = 0; i < KDICHAN; i++) { ! 795: xp->kdi[i].chan = i; ! 796: xp->kdi[i].kno = kno; ! 797: } ! 798: } ! 799: if ((xp->modp = dkmodall(dev, kno*KDICHAN, (kno+1)*KDICHAN)) == 0) ! 800: return (0); ! 801: xp->modp->dkstate = xp->state; ! 802: xp->ubno = kmcaddr[kno].ubno; ! 803: if (xp->umap == 0) { ! 804: if ((xp->umap = ubmalloc(xp->ubno, sizeof(struct kmcdk), 0)) == 0) { ! 805: printf("kdi%d: no map\n", kno); ! 806: return (0); ! 807: } ! 808: } ! 809: xp->ubad = ubmaddr(xp->ubno, (caddr_t)&k[kno], sizeof(struct kmcdk), xp->umap); ! 810: k[kno].kinit.cmdaddr = kmcubaddr((caddr_t)k[kno].cmd, (caddr_t)&k[kno], xp->ubad); ! 811: k[kno].kinit.stataddr = kmcubaddr((caddr_t)k[kno].stat, (caddr_t)&k[kno], xp->ubad); ! 812: k[kno].kinit.bufaddr = kmcubaddr((caddr_t)k[kno].kmcbuf, (caddr_t)&k[kno], xp->ubad); ! 813: ka = kmcubaddr((caddr_t)&k[kno].kinit, (caddr_t)&k[kno], xp->ubad); ! 814: kp->u.a.lo = ka.lo; ! 815: kp->u.a.hi = ka.hi; ! 816: xp->badtime = time; ! 817: kp->sts = 1; /* start handshake */ ! 818: for (i = 0; i<100000; i++) { ! 819: if (kp->sts == 2) { ! 820: kmc[kno].k_rint = kdiintr; ! 821: kmc[kno].k_xint = kdiintr; ! 822: kmc[kno].k_reset = kdireload; ! 823: xp->init = 1; ! 824: return(1); /* KMC is running OK */ ! 825: } ! 826: if (kp->sts == 3) { ! 827: printf("kdi%d: entered state 3\n", kno); ! 828: return(0); ! 829: } ! 830: } ! 831: printf("kdi%d: kmc not ready\n", kno); ! 832: return(0); ! 833: } ! 834: ! 835: struct kmaddr ! 836: kmcubaddr(memaddr, membase, ubbase) ! 837: caddr_t memaddr, membase; ! 838: uaddr_t ubbase; ! 839: { ! 840: register struct kmaddr r; ! 841: register long a; ! 842: ! 843: a = (long)memaddr - (long)membase + (long)ubbase; ! 844: r.hi = a >> 16; ! 845: r.lo = (u_short)a; ! 846: return(r); ! 847: } ! 848: ! 849: /* ! 850: * kmc reload ! 851: */ ! 852: kdireload(kno) ! 853: { ! 854: register struct kdikmc *xp; ! 855: ! 856: xp = &kdikmc[kno]; ! 857: xp->init = 0; ! 858: xp->modp = 0; ! 859: xp->bad = 0; ! 860: } ! 861: ! 862: /* ! 863: * zap all open channels ! 864: */ ! 865: kdireset(kno) ! 866: { ! 867: register struct kdi *kp; ! 868: register struct kdikmc *xp; ! 869: register struct device *dp; ! 870: ! 871: xp = &kdikmc[kno]; ! 872: if (xp->modp==0) ! 873: return; ! 874: if ((dp = kmc[kno].k_addr) != NULL) ! 875: dp->sts = 3; /* disable kdi kmc code */ ! 876: for (kp = &xp->kdi[KDICHAN-1]; kp >= xp->kdi; --kp) { ! 877: register state = xp->state[kp->chan]; ! 878: if ((state==DKOPEN || state==DKLCLOSE) && kp->dkrq) { ! 879: flushq(WR(kp->dkrq), 1); ! 880: xp->state[kp->chan] = state==DKOPEN? DKRCLOSE: DKCLOSED; ! 881: putctl(kp->dkrq->next, M_HANGUP); ! 882: } ! 883: if (kp->imap) ! 884: ubmfree(xp->ubno, kp->imap); ! 885: if (kp->omap) ! 886: ubmfree(xp->ubno, kp->omap); ! 887: kp->imap = kp->omap = 0; ! 888: } ! 889: xp->bad = 1; ! 890: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.