1*38624Skarels /* 2*38624Skarels * Datakit driver 3*38624Skarels * DR11C version without KMC 4*38624Skarels * 5*38624Skarels * uses mbufs for transmission 6*38624Skarels * 7*38624Skarels * SCCSID[] = "@(#)dkit_dr.c 1.5 Garage 84/04/11" 8*38624Skarels */ 9*38624Skarels 10*38624Skarels #include "dkitdr.h" 11*38624Skarels #if NDKITDR>0 12*38624Skarels #include "datakit.h" 13*38624Skarels 14*38624Skarels #include "../machine/pte.h" 15*38624Skarels #include "param.h" 16*38624Skarels #include "time.h" 17*38624Skarels #include "kernel.h" 18*38624Skarels #include "buf.h" 19*38624Skarels #include "mbuf.h" 20*38624Skarels #include "errno.h" 21*38624Skarels #include "socket.h" 22*38624Skarels #include "syslog.h" 23*38624Skarels #include "../net/if.h" 24*38624Skarels #include "../vaxuba/ubareg.h" 25*38624Skarels #include "../vaxuba/ubavar.h" 26*38624Skarels 27*38624Skarels #include "dk.h" 28*38624Skarels #include "dkit.h" 29*38624Skarels #include "dkdr.h" 30*38624Skarels 31*38624Skarels 32*38624Skarels #define PKBHOG 64 /* max temp buffers per channel */ 33*38624Skarels #define DKNPKB (200+4*NDATAKIT) 34*38624Skarels #define DKNSTB 10 35*38624Skarels 36*38624Skarels struct dkchan dkit[NDATAKIT]; 37*38624Skarels extern int dk_nchan; 38*38624Skarels 39*38624Skarels int dkdr_npk = DKNPKB; 40*38624Skarels struct dkpkbufr dk_pkbuf[DKNPKB]; 41*38624Skarels 42*38624Skarels int dkdr_nstat = DKNSTB; 43*38624Skarels struct dkstat dkdr_stat[DKNSTB]; 44*38624Skarels 45*38624Skarels int dkattached = 0; /* Is it really there? */ 46*38624Skarels 47*38624Skarels #ifdef KALYPSO 48*38624Skarels #define URPDEBUG 5000 49*38624Skarels #else 50*38624Skarels #define URPDEBUG 500 51*38624Skarels #endif 52*38624Skarels 53*38624Skarels #ifdef URPDEBUG 54*38624Skarels int dkurpdebug = 0; 55*38624Skarels #define URPTRACE(chan, chr, Dkp) if (dkurpdebug == (chan)) \ 56*38624Skarels dkurptrace(chr, Dkp); 57*38624Skarels #endif 58*38624Skarels 59*38624Skarels /* 60*38624Skarels * structure of data in first mbuf on chain (type DKM_HDR) 61*38624Skarels * 62*38624Skarels */ 63*38624Skarels struct mpacket { 64*38624Skarels short mp_len; /* Total length left */ 65*38624Skarels char mp_ctl; /* Control character */ 66*38624Skarels int mp_eob; /* Send end-of-block indicator */ 67*38624Skarels int (*mp_endfcn)(); /* End-action function */ 68*38624Skarels caddr_t mp_endparm; /* Parameter to above function */ 69*38624Skarels }; 70*38624Skarels 71*38624Skarels /* 72*38624Skarels * dr11-c bit definitions 73*38624Skarels */ 74*38624Skarels #define DKTENAB 0100 /* transmit interrupt enable */ 75*38624Skarels #define DKRENAB 040 /* receiver interrupt enable */ 76*38624Skarels #define ENABS 0140 /* both enables */ 77*38624Skarels #define DKCOM 03 /* dr11-c command bits */ 78*38624Skarels #define DKTDONE 0200 /* transmit done bit */ 79*38624Skarels #define DKRDONE 0100000 /* receiver done bit */ 80*38624Skarels #define DKMARK 01000 /* start of packet bit */ 81*38624Skarels #define DKOVF 040000 /* receiver overflow bit (in drin) */ 82*38624Skarels #define DKDATA 0400 /* bit 9 ... indicates non-control */ 83*38624Skarels 84*38624Skarels #define DKCHUNK 16 /* packet size */ 85*38624Skarels 86*38624Skarels /* 87*38624Skarels * dr11c commands 88*38624Skarels */ 89*38624Skarels #define D_OSEQ 0 90*38624Skarels #define D_READ 1 91*38624Skarels #define D_WRITE 2 92*38624Skarels #define D_XPACK 3 93*38624Skarels 94*38624Skarels /* 95*38624Skarels * error control protocol definitions 96*38624Skarels */ 97*38624Skarels #define SEQ 0010 /* 8 sequence numbers to end trailers */ 98*38624Skarels #define ECHO 0020 /* 8 echoes, data given to host */ 99*38624Skarels #define REJ 0030 /* 8 rejections, transmission error */ 100*38624Skarels #define ACK 0040 /* first of 8 acks, correct reception */ 101*38624Skarels #define BOT 0050 /* normal beginning of trailer */ 102*38624Skarels #define BOTM 0051 /* trailer with more data to follow */ 103*38624Skarels #define BOTS 0052 /* seq update algorithm on this trailer */ 104*38624Skarels #define SOI 0053 /* start of interrupt trailer */ 105*38624Skarels #define EOI 0054 /* end of interrupt trailer */ 106*38624Skarels #define ENQ 0055 /* xmitter request flow/error status */ 107*38624Skarels #define CHECK 0056 /* xmitter request error status */ 108*38624Skarels #define INITREQ 0057 /* request initialization */ 109*38624Skarels #define INIT0 0060 /* disable trailer processing */ 110*38624Skarels #define INIT1 0061 /* enable trailer processing */ 111*38624Skarels #define AINIT 0062 /* response to INIT0/INIT1 */ 112*38624Skarels 113*38624Skarels #define DKBMASK 03 /* this xmitter has window size of 4, */ 114*38624Skarels /* #define DKBLOCK 60 /* each message is 60 bytes */ 115*38624Skarels #define DKBLOCK 28 /* each message is 60 bytes */ 116*38624Skarels 117*38624Skarels 118*38624Skarels /* 119*38624Skarels * some commonly used macros 120*38624Skarels */ 121*38624Skarels 122*38624Skarels 123*38624Skarels 124*38624Skarels struct dkpkbufr *dk_Sfree; 125*38624Skarels extern int dkdr_npk; 126*38624Skarels extern struct dkpkbufr dk_pkbuf[]; 127*38624Skarels 128*38624Skarels int dknopkb = 1 ; /* Counter for 'no dkpkbufr' condition. */ 129*38624Skarels int dkstray; /* number of stray interrupts since last timeout */ 130*38624Skarels int dkdrlostint; /* Number of lost receiver interrupts */ 131*38624Skarels int dkdisabled; /* flag to indicate that DK interface has been disabled 132*38624Skarels due to stray interrupts, etc. */ 133*38624Skarels #define MAX_STRAY 10 /* maximum number of stray interrupts 134*38624Skarels before temporarily disabling DK interrupts */ 135*38624Skarels 136*38624Skarels /* 137*38624Skarels * dr11c device registers 138*38624Skarels */ 139*38624Skarels struct rdevice { 140*38624Skarels short dkcsr; 141*38624Skarels short dko; 142*38624Skarels short dki; 143*38624Skarels }; 144*38624Skarels 145*38624Skarels extern int dkdr_nstat; 146*38624Skarels extern struct dkstat dkdr_stat[]; 147*38624Skarels 148*38624Skarels static char Hstat, Tstat; 149*38624Skarels 150*38624Skarels #define DKADDR ((struct rdevice *) dkitdrdinfo[0]->ui_addr) 151*38624Skarels 152*38624Skarels 153*38624Skarels /* 154*38624Skarels * Intermediate level command codes 155*38624Skarels */ 156*38624Skarels #define KS_SEND 20 157*38624Skarels #define KS_RDB 21 158*38624Skarels #define KS_EOI 22 159*38624Skarels #define KS_CNTL 23 160*38624Skarels #define KS_ERR 24 161*38624Skarels 162*38624Skarels 163*38624Skarels 164*38624Skarels int dkdebug = 512 ; 165*38624Skarels int dkactive ; 166*38624Skarels 167*38624Skarels static int timeron; 168*38624Skarels 169*38624Skarels 170*38624Skarels int dkitdrprobe(), dkitdrattach(); 171*38624Skarels struct uba_device *dkitdrdinfo[1]; 172*38624Skarels u_short dkitdrstd[] = { 0 }; 173*38624Skarels struct uba_driver dkitdrdriver = 174*38624Skarels { dkitdrprobe, 0, dkitdrattach, 0, dkitdrstd, "dkitdr", dkitdrdinfo }; 175*38624Skarels 176*38624Skarels dkitdrprobe(reg) 177*38624Skarels caddr_t reg; 178*38624Skarels { 179*38624Skarels register int br, cvec; /* value-result */ 180*38624Skarels register struct rdevice *draddr = (struct rdevice *) reg; 181*38624Skarels register int i, c; 182*38624Skarels 183*38624Skarels #ifdef lint 184*38624Skarels br = 0; cvec = br; br = cvec; 185*38624Skarels dkdrrint(0); dkdrxint(0); 186*38624Skarels #endif 187*38624Skarels draddr->dkcsr = D_READ; 188*38624Skarels for (i = 0; i < 1024; i++) 189*38624Skarels if (draddr->dkcsr & DKRDONE) c = draddr->dki; 190*38624Skarels else break; 191*38624Skarels #ifdef lint 192*38624Skarels c = c; 193*38624Skarels #endif 194*38624Skarels draddr->dkcsr = D_WRITE; 195*38624Skarels draddr->dko = DKMARK | (dk_nchan-1); /* pack on 511 */ 196*38624Skarels draddr->dkcsr = D_XPACK + DKTENAB; 197*38624Skarels draddr->dko = 0; 198*38624Skarels DELAY(10000); 199*38624Skarels draddr->dkcsr = 0; 200*38624Skarels return(sizeof(struct rdevice)); 201*38624Skarels } 202*38624Skarels 203*38624Skarels /*ARGSUSED*/ 204*38624Skarels dkitdrattach(ui) 205*38624Skarels struct uba_device *ui; 206*38624Skarels { 207*38624Skarels dkattached = 1; 208*38624Skarels 209*38624Skarels #if defined(INET) && NDKI>0 210*38624Skarels dkiattach(); 211*38624Skarels #endif 212*38624Skarels } 213*38624Skarels 214*38624Skarels 215*38624Skarels static 216*38624Skarels dk_init() 217*38624Skarels { 218*38624Skarels register struct rdevice *raddr = DKADDR; 219*38624Skarels register s ; 220*38624Skarels /* 221*38624Skarels * At attach time for the hardware device 222*38624Skarels * initialize and check things out to the 223*38624Skarels * (grumble) limited extent that is possible. 224*38624Skarels */ 225*38624Skarels 226*38624Skarels s = spl5() ; 227*38624Skarels Hstat = Tstat = 0 ; 228*38624Skarels dkdisabled = 0; 229*38624Skarels dkstray = 0; 230*38624Skarels { 231*38624Skarels register struct dkchan *dkp ; 232*38624Skarels 233*38624Skarels for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) { 234*38624Skarels dkp->dk_rlen = 0 ; 235*38624Skarels dkp->dk_xlen = 0 ; 236*38624Skarels dkp->dk_X = XM_OFF; 237*38624Skarels dkp->dk_rq = NULL ; 238*38624Skarels dkp->dk_outq.ifq_len = 0; 239*38624Skarels dkp->dk_outq.ifq_maxlen = 20; 240*38624Skarels dkp->dk_outq.ifq_drops = 0; 241*38624Skarels dkp->dk_outq.ifq_head = NULL; 242*38624Skarels dkp->dk_outq.ifq_tail = NULL; 243*38624Skarels } 244*38624Skarels } { register struct dkpkbufr *pkb ; 245*38624Skarels 246*38624Skarels for (pkb = &dk_pkbuf[1]; pkb < &dk_pkbuf[dkdr_npk-1]; pkb++) { 247*38624Skarels pkb->Pnext = pkb + 1 ; 248*38624Skarels } 249*38624Skarels dk_pkbuf[dkdr_npk-1].Pnext = NULL ; 250*38624Skarels dk_Sfree = &dk_pkbuf[1] ; 251*38624Skarels dk_pkbuf[0].Pnext = NULL ; 252*38624Skarels } { 253*38624Skarels register int seq, i, c ; 254*38624Skarels 255*38624Skarels raddr->dkcsr = D_OSEQ ; 256*38624Skarels raddr->dko = 0 ; /* clears all FIFO's */ 257*38624Skarels seq = 0 ; 258*38624Skarels while (raddr->dkcsr & DKTDONE) { 259*38624Skarels seq += (((raddr->dki)>>10) & 017) + 2 ; 260*38624Skarels if (seq > 100) { 261*38624Skarels dkreport(KS_ERR, 0, 1, 0, 1) ; 262*38624Skarels splx(s) ; 263*38624Skarels return -EIO ; 264*38624Skarels } 265*38624Skarels } 266*38624Skarels raddr->dkcsr = D_READ; 267*38624Skarels for (i = 0; i < 1024; i++) 268*38624Skarels if (raddr->dkcsr & DKRDONE) c = raddr->dki; 269*38624Skarels else break; 270*38624Skarels #ifdef lint 271*38624Skarels c = c; 272*38624Skarels #endif 273*38624Skarels } 274*38624Skarels raddr->dkcsr = ENABS ; 275*38624Skarels if(!timeron){ 276*38624Skarels dk_timeout(); 277*38624Skarels timeron++; 278*38624Skarels } 279*38624Skarels 280*38624Skarels splx(s) ; 281*38624Skarels dkactive = 1 ; 282*38624Skarels 283*38624Skarels 284*38624Skarels return 0 ; 285*38624Skarels } 286*38624Skarels 287*38624Skarels /*ARGSUSED*/ 288*38624Skarels dkitreset(uban) 289*38624Skarels int uban; 290*38624Skarels { 291*38624Skarels register struct rdevice *raddr ; 292*38624Skarels 293*38624Skarels raddr = DKADDR; 294*38624Skarels raddr->dkcsr = ENABS; 295*38624Skarels log(LOG_ERR, " dkit_dr%d", 0); 296*38624Skarels } 297*38624Skarels 298*38624Skarels dk_open(chan, supfcn) 299*38624Skarels register chan ; 300*38624Skarels int (*supfcn)() ; 301*38624Skarels { 302*38624Skarels register struct dkchan *dkp; 303*38624Skarels register s ; 304*38624Skarels extern dkkint() ; 305*38624Skarels static firsttime = 1; 306*38624Skarels static init; 307*38624Skarels extern int commchan; 308*38624Skarels 309*38624Skarels if (chan >= dk_nchan || !dkattached) 310*38624Skarels return -ENXIO ; 311*38624Skarels if (firsttime) { 312*38624Skarels if ((init = dk_init()) < 0) return init; 313*38624Skarels firsttime = 0; 314*38624Skarels } 315*38624Skarels dkp = &dkit[chan] ; 316*38624Skarels s = spl5() ; 317*38624Skarels /* 318*38624Skarels * Channel 0 (0-3 in ISN) is reserved for maintenance. 319*38624Skarels * An open on channel 0 is interpreted as a request 320*38624Skarels * for an unused channel. Channel 1 (4 in ISN or RADIAN) 321*38624Skarels * is the common supervisory channel. 322*38624Skarels */ 323*38624Skarels if (chan == 0) { 324*38624Skarels chan = commchan+1 ; /* Start above commchan */ 325*38624Skarels while (1) { 326*38624Skarels dkp = &dkit[chan] ; 327*38624Skarels if (dkp->dk_state == 0) 328*38624Skarels break ; 329*38624Skarels chan++ ; 330*38624Skarels if (chan >= dk_nchan) { 331*38624Skarels splx(s) ; 332*38624Skarels return -EADDRNOTAVAIL ; 333*38624Skarels } 334*38624Skarels } 335*38624Skarels } 336*38624Skarels 337*38624Skarels 338*38624Skarels /* 339*38624Skarels * Finish setting up dkp struct. 340*38624Skarels */ 341*38624Skarels if ((dkp->dk_state & DK_OPEN) ==0) { 342*38624Skarels if (chan > dkdebug) 343*38624Skarels log(LOG_ERR, "dkopen %d: %x\n", chan, supfcn) ; 344*38624Skarels dkp->dk_S = 1 ; 345*38624Skarels dkp->dk_R = 0 ; 346*38624Skarels dkp->dk_X = 0 ; 347*38624Skarels dkp->dk_A = 0 ; 348*38624Skarels dkp->dk_rejcnt = 0; 349*38624Skarels dkp->dk_srejcnt = 0; 350*38624Skarels dkp->dk_ackrejcnt = 0; 351*38624Skarels dkp->dk_enqcnt = 0; 352*38624Skarels dksend(chan, INIT1) ; 353*38624Skarels flushall(dkp, 0); 354*38624Skarels dkp->dk_state &= ~DK_LINGR ; 355*38624Skarels dkp->dk_state |= DK_OPEN; 356*38624Skarels } 357*38624Skarels dkp->dk_supfcn = supfcn ; 358*38624Skarels splx(s) ; 359*38624Skarels return chan ; 360*38624Skarels } 361*38624Skarels 362*38624Skarels 363*38624Skarels /* 364*38624Skarels * Close a channel: 365*38624Skarels */ 366*38624Skarels 367*38624Skarels dk_close(chan) 368*38624Skarels { 369*38624Skarels register struct dkchan *dkp; 370*38624Skarels register s ; 371*38624Skarels 372*38624Skarels s = spl5() ; 373*38624Skarels if (chan > dkdebug) 374*38624Skarels log(LOG_ERR, "dkclose %d\n", chan) ; 375*38624Skarels dkp = &dkit[chan] ; 376*38624Skarels if (chan == 0) { 377*38624Skarels if (!dkattached) return -ENXIO; 378*38624Skarels for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) { 379*38624Skarels if (dkp->dk_state & (DK_OPEN|DK_BUSY|DK_RCV)) { 380*38624Skarels dkp->dk_state |= DK_RESET ; 381*38624Skarels flushall(dkp, 0) ; 382*38624Skarels } 383*38624Skarels } 384*38624Skarels dkactive = 0 ; 385*38624Skarels splx(s); 386*38624Skarels return dk_init() ; 387*38624Skarels } else { 388*38624Skarels dkp->dk_state |= DK_OPEN ; 389*38624Skarels flushall(dkp, 0) ; 390*38624Skarels dkp->dk_state = DK_LINGR ; 391*38624Skarels dkp->dk_X = XM_OFF; 392*38624Skarels dkp->dk_trmode = 0 ; 393*38624Skarels } 394*38624Skarels splx(s) ; 395*38624Skarels return 0; 396*38624Skarels } 397*38624Skarels 398*38624Skarels /* 399*38624Skarels * Close phase 2 - mark available for reassignment 400*38624Skarels */ 401*38624Skarels dk_free(chan) 402*38624Skarels { 403*38624Skarels if (chan > dkdebug) 404*38624Skarels log(LOG_ERR, "dkfree %d\n", chan) ; 405*38624Skarels dkit[chan].dk_state &= ~DK_LINGR ; 406*38624Skarels } 407*38624Skarels 408*38624Skarels 409*38624Skarels /* 410*38624Skarels * Reset a channel 411*38624Skarels * prevents further I/O until close 412*38624Skarels */ 413*38624Skarels dk_reset(chan) 414*38624Skarels { 415*38624Skarels register struct dkchan *dkp ; 416*38624Skarels register s ; 417*38624Skarels 418*38624Skarels if (chan > dkdebug) 419*38624Skarels log(LOG_ERR, "dkreset %d\n", chan) ; 420*38624Skarels s = spl5() ; 421*38624Skarels dkp = &dkit[chan] ; 422*38624Skarels dkp->dk_state |= DK_RESET ; 423*38624Skarels flushall(dkp, 0) ; 424*38624Skarels splx(s) ; 425*38624Skarels } 426*38624Skarels 427*38624Skarels 428*38624Skarels 429*38624Skarels /* 430*38624Skarels * Xmit a short control (interrupt) packet 431*38624Skarels */ 432*38624Skarels dk_xint(chan, intr) 433*38624Skarels { 434*38624Skarels register struct rdevice *raddr ; 435*38624Skarels register s ; 436*38624Skarels register struct dkchan *dkp ; 437*38624Skarels 438*38624Skarels dkp = &dkit[chan] ; 439*38624Skarels if (chan == 0 || dkp->dk_X < XM_INIT) 440*38624Skarels return -1 ; 441*38624Skarels s = spl5() ; 442*38624Skarels if (chan > dkdebug) 443*38624Skarels log(LOG_ERR, "dkxint %d: %o %o\n", chan, (intr & 0377), ((intr >>8)&0377)) ; 444*38624Skarels raddr = DKADDR ; 445*38624Skarels raddr->dkcsr = D_WRITE ; 446*38624Skarels raddr->dko = chan | DKMARK ; 447*38624Skarels raddr->dko = SOI ; 448*38624Skarels raddr->dko = (intr & 0377) | DKDATA ; 449*38624Skarels raddr->dko = ((intr >> 8) & 0377) | DKDATA ; 450*38624Skarels raddr->dko = EOI ; 451*38624Skarels raddr->dkcsr = D_XPACK ; 452*38624Skarels raddr->dko = 0 ; 453*38624Skarels if(dkdisabled) 454*38624Skarels raddr->dko = 0; 455*38624Skarels else 456*38624Skarels raddr->dko = ENABS; 457*38624Skarels splx(s) ; 458*38624Skarels return 0 ; 459*38624Skarels } 460*38624Skarels 461*38624Skarels 462*38624Skarels /* 463*38624Skarels * Adjust window size 464*38624Skarels */ 465*38624Skarels dk_winsize(chan, win) 466*38624Skarels struct diocxwin win; 467*38624Skarels { 468*38624Skarels return EINVAL; /* For now... */ 469*38624Skarels } 470*38624Skarels 471*38624Skarels 472*38624Skarels /* 473*38624Skarels * Xmit data on a channel 474*38624Skarels * NOTE * * * * * 475*38624Skarels * Although it is never checked here, buffer addresses 476*38624Skarels * in this version of the driver must be kernel addressable. 477*38624Skarels */ 478*38624Skarels dk_xmit(chan, m, eob, ctlchar, endfcn, endparm) 479*38624Skarels struct mbuf *m ; 480*38624Skarels int (*endfcn)() ; 481*38624Skarels caddr_t endparm ; 482*38624Skarels { 483*38624Skarels register struct dkchan *dkp ; 484*38624Skarels register struct mpacket *mbp ; 485*38624Skarels register struct mbuf *mb; 486*38624Skarels int s ; 487*38624Skarels 488*38624Skarels s = spl5() ; 489*38624Skarels dkp = &dkit[chan] ; 490*38624Skarels if ((dkp->dk_state & DK_RESET) || (mb = m_get(M_DONTWAIT,DKMT_HDR)) == NULL) { 491*38624Skarels m_freem(m); 492*38624Skarels splx(s) ; 493*38624Skarels return 0 ; 494*38624Skarels } 495*38624Skarels 496*38624Skarels if (ctlchar == '\001') eob = 0; 497*38624Skarels mb->m_len = 0; 498*38624Skarels mbp = mtod(mb, struct mpacket *); 499*38624Skarels mbp->mp_endfcn = endfcn ; 500*38624Skarels mbp->mp_endparm = endparm ; 501*38624Skarels mbp->mp_eob = eob; 502*38624Skarels mb->m_next = m; 503*38624Skarels 504*38624Skarels mbp->mp_len = 0; 505*38624Skarels while (m) { 506*38624Skarels #ifdef notdef 507*38624Skarels if (m->m_type != DKMT_DATA && m->m_type != DKMT_CTL) { 508*38624Skarels log(LOG_ERR, "dk_xmit %d: got type %x\n", chan, m->m_type); 509*38624Skarels m_freem(mb); 510*38624Skarels return 0; 511*38624Skarels } 512*38624Skarels #endif 513*38624Skarels mbp->mp_len += m->m_len; 514*38624Skarels m = m->m_next; 515*38624Skarels } 516*38624Skarels 517*38624Skarels if ((ctlchar & 0300) == 0100) { 518*38624Skarels register struct mbuf *n = mb, *mc; 519*38624Skarels 520*38624Skarels mc = m_get(M_DONTWAIT, DKMT_CTL); 521*38624Skarels if (mc == NULL) { 522*38624Skarels m_freem(mb); 523*38624Skarels splx(s); 524*38624Skarels return 0; 525*38624Skarels } 526*38624Skarels *mtod(mc, char *) = ctlchar; 527*38624Skarels mc->m_len = 1; 528*38624Skarels 529*38624Skarels /* Append it -- can't use m_cat because type field counts */ 530*38624Skarels while (n->m_next) n = n->m_next; 531*38624Skarels n->m_next = mc; 532*38624Skarels mbp->mp_len++; 533*38624Skarels ctlchar = 0; 534*38624Skarels } 535*38624Skarels mbp->mp_ctl = ctlchar; 536*38624Skarels 537*38624Skarels if ((dkp->dk_state & DK_BUSY) == 0) { 538*38624Skarels dkp->dk_state |= DK_BUSY ; 539*38624Skarels dkp->dk_curout = mb; 540*38624Skarels dkp->dk_xlen = mbp->mp_len ; 541*38624Skarels if (chan > dkdebug) 542*38624Skarels log(LOG_ERR, "xmit %d: %x len %d\n", chan, 543*38624Skarels mb->m_next, mbp->mp_len) ; 544*38624Skarels dkxmit(dkp, chan, 2) ; 545*38624Skarels splx(s) ; 546*38624Skarels return dkp->dk_state ; 547*38624Skarels } 548*38624Skarels if (IF_QFULL(&dkp->dk_outq)) { 549*38624Skarels IF_DROP(&dkp->dk_outq); 550*38624Skarels m_freem(mb); 551*38624Skarels } 552*38624Skarels else 553*38624Skarels IF_ENQUEUE(&dkp->dk_outq, mb); 554*38624Skarels splx(s) ; 555*38624Skarels return dkp->dk_state ; 556*38624Skarels } 557*38624Skarels 558*38624Skarels /* 559*38624Skarels * Receive into a block buffer 560*38624Skarels */ 561*38624Skarels dk_recv(chan, addr, len, mode, endfcn, endparm) 562*38624Skarels caddr_t addr ; 563*38624Skarels int (*endfcn)() ; 564*38624Skarels caddr_t endparm ; 565*38624Skarels { 566*38624Skarels register struct dkchan *dkp ; 567*38624Skarels register s ; 568*38624Skarels 569*38624Skarels if (addr == 0) { 570*38624Skarels log(LOG_ERR, "dk_recv: channel %d endfcn %x: invalid address specification\n", chan, endfcn); 571*38624Skarels return 0; 572*38624Skarels } 573*38624Skarels 574*38624Skarels s = spl5() ; 575*38624Skarels dkp = &dkit[chan] ; 576*38624Skarels if (dkp->dk_state & (DK_RCV | DK_RESET)) { 577*38624Skarels splx(s) ; 578*38624Skarels return 0 ; 579*38624Skarels } 580*38624Skarels dkp->dk_state |= DK_RCV ; 581*38624Skarels dkp->dk_endfcn = endfcn ; 582*38624Skarels dkp->dk_endparm = endparm ; 583*38624Skarels dkp->dk_rmode = mode ; 584*38624Skarels dkp->dk_rlen = len ; 585*38624Skarels dkp->dk_raddr = (caddr_t)addr ; 586*38624Skarels if (chan > dkdebug) 587*38624Skarels log(LOG_ERR, "dkrecv %d: %x len %d mode %o\n", chan, (caddr_t)addr, len, mode) ; 588*38624Skarels dkrcv(dkp, chan, 2) ; 589*38624Skarels splx(s) ; 590*38624Skarels return dkp->dk_state ; 591*38624Skarels } 592*38624Skarels 593*38624Skarels 594*38624Skarels dk_rabort(chan, nendfcn, nendparm) 595*38624Skarels int (*nendfcn)() ; 596*38624Skarels caddr_t nendparm ; 597*38624Skarels { 598*38624Skarels register struct dkchan *dkp ; 599*38624Skarels register s ; 600*38624Skarels 601*38624Skarels dkp = &dkit[chan] ; 602*38624Skarels s = spl5() ; 603*38624Skarels if (dkp->dk_state & DK_RCV) { 604*38624Skarels dkp->dk_state &= ~DK_RCV ; 605*38624Skarels if (dkp->dk_rlen) { 606*38624Skarels if (chan > dkdebug) 607*38624Skarels log(LOG_ERR, "rcvabo %d: rlen %d\n", chan, dkp->dk_rlen) ; 608*38624Skarels (*nendfcn)(nendparm, chan, dkp->dk_rlen, DKR_ABORT, 0) ; 609*38624Skarels } 610*38624Skarels dkp->dk_rlen = 0 ; 611*38624Skarels } 612*38624Skarels splx(s) ; 613*38624Skarels return dkp->dk_state ; 614*38624Skarels } 615*38624Skarels 616*38624Skarels 617*38624Skarels 618*38624Skarels dk_status(chan) 619*38624Skarels { 620*38624Skarels if (chan >= dk_nchan) 621*38624Skarels return 0 ; 622*38624Skarels return dkit[chan].dk_state ; 623*38624Skarels } 624*38624Skarels 625*38624Skarels 626*38624Skarels dk_timeout() 627*38624Skarels { 628*38624Skarels register struct rdevice *raddr; 629*38624Skarels register struct dkchan *dkp; 630*38624Skarels register chan ; 631*38624Skarels int s = spl5(); 632*38624Skarels 633*38624Skarels chan = 0 ; 634*38624Skarels for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) { 635*38624Skarels if (dkp->dk_X != XM_OFF) { 636*38624Skarels if (dkp->dk_X == 0) 637*38624Skarels dksend(chan, INIT1) ; 638*38624Skarels else 639*38624Skarels if (dkp->dk_S != ((dkp->dk_R + 1) & 07)) { 640*38624Skarels if (dkp->dk_X & XM_ENQ) { 641*38624Skarels dksend(chan, ENQ) ; 642*38624Skarels dkp->dk_X &= ~XM_REJ ; 643*38624Skarels dkp->dk_enqcnt++; 644*38624Skarels URPTRACE(chan, ENQ, dkp); 645*38624Skarels } 646*38624Skarels else dkp->dk_X |= XM_ENQ; 647*38624Skarels } 648*38624Skarels } 649*38624Skarels chan++ ; 650*38624Skarels } 651*38624Skarels 652*38624Skarels dkstray = 0; 653*38624Skarels if(dkdisabled){ 654*38624Skarels if(dkdisabled++ > 10){ 655*38624Skarels /* try re-enabling interrupts */ 656*38624Skarels dkdisabled = 0; 657*38624Skarels log(LOG_ERR, "re-enabling DK interface\n"); 658*38624Skarels raddr = DKADDR; 659*38624Skarels raddr->dkcsr = ENABS; 660*38624Skarels } 661*38624Skarels } 662*38624Skarels else { 663*38624Skarels /* Look for lost interrupts */ 664*38624Skarels if (raddr->dkcsr < 0) { 665*38624Skarels dkdrlostint++; 666*38624Skarels dkdrxint(0); 667*38624Skarels } 668*38624Skarels } 669*38624Skarels 670*38624Skarels timeout(dk_timeout, (caddr_t) 0, 1*hz); 671*38624Skarels splx(s); 672*38624Skarels } 673*38624Skarels 674*38624Skarels dk_cmd(chan, cmd) 675*38624Skarels { 676*38624Skarels register struct dkchan *dkp ; 677*38624Skarels int s = spl5(); 678*38624Skarels 679*38624Skarels if (chan > dkdebug) 680*38624Skarels log(LOG_ERR, "dkcmd %d: %o\n", chan, cmd) ; 681*38624Skarels dkp = &dkit[chan] ; 682*38624Skarels if (cmd & DKC_XINIT) { 683*38624Skarels dkp->dk_X = dkp->dk_R = dkp->dk_A = 0 ; 684*38624Skarels dkp->dk_S = 1 ; 685*38624Skarels dksend(chan, INIT1) ; 686*38624Skarels } 687*38624Skarels if (cmd & DKC_FLUSH) { 688*38624Skarels flushall(dkp, -1) ; 689*38624Skarels } 690*38624Skarels if (cmd & DKC_SPND) 691*38624Skarels dkp->dk_state |= DK_SPND ; 692*38624Skarels if (cmd & DKC_RSME) { 693*38624Skarels dkp->dk_state &= ~DK_SPND ; 694*38624Skarels dkxmit(dkp, chan, 2) ; 695*38624Skarels } 696*38624Skarels splx(s); 697*38624Skarels } 698*38624Skarels 699*38624Skarels 700*38624Skarels static 701*38624Skarels flushall(dkp, rwflag) 702*38624Skarels register struct dkchan *dkp ; 703*38624Skarels { 704*38624Skarels register s ; 705*38624Skarels struct mpacket *mbp; 706*38624Skarels 707*38624Skarels s = spl5() ; 708*38624Skarels if ((dkp->dk_state & DK_RCV) && (rwflag >= 0)) { 709*38624Skarels dkp->dk_state &= ~DK_RCV ; 710*38624Skarels if (dkp->dk_endfcn) 711*38624Skarels (*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, dkp->dk_rlen, DKR_ABORT, 0) ; 712*38624Skarels dkp->dk_rlen = 0 ; 713*38624Skarels } 714*38624Skarels if ((dkp->dk_state & DK_BUSY) && (rwflag <= 0)) { 715*38624Skarels register struct mbuf *m ; 716*38624Skarels 717*38624Skarels dkp->dk_xlen = 0; 718*38624Skarels if (dkp->dk_curout) { 719*38624Skarels mbp = mtod(dkp->dk_curout, struct mpacket *); 720*38624Skarels if (mbp->mp_endfcn) 721*38624Skarels (mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit); 722*38624Skarels m_freem(dkp->dk_curout); 723*38624Skarels dkp->dk_curout = NULL; 724*38624Skarels } 725*38624Skarels while (1) { 726*38624Skarels IF_DEQUEUE(&dkp->dk_outq, m); 727*38624Skarels if (!m) break; 728*38624Skarels mbp = mtod(m, struct mpacket *); 729*38624Skarels if (mbp->mp_endfcn) 730*38624Skarels (mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit); 731*38624Skarels m_freem(m); 732*38624Skarels } 733*38624Skarels dkp->dk_state &= ~DK_BUSY ; 734*38624Skarels } 735*38624Skarels if ((dkp->dk_state & DK_OPEN) && (rwflag >= 0)) { 736*38624Skarels register struct dkpkbufr *dbp ; 737*38624Skarels 738*38624Skarels dkp->dk_rlen = 0 ; 739*38624Skarels dkp->dk_xlen = 0 ; 740*38624Skarels dkp->dk_C = 0 ; 741*38624Skarels while (dbp = dkp->dk_rq) { 742*38624Skarels dkp->dk_rq = dbp->Pnext ; 743*38624Skarels dbp->Pnext = dk_Sfree ; 744*38624Skarels dk_Sfree = dbp ; 745*38624Skarels } 746*38624Skarels while (dbp = dkp->dk_rb) { 747*38624Skarels dkp->dk_rb = dbp->Pnext ; 748*38624Skarels dbp->Pnext = dk_Sfree ; 749*38624Skarels dk_Sfree = dbp ; 750*38624Skarels } 751*38624Skarels } 752*38624Skarels splx(s) ; 753*38624Skarels } 754*38624Skarels 755*38624Skarels 756*38624Skarels /* 757*38624Skarels * Routine to handle completion status 758*38624Skarels */ 759*38624Skarels static 760*38624Skarels dkkint() 761*38624Skarels { 762*38624Skarels register struct dkchan *dkp; 763*38624Skarels register struct dkstat *sp; 764*38624Skarels register chan; 765*38624Skarels struct mbuf *m ,*om; 766*38624Skarels struct mpacket *mbp; 767*38624Skarels static char *cmpltype[] = {"send", "rdb", "eoi", "cntl", "err"}; 768*38624Skarels 769*38624Skarels while (Tstat != Hstat) { 770*38624Skarels sp = &dkdr_stat[Hstat]; 771*38624Skarels chan = sp->k_chan; 772*38624Skarels dkp = &dkit[chan]; 773*38624Skarels if (sp->k_chan > dkdebug) { 774*38624Skarels if (sp->k_type >= KS_SEND && sp->k_type <= KS_ERR) 775*38624Skarels log(LOG_ERR, "dkdone: type %s chan %d info %o-%o\n", 776*38624Skarels cmpltype[sp->k_type-KS_SEND], 777*38624Skarels sp->k_chan, sp->k_info1, sp->k_info2) ; 778*38624Skarels else log(LOG_ERR, "dkdone: type %d chan %d info %o-%o\n", 779*38624Skarels sp->k_type, sp->k_chan, sp->k_info1, sp->k_info2) ; 780*38624Skarels } 781*38624Skarels if (Hstat==dkdr_nstat-1) Hstat=0; else Hstat++; 782*38624Skarels switch(sp->k_type) { 783*38624Skarels case KS_CNTL: 784*38624Skarels if (dkp->dk_supfcn) 785*38624Skarels (*dkp->dk_supfcn)(chan, sp->k_info1) ; 786*38624Skarels break ; 787*38624Skarels case KS_EOI: 788*38624Skarels break ; 789*38624Skarels case KS_SEND: 790*38624Skarels om = dkp->dk_curout ; 791*38624Skarels if (om == NULL) { 792*38624Skarels log(LOG_ERR, "dkk: xbufout\n"); 793*38624Skarels break; 794*38624Skarels } 795*38624Skarels IF_DEQUEUE(&dkp->dk_outq, m); 796*38624Skarels if (m == NULL) { 797*38624Skarels dkp->dk_state &= ~DK_BUSY; 798*38624Skarels dkp->dk_curout = NULL; 799*38624Skarels } else { 800*38624Skarels dkp->dk_curout = m; 801*38624Skarels mbp = mtod(m, struct mpacket *); 802*38624Skarels dkp->dk_xlen = mbp->mp_len ; 803*38624Skarels if (chan > dkdebug) 804*38624Skarels log(LOG_ERR, "xmiti %d: %x len %d\n", chan, 805*38624Skarels m->m_next, mbp->mp_len) ; 806*38624Skarels dkxmit(dkp, chan, 0) ; 807*38624Skarels } 808*38624Skarels mbp = mtod(om, struct mpacket *); 809*38624Skarels if (mbp->mp_endfcn != NULL) 810*38624Skarels (mbp->mp_endfcn)(mbp->mp_endparm, chan) ; 811*38624Skarels m_freem(om); 812*38624Skarels break; 813*38624Skarels case KS_RDB: 814*38624Skarels dkp->dk_state &= ~(DK_RCV|DK_RCVQ) ; 815*38624Skarels if (sp->k_info2 == DKR_TIME && dkp->dk_rlen == 0) 816*38624Skarels break ; /* another coming later */ 817*38624Skarels if (dkp->dk_rlen) { 818*38624Skarels sp->k_info1 = dkp->dk_rlen ; 819*38624Skarels dkp->dk_rlen = 0 ; 820*38624Skarels } 821*38624Skarels if (dkp->dk_endfcn != NULL) 822*38624Skarels (*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, sp->k_info1, sp->k_info2&0377, 823*38624Skarels (sp->k_info2>>8)&0377) ; 824*38624Skarels break; 825*38624Skarels case KS_ERR: 826*38624Skarels log(LOG_ERR, "err in dkit.c: chan - %d, code - %o\n", 827*38624Skarels chan, sp->k_info1); 828*38624Skarels break; 829*38624Skarels } /* end switch */ 830*38624Skarels 831*38624Skarels } /* end while */ 832*38624Skarels } 833*38624Skarels 834*38624Skarels 835*38624Skarels 836*38624Skarels 837*38624Skarels 838*38624Skarels 839*38624Skarels 840*38624Skarels /* static */ 841*38624Skarels int dkxmitpanic = 0; 842*38624Skarels 843*38624Skarels dkxmit(dkp, stechan, intrpt) 844*38624Skarels struct dkchan *dkp ; 845*38624Skarels { 846*38624Skarels register struct rdevice *raddr ; 847*38624Skarels register char *ptr ; 848*38624Skarels register struct mbuf *m; 849*38624Skarels register int wtype; 850*38624Skarels short pklen ; 851*38624Skarels short mlen, unacked ; 852*38624Skarels short blklen ; 853*38624Skarels unsigned short totlen ; 854*38624Skarels struct mpacket *mbp ; 855*38624Skarels #ifdef notdef 856*38624Skarels short scheck ; 857*38624Skarels #endif 858*38624Skarels 859*38624Skarels if( dkp->dk_curout == NULL || stechan ==0 ) 860*38624Skarels return ; 861*38624Skarels mbp = mtod(dkp->dk_curout, struct mpacket *); 862*38624Skarels raddr = DKADDR ; 863*38624Skarels if ((dkp->dk_S & DKBMASK) == (dkp->dk_R & DKBMASK) || (dkp->dk_state & DK_SPND)) 864*38624Skarels goto ctlchk ; 865*38624Skarels if ((dkp->dk_xlen || ((mbp->mp_ctl & 0200) == 0)) && dkp->dk_X < XM_INIT) 866*38624Skarels goto ctlchk ; 867*38624Skarels #ifdef notdef 868*38624Skarels if ((dkp->dk_S & DKBMASK) == ((dkp->dk_R + 1) & DKBMASK)) 869*38624Skarels scheck = 0 ; 870*38624Skarels else 871*38624Skarels scheck = 1 ; 872*38624Skarels #endif 873*38624Skarels 874*38624Skarels unacked = ((dkp->dk_S - dkp->dk_A - 1) & 07) * DKBLOCK ; 875*38624Skarels mlen = MIN(unacked, dkp->dk_xlen) ; 876*38624Skarels totlen = dkp->dk_xlen - mlen; 877*38624Skarels if (totlen == 0) 878*38624Skarels goto ctlchk ; 879*38624Skarels 880*38624Skarels /* Skip over stuff sent but not acked */ 881*38624Skarels for (m = dkp->dk_curout->m_next; m && (mlen > 0); m = m->m_next) 882*38624Skarels if (mlen > m->m_len) mlen -= m->m_len; 883*38624Skarels else break; 884*38624Skarels 885*38624Skarels while (totlen && ((dkp->dk_S ^ dkp->dk_R) & DKBMASK)) { 886*38624Skarels if (dkxmitpanic) panic("dkxmit -- panic 1"); 887*38624Skarels blklen = MIN (totlen, DKBLOCK) ; 888*38624Skarels pklen = 0 ; 889*38624Skarels raddr->dkcsr = D_WRITE ; 890*38624Skarels raddr->dko = stechan | DKMARK ; 891*38624Skarels while (blklen) { 892*38624Skarels if (dkxmitpanic) panic("dkxmit -- panic 2"); 893*38624Skarels if (m == NULL) panic("dkxmit mlen"); 894*38624Skarels ptr = mtod(m, char *) + mlen; 895*38624Skarels mlen = MIN(blklen, m->m_len - mlen); 896*38624Skarels blklen -= mlen; 897*38624Skarels wtype = (m->m_type == DKMT_CTL ? 0 : DKDATA); 898*38624Skarels while (mlen--) { 899*38624Skarels if (dkxmitpanic) panic("dkxmit -- panic 3"); 900*38624Skarels raddr->dko = (*ptr++ & 0377) | wtype ; 901*38624Skarels pklen++ ; 902*38624Skarels if ((pklen & (DKCHUNK-1)) == 0) { 903*38624Skarels raddr->dkcsr = D_XPACK ; 904*38624Skarels raddr->dko = 0 ; 905*38624Skarels raddr->dkcsr = D_WRITE ; 906*38624Skarels raddr->dko = stechan|DKMARK ; 907*38624Skarels } 908*38624Skarels } 909*38624Skarels if (ptr == (mtod(m, char *) + m->m_len)) { 910*38624Skarels m = m->m_next; 911*38624Skarels mlen = 0; 912*38624Skarels } 913*38624Skarels else mlen = ptr - mtod(m, char *); 914*38624Skarels } 915*38624Skarels blklen = MIN (totlen, DKBLOCK) ; 916*38624Skarels if ((pklen & (DKCHUNK-1)) > (DKCHUNK-4)) { 917*38624Skarels raddr->dkcsr = D_XPACK ; 918*38624Skarels raddr->dko = 0 ; 919*38624Skarels raddr->dkcsr = D_WRITE ; 920*38624Skarels raddr->dko = stechan|DKMARK ; 921*38624Skarels } 922*38624Skarels if (blklen == totlen && mbp->mp_eob) 923*38624Skarels raddr->dko = BOT ; 924*38624Skarels else 925*38624Skarels raddr->dko = BOTM ; 926*38624Skarels raddr->dko = (blklen & 0377) | DKDATA ; 927*38624Skarels raddr->dko = ((blklen>>8) & 0377) | DKDATA ; 928*38624Skarels raddr->dko = SEQ + dkp->dk_S ; 929*38624Skarels raddr->dkcsr = D_XPACK ; 930*38624Skarels raddr->dko = 0 ; 931*38624Skarels URPTRACE(stechan, SEQ + dkp->dk_S, dkp); 932*38624Skarels dkp->dk_S++ ; 933*38624Skarels dkp->dk_S &= 07 ; 934*38624Skarels totlen -= blklen ; 935*38624Skarels } 936*38624Skarels #ifdef notdef 937*38624Skarels if (totlen == 0 && dkp->dk_xlen && scheck) { 938*38624Skarels raddr->dkcsr = D_WRITE ; 939*38624Skarels raddr->dko = stechan|DKMARK ; 940*38624Skarels raddr->dko = CHECK ; 941*38624Skarels raddr->dkcsr = D_XPACK ; 942*38624Skarels raddr->dko = 0 ; 943*38624Skarels URPTRACE(stechan, CHECK, dkp); 944*38624Skarels } 945*38624Skarels #endif 946*38624Skarels ctlchk: 947*38624Skarels if (mbp->mp_ctl & 0200) { 948*38624Skarels raddr->dkcsr = D_WRITE ; 949*38624Skarels raddr->dko = stechan|DKMARK ; 950*38624Skarels raddr->dko = mbp->mp_ctl & 0377 ; 951*38624Skarels raddr->dkcsr = D_XPACK ; 952*38624Skarels raddr->dko = 0 ; 953*38624Skarels mbp->mp_ctl = 0 ; 954*38624Skarels if (dkp->dk_xlen == 0) 955*38624Skarels dkreport(KS_SEND, stechan, 0, 0, intrpt) ; 956*38624Skarels } 957*38624Skarels if(dkdisabled) 958*38624Skarels raddr->dkcsr = 0; 959*38624Skarels else 960*38624Skarels raddr->dkcsr = ENABS ; 961*38624Skarels } 962*38624Skarels 963*38624Skarels 964*38624Skarels static 965*38624Skarels dkrcv(dkp, stechan, intrpt) 966*38624Skarels struct dkchan *dkp ; 967*38624Skarels { 968*38624Skarels register char *ptr1 ; 969*38624Skarels register char *ptr2 ; 970*38624Skarels register len ; 971*38624Skarels short final ; 972*38624Skarels short hibits ; 973*38624Skarels struct dkpkbufr *pkb ; 974*38624Skarels short tlen ; 975*38624Skarels 976*38624Skarels if ((dkp->dk_rlen == 0) || (dkp->dk_rq == NULL)) 977*38624Skarels return ; 978*38624Skarels final = 0 ; 979*38624Skarels tlen = 0 ; 980*38624Skarels while (final == 0 && (pkb = dkp->dk_rq)) { 981*38624Skarels if (dkp->dk_rlen == 0) 982*38624Skarels final |= DKR_FULL ; 983*38624Skarels ptr1 = &pkb->Pdata[0] ; 984*38624Skarels ptr2 = dkp->dk_raddr ; 985*38624Skarels len = MIN(pkb->Plen, dkp->dk_rlen) ; 986*38624Skarels hibits = pkb->Phibits ; 987*38624Skarels while (len--) { 988*38624Skarels if (hibits < 0) 989*38624Skarels break ; 990*38624Skarels hibits <<= 1 ; 991*38624Skarels *ptr2++ = *ptr1++ ; 992*38624Skarels } 993*38624Skarels len = ptr2 - dkp->dk_raddr ; 994*38624Skarels tlen += len ; 995*38624Skarels dkp->dk_rlen -= len ; 996*38624Skarels dkp->dk_raddr = ptr2 ; 997*38624Skarels if ((pkb->Plen -= len) && hibits < 0) { 998*38624Skarels final |= ((*ptr1++ & 0377) << 8) | DKR_CNTL ; 999*38624Skarels hibits <<= 1 ; 1000*38624Skarels pkb->Plen-- ; 1001*38624Skarels } 1002*38624Skarels if (len = pkb->Plen) { 1003*38624Skarels ptr2 = &pkb->Pdata[0] ; 1004*38624Skarels while (len--) 1005*38624Skarels *ptr2++ = *ptr1++ ; 1006*38624Skarels pkb->Phibits = hibits ; 1007*38624Skarels } 1008*38624Skarels while (pkb && (pkb->Plen == 0)) { 1009*38624Skarels if ((pkb->Pseq & 0370) == ACK) { 1010*38624Skarels pkb->Pseq += ECHO - ACK ; 1011*38624Skarels final |= dkp->dk_rmode & DKR_BLOCK ; 1012*38624Skarels } 1013*38624Skarels if (pkb->Pseq) { 1014*38624Skarels dksend(stechan, pkb->Pseq) ; 1015*38624Skarels dkp->dk_C = pkb->Pseq ; 1016*38624Skarels } 1017*38624Skarels dkp->dk_rq = pkb->Pnext ; 1018*38624Skarels pkb->Pnext = dk_Sfree ; 1019*38624Skarels dk_Sfree = pkb ; 1020*38624Skarels pkb = dkp->dk_rq ; 1021*38624Skarels } 1022*38624Skarels } 1023*38624Skarels if (tlen && (dkp->dk_rmode & DKR_TIME)) 1024*38624Skarels final |= DKR_TIME ; 1025*38624Skarels if (dkp->dk_rlen == 0) 1026*38624Skarels final |= DKR_FULL ; 1027*38624Skarels if (final && (final != DKR_TIME || ((dkp->dk_state & DK_RCVQ) == 0))) { 1028*38624Skarels dkp->dk_state |= DK_RCVQ ; 1029*38624Skarels len = dkp->dk_rlen ; 1030*38624Skarels if (final != DKR_TIME) 1031*38624Skarels dkp->dk_rlen = 0 ; 1032*38624Skarels dkreport(KS_RDB, stechan, len, final, (final == DKR_TIME)?2:intrpt) ; 1033*38624Skarels } 1034*38624Skarels } 1035*38624Skarels 1036*38624Skarels 1037*38624Skarels 1038*38624Skarels static 1039*38624Skarels dksend(stechan, val) 1040*38624Skarels { 1041*38624Skarels register struct rdevice *raddr ; 1042*38624Skarels register savcsr ; 1043*38624Skarels 1044*38624Skarels if(stechan == 0) 1045*38624Skarels return; 1046*38624Skarels 1047*38624Skarels raddr = DKADDR ; 1048*38624Skarels savcsr = raddr->dkcsr ; 1049*38624Skarels raddr->dkcsr = D_WRITE ; 1050*38624Skarels raddr->dko = stechan| DKMARK ; 1051*38624Skarels raddr->dko = val ; 1052*38624Skarels raddr->dkcsr = D_XPACK ; 1053*38624Skarels raddr->dko = 0 ; 1054*38624Skarels raddr->dkcsr = savcsr ; 1055*38624Skarels } 1056*38624Skarels 1057*38624Skarels 1058*38624Skarels /*ARGSUSED*/ 1059*38624Skarels dkdrrint(dev) /* ?? */ /* needed for UNIX OS */ 1060*38624Skarels { 1061*38624Skarels register struct rdevice *raddr ; 1062*38624Skarels register c ; 1063*38624Skarels register cnt; 1064*38624Skarels 1065*38624Skarels #ifdef lint 1066*38624Skarels c = 0; cnt = c; 1067*38624Skarels #endif 1068*38624Skarels cnt = 0; 1069*38624Skarels raddr = DKADDR ; 1070*38624Skarels raddr->dkcsr = D_OSEQ ; 1071*38624Skarels if((raddr->dkcsr & DKTDONE) == 0){ 1072*38624Skarels if(dkstray++ >= MAX_STRAY){ 1073*38624Skarels log(LOG_ERR, "DK err 1 (Cabling?)\n"); 1074*38624Skarels raddr->dkcsr = 0; 1075*38624Skarels dkdisabled = 1; 1076*38624Skarels return; 1077*38624Skarels } 1078*38624Skarels } 1079*38624Skarels while (raddr->dkcsr & DKTDONE){ 1080*38624Skarels c = raddr->dki ; 1081*38624Skarels if(cnt++ > 65){ 1082*38624Skarels log(LOG_ERR, "DK err 2 (Cabling?)\n"); 1083*38624Skarels raddr->dkcsr = 0; 1084*38624Skarels dkdisabled = 1; 1085*38624Skarels return; 1086*38624Skarels } 1087*38624Skarels } 1088*38624Skarels raddr->dkcsr = ENABS ; 1089*38624Skarels if (Hstat != Tstat) 1090*38624Skarels dkkint() ; 1091*38624Skarels } 1092*38624Skarels 1093*38624Skarels /*ARGSUSED*/ 1094*38624Skarels dkdrxint(dev) /* ?? */ 1095*38624Skarels { 1096*38624Skarels register struct rdevice *raddr ; 1097*38624Skarels register char *ptr ; 1098*38624Skarels struct dkchan *dkp ; 1099*38624Skarels register c ; 1100*38624Skarels short badpacks ; 1101*38624Skarels struct dkpkbufr *pkb ; 1102*38624Skarels short stechan ; 1103*38624Skarels short len, xlen ; 1104*38624Skarels unsigned short bitloc ; 1105*38624Skarels 1106*38624Skarels badpacks = 0 ; 1107*38624Skarels raddr = DKADDR ; 1108*38624Skarels pkb = NULL ; 1109*38624Skarels if(raddr->dkcsr >= 0){ 1110*38624Skarels if(dkstray++ > MAX_STRAY){ 1111*38624Skarels log(LOG_ERR, "DK err 3 (Cabling?)\n"); 1112*38624Skarels goto disable; 1113*38624Skarels } 1114*38624Skarels } 1115*38624Skarels while (raddr->dkcsr < 0) { 1116*38624Skarels raddr->dkcsr = D_READ ; 1117*38624Skarels c = raddr->dki ; 1118*38624Skarels while (raddr->dkcsr < 0 && (c & DKMARK)) { 1119*38624Skarels c &= 0777 ; 1120*38624Skarels if (c >= dk_nchan) { 1121*38624Skarels if (++badpacks > 20) { 1122*38624Skarels log(LOG_ERR, "DK err 4 (Cabling?)\n"); 1123*38624Skarels dkreport(KS_ERR, 0, 2, 0, 1) ; 1124*38624Skarels goto disable ; 1125*38624Skarels } 1126*38624Skarels break ; 1127*38624Skarels } 1128*38624Skarels /* discard all chl 0 packets; 1129*38624Skarels * the LDI version of the CPM-DR and CPM-422 1130*38624Skarels * puts out packets on chl 0 occasionally. 1131*38624Skarels */ 1132*38624Skarels if(c == 0) break; 1133*38624Skarels 1134*38624Skarels dkp = &dkit[c] ; 1135*38624Skarels stechan = c ; 1136*38624Skarels qpkb: 1137*38624Skarels if (pkb && pkb->Plen) { 1138*38624Skarels dkrcvq(stechan, dkp, pkb, 0) ; 1139*38624Skarels pkb = NULL ; 1140*38624Skarels } 1141*38624Skarels if (pkb == NULL) { 1142*38624Skarels if ((pkb = dk_Sfree) != NULL) { 1143*38624Skarels dk_Sfree = pkb->Pnext ; 1144*38624Skarels pkb->Pseq = 0 ; 1145*38624Skarels pkb->Plen = 0 ; 1146*38624Skarels pkb->Pnext = NULL ; 1147*38624Skarels pkb->Phibits = 0 ; 1148*38624Skarels } else { 1149*38624Skarels /* 1150*38624Skarels ** Oops, no more dkpkbufr's. 1151*38624Skarels ** Let outer loop gobble up 1152*38624Skarels ** the entire packet. 1153*38624Skarels ** Report to the console 1154*38624Skarels ** every 100th occurrence. 1155*38624Skarels */ 1156*38624Skarels if ( dknopkb++ >= 100 ) { 1157*38624Skarels dknopkb = 1 ; 1158*38624Skarels dkreport(KS_ERR, 0, 3, 0, 1) ; 1159*38624Skarels } 1160*38624Skarels break ; 1161*38624Skarels } 1162*38624Skarels } 1163*38624Skarels raddr->dkcsr = D_READ ; 1164*38624Skarels ptr = &pkb->Pdata[0] ; 1165*38624Skarels bitloc = 0100000 ; 1166*38624Skarels while (raddr->dkcsr < 0 && ((c = raddr->dki) & DKMARK) == 0) 1167*38624Skarels switch (c = c & 0777) { 1168*38624Skarels case NULL: 1169*38624Skarels break ; 1170*38624Skarels case AINIT: 1171*38624Skarels dkp->dk_X = XM_INIT ; 1172*38624Skarels dkp->dk_R = 0 ; 1173*38624Skarels dkp->dk_S = 1 ; 1174*38624Skarels dkp->dk_A = 0 ; 1175*38624Skarels dkxmit(dkp, stechan, 1) ; 1176*38624Skarels raddr->dkcsr = D_READ ; 1177*38624Skarels break ; 1178*38624Skarels case INIT0: 1179*38624Skarels dksend(stechan, AINIT) ; 1180*38624Skarels dkp->dk_trmode = 0 ; 1181*38624Skarels dkp->dk_C = dkp->dk_rseq = 0 ; 1182*38624Skarels break ; 1183*38624Skarels case INIT1: 1184*38624Skarels dksend(stechan, AINIT) ; 1185*38624Skarels dkp->dk_trmode = 1 ; 1186*38624Skarels dkp->dk_C = dkp->dk_tail1 = dkp->dk_tail2 = dkp->dk_rseq = 0 ; 1187*38624Skarels while (pkb) { 1188*38624Skarels pkb->Pnext = dk_Sfree ; 1189*38624Skarels dk_Sfree = pkb ; 1190*38624Skarels if (pkb = dkp->dk_rq) 1191*38624Skarels dkp->dk_rq = pkb->Pnext ; 1192*38624Skarels if (pkb == NULL) 1193*38624Skarels if (pkb = dkp->dk_rb) 1194*38624Skarels dkp->dk_rb = pkb->Pnext ; 1195*38624Skarels } 1196*38624Skarels goto qpkb ; 1197*38624Skarels case INITREQ: 1198*38624Skarels dksend(stechan, INIT1) ; 1199*38624Skarels dkp->dk_X = 0 ; 1200*38624Skarels break ; 1201*38624Skarels case ENQ: 1202*38624Skarels dksend(stechan, dkp->dk_C) ; 1203*38624Skarels case CHECK: 1204*38624Skarels dksend(stechan, ACK+dkp->dk_rseq) ; 1205*38624Skarels while (pkb) { 1206*38624Skarels pkb->Pnext = dk_Sfree ; 1207*38624Skarels dk_Sfree = pkb ; 1208*38624Skarels if (pkb = dkp->dk_rb) 1209*38624Skarels dkp->dk_rb = pkb->Pnext ; 1210*38624Skarels } 1211*38624Skarels dkp->dk_rblen = 0 ; 1212*38624Skarels goto qpkb ; 1213*38624Skarels case EOI: 1214*38624Skarels if (dkp->dk_tail1 == ((SOI<<8)|2)) 1215*38624Skarels dkreport(KS_EOI, stechan, dkp->dk_tail2, 0, 1) ; 1216*38624Skarels dkp->dk_tail1 = 0 ; 1217*38624Skarels break ; 1218*38624Skarels default: 1219*38624Skarels if (c & DKDATA) { 1220*38624Skarels if (dkp->dk_tail1) { 1221*38624Skarels dkp->dk_tail2 = ((dkp->dk_tail2 >> 8) & 0377) | (c<<8) ; 1222*38624Skarels dkp->dk_tail1++ ; 1223*38624Skarels if ((dkp->dk_tail1 & 0377) > 3) 1224*38624Skarels dkp->dk_tail1 = 0 ; 1225*38624Skarels } else { 1226*38624Skarels *ptr++ = c & 0377 ; 1227*38624Skarels pkb->Plen++ ; 1228*38624Skarels bitloc >>= 1 ; 1229*38624Skarels } 1230*38624Skarels break ; 1231*38624Skarels } 1232*38624Skarels if (((c & 0770) == ECHO) || ((c & 0770) == REJ)) { 1233*38624Skarels URPTRACE(stechan, c, dkp); 1234*38624Skarels dkp->dk_R = c & 07 ; 1235*38624Skarels if (((dkp->dk_S - dkp->dk_R - 1) & 07) < 1236*38624Skarels ((dkp->dk_S - dkp->dk_A - 1) & 07)) { 1237*38624Skarels gotack: 1238*38624Skarels dkp->dk_X &= ~(XM_REJ | XM_ENQ); 1239*38624Skarels xlen = dkp->dk_xlen ; 1240*38624Skarels len = ((c - dkp->dk_A) & 07) * DKBLOCK ; 1241*38624Skarels len = MIN(len, xlen); 1242*38624Skarels dkp->dk_xlen -= len; 1243*38624Skarels if (dkp->dk_curout) 1244*38624Skarels m_adj(dkp->dk_curout->m_next, len) ; 1245*38624Skarels dkp->dk_A = c & 07 ; 1246*38624Skarels if (len || xlen) 1247*38624Skarels if ((dkp->dk_xlen) == 0) 1248*38624Skarels dkreport(KS_SEND, stechan, 0, 0, 1) ; 1249*38624Skarels } 1250*38624Skarels dkxmit(dkp, stechan, 1) ; 1251*38624Skarels raddr->dkcsr = D_READ ; 1252*38624Skarels if ((c & 0770) == REJ && ((dkp->dk_X & XM_REJ) == 0)) { 1253*38624Skarels dkp->dk_rejcnt++; 1254*38624Skarels gotrej: 1255*38624Skarels dkp->dk_S = (c+1) & 07 ; 1256*38624Skarels dkxmit(dkp, stechan, 1) ; 1257*38624Skarels raddr->dkcsr = D_READ ; 1258*38624Skarels dkp->dk_X |= XM_REJ ; 1259*38624Skarels } 1260*38624Skarels break ; 1261*38624Skarels } 1262*38624Skarels if ((c & 0770) == ACK) { 1263*38624Skarels URPTRACE(stechan, c, dkp); 1264*38624Skarels if (dkp->dk_A != (c & 07)) 1265*38624Skarels goto gotack ; 1266*38624Skarels if ((dkp->dk_X & XM_REJ) == 0) { 1267*38624Skarels dkp->dk_ackrejcnt++; 1268*38624Skarels goto gotrej ; 1269*38624Skarels } 1270*38624Skarels break ; 1271*38624Skarels } 1272*38624Skarels if ((c & 0774) == BOT) { 1273*38624Skarels dkp->dk_tail1 = c << 8 ; 1274*38624Skarels break ; 1275*38624Skarels } 1276*38624Skarels if ((c & 0770) == SEQ) { 1277*38624Skarels pkb->Pseq = c - SEQ + ECHO ; 1278*38624Skarels dkrcvq(stechan, dkp, pkb, 0) ; 1279*38624Skarels if (dkp->dk_trmode) { 1280*38624Skarels if (dkp->dk_rblen == dkp->dk_tail2 && 1281*38624Skarels (dkp->dk_tail1 & 0377) == 2 && 1282*38624Skarels ((dkp->dk_tail1 >> 8) & 0377) != SOI && 1283*38624Skarels ((dkp->dk_rseq+1) & 07) == (c & 07)) { 1284*38624Skarels dkp->dk_rseq = c & 07 ; 1285*38624Skarels if (((dkp->dk_tail1>>8) & 0377) != BOTM) 1286*38624Skarels pkb->Pseq += ACK - ECHO ; 1287*38624Skarels dkrcvq(stechan, dkp, dkp->dk_rb, 1) ; 1288*38624Skarels } else { 1289*38624Skarels while (pkb = dkp->dk_rb) { 1290*38624Skarels dkp->dk_rb = pkb->Pnext ; 1291*38624Skarels pkb->Pnext = dk_Sfree ; 1292*38624Skarels dk_Sfree = pkb ; 1293*38624Skarels } 1294*38624Skarels pkb = dk_Sfree ; 1295*38624Skarels dk_Sfree = pkb->Pnext ; 1296*38624Skarels pkb->Plen = 0 ; 1297*38624Skarels pkb->Pnext = NULL ; 1298*38624Skarels pkb->Pseq = REJ + dkp->dk_rseq ; 1299*38624Skarels dkp->dk_srejcnt++; 1300*38624Skarels if (((dkp->dk_tail1>>8) & 0377) == BOTS) { 1301*38624Skarels dkp->dk_rseq = c & 07 ; 1302*38624Skarels pkb->Pseq = ECHO + dkp->dk_rseq ; 1303*38624Skarels } 1304*38624Skarels dkrcvq(stechan, dkp, pkb, 1) ; 1305*38624Skarels } 1306*38624Skarels dkp->dk_rb = NULL ; 1307*38624Skarels dkp->dk_rblen = 0 ; 1308*38624Skarels dkp->dk_tail1 = 0 ; 1309*38624Skarels } else 1310*38624Skarels /* always keep seq no up to date */ 1311*38624Skarels dkp->dk_rseq = c & 07; 1312*38624Skarels pkb = NULL ; 1313*38624Skarels goto qpkb ; 1314*38624Skarels } 1315*38624Skarels if (c & 0200) { 1316*38624Skarels dkreport(KS_CNTL, stechan, c, 0, 1) ; 1317*38624Skarels raddr->dkcsr = D_READ ; 1318*38624Skarels } else { 1319*38624Skarels *ptr++ = c & 0377 ; 1320*38624Skarels pkb->Plen++ ; 1321*38624Skarels pkb->Phibits |= bitloc ; 1322*38624Skarels bitloc >>= 1 ; 1323*38624Skarels } 1324*38624Skarels } 1325*38624Skarels if (pkb && pkb->Plen) { 1326*38624Skarels dkrcvq(stechan, dkp, pkb, 0) ; 1327*38624Skarels pkb = NULL ; 1328*38624Skarels } 1329*38624Skarels } 1330*38624Skarels } 1331*38624Skarels 1332*38624Skarels if (pkb) { 1333*38624Skarels if (pkb->Plen) 1334*38624Skarels dkrcvq(stechan, dkp, pkb, 0) ; 1335*38624Skarels else { 1336*38624Skarels pkb->Pnext = dk_Sfree ; 1337*38624Skarels dk_Sfree = pkb ; 1338*38624Skarels } 1339*38624Skarels } 1340*38624Skarels raddr->dkcsr = ENABS ; 1341*38624Skarels return; 1342*38624Skarels 1343*38624Skarels disable: 1344*38624Skarels if(pkb){ 1345*38624Skarels pkb->Pnext = dk_Sfree; 1346*38624Skarels dk_Sfree = pkb; 1347*38624Skarels } 1348*38624Skarels raddr->dkcsr = 0; 1349*38624Skarels dkdisabled = 1; 1350*38624Skarels } 1351*38624Skarels 1352*38624Skarels dkrcvq(stechan, dkp, npkb, where) 1353*38624Skarels register struct dkchan *dkp ; 1354*38624Skarels struct dkpkbufr *npkb ; 1355*38624Skarels { 1356*38624Skarels register struct dkpkbufr *pkb ; 1357*38624Skarels int i ; 1358*38624Skarels 1359*38624Skarels i = 0 ; 1360*38624Skarels if (dkp->dk_trmode && where == 0) 1361*38624Skarels pkb = (struct dkpkbufr *)&dkp->dk_rb ; 1362*38624Skarels else 1363*38624Skarels pkb = (struct dkpkbufr *)&dkp->dk_rq ; 1364*38624Skarels 1365*38624Skarels while (pkb->Pnext) { 1366*38624Skarels pkb = pkb->Pnext ; 1367*38624Skarels i++ ; 1368*38624Skarels } 1369*38624Skarels if ( i >= PKBHOG ) { 1370*38624Skarels /* 1371*38624Skarels ** This channel has too many buffers. 1372*38624Skarels ** Do not queue any more. 1373*38624Skarels ** Return the new buffer to the free list. 1374*38624Skarels */ 1375*38624Skarels npkb->Pnext = dk_Sfree ; 1376*38624Skarels dk_Sfree = npkb ; 1377*38624Skarels return ; 1378*38624Skarels } 1379*38624Skarels pkb->Pnext = npkb ; 1380*38624Skarels 1381*38624Skarels if (dkp->dk_trmode && where == 0) 1382*38624Skarels dkp->dk_rblen += npkb->Plen ; 1383*38624Skarels else 1384*38624Skarels dkrcv(dkp, stechan, 1) ; 1385*38624Skarels } 1386*38624Skarels 1387*38624Skarels 1388*38624Skarels 1389*38624Skarels dkreport(type, chan, info1, info2, intrpt) 1390*38624Skarels /* intrpt parameter controlls whether the pdp-11 interrupt is called. 1391*38624Skarels * Value 0 says no (means dkxint queued already) 1392*38624Skarels * Value 1 says call it immediately (like from dr11c interrupt) 1393*38624Skarels * Value 2 says to queue a call as soon as processor priority lowers 1394*38624Skarels * (by sending a dummy packet on a channel and getting dkxint) 1395*38624Skarels */ 1396*38624Skarels { 1397*38624Skarels register struct dkstat *sp; 1398*38624Skarels 1399*38624Skarels if ((Tstat + 1) % dkdr_nstat == Hstat) { /* room in queue? */ 1400*38624Skarels log(LOG_ERR, "dkit_dr: No room in status queue, Channel %d\n", chan); 1401*38624Skarels return; 1402*38624Skarels } 1403*38624Skarels 1404*38624Skarels sp = &dkdr_stat[Tstat] ; 1405*38624Skarels sp->k_chan = chan ; 1406*38624Skarels sp->k_type = type ; 1407*38624Skarels sp->k_info1 = info1 ; 1408*38624Skarels sp->k_info2 = info2 ; 1409*38624Skarels if (Tstat == dkdr_nstat-1) Tstat = 0 ; else Tstat++ ; 1410*38624Skarels if (intrpt==1) { 1411*38624Skarels dkkint() ; 1412*38624Skarels } else if (intrpt==2) { 1413*38624Skarels register struct rdevice *raddr ; 1414*38624Skarels raddr = DKADDR ; 1415*38624Skarels raddr->dkcsr = D_WRITE ; 1416*38624Skarels 1417*38624Skarels /* Chl (dk_nchan-1) is used instead of 511 because 1418*38624Skarels * the LDI switch module will complain if we use 1419*38624Skarels * a chl outside the range set up in its route tables. 1420*38624Skarels */ 1421*38624Skarels raddr->dko = (dk_nchan-1) | DKMARK ; 1422*38624Skarels 1423*38624Skarels /* 1424*38624Skarels * A null is used here because it should always 1425*38624Skarels * be ignored by the far end of the circuit. 1426*38624Skarels */ 1427*38624Skarels raddr->dko = 0 ; 1428*38624Skarels 1429*38624Skarels raddr->dkcsr = D_XPACK ; 1430*38624Skarels raddr->dko = 0 ; 1431*38624Skarels raddr->dkcsr = ENABS ; 1432*38624Skarels } 1433*38624Skarels } 1434*38624Skarels 1435*38624Skarels #ifdef URPDEBUG 1436*38624Skarels struct dkurps { 1437*38624Skarels char dku_ctl; 1438*38624Skarels char dku_S; 1439*38624Skarels char dku_R; 1440*38624Skarels char dku_A; 1441*38624Skarels } dkurps[URPDEBUG]; 1442*38624Skarels int dkurpsize = URPDEBUG; 1443*38624Skarels 1444*38624Skarels struct dkurps *dkurpsp = dkurps; 1445*38624Skarels int dkurpreset; 1446*38624Skarels 1447*38624Skarels dkurptrace(ctl, dkp) char ctl; register struct dkchan *dkp; 1448*38624Skarels { 1449*38624Skarels #ifdef lint 1450*38624Skarels dkurpsize = dkurpsize; 1451*38624Skarels #endif 1452*38624Skarels if (dkurpreset) { 1453*38624Skarels dkurpsp = dkurps; 1454*38624Skarels dkurpreset = 0; 1455*38624Skarels } 1456*38624Skarels dkurpsp->dku_ctl = ctl; 1457*38624Skarels dkurpsp->dku_S = dkp->dk_S; 1458*38624Skarels dkurpsp->dku_R = dkp->dk_R; 1459*38624Skarels dkurpsp->dku_A = dkp->dk_A; 1460*38624Skarels if (++dkurpsp == dkurps+URPDEBUG) 1461*38624Skarels dkurpsp = dkurps; 1462*38624Skarels } 1463*38624Skarels #endif URPDEBUG 1464*38624Skarels #endif 1465