1*38623Skarels /* 2*38623Skarels * Datakit driver 3*38623Skarels * KMC assistance, with or without DR11C 4*38623Skarels */ 5*38623Skarels 6*38623Skarels #include "dkitkmc.h" 7*38623Skarels #if NDKITKMC>0 8*38623Skarels 9*38623Skarels #include "datakit.h" 10*38623Skarels 11*38623Skarels #include "../machine/pte.h" 12*38623Skarels #include "param.h" 13*38623Skarels #include "syslog.h" 14*38623Skarels #include "time.h" 15*38623Skarels #include "kernel.h" 16*38623Skarels #include "buf.h" 17*38623Skarels #include "mbuf.h" 18*38623Skarels #include "errno.h" 19*38623Skarels #include "socket.h" 20*38623Skarels #include "../net/if.h" 21*38623Skarels #include "../vaxif/if_uba.h" 22*38623Skarels #include "../vaxuba/ubareg.h" 23*38623Skarels #include "../vaxuba/ubavar.h" 24*38623Skarels 25*38623Skarels #include "dkit.h" 26*38623Skarels #include "dkkmc.h" 27*38623Skarels #include "dk.h" 28*38623Skarels 29*38623Skarels #define MONITOR 1 30*38623Skarels 31*38623Skarels #ifdef MONITOR 32*38623Skarels static int dummy ; 33*38623Skarels int *DKP = &dummy ; 34*38623Skarels #define M_ON(a) *DKP |= (a) 35*38623Skarels #define M_OFF(a) *DKP &= ~(a) 36*38623Skarels #define M_TRACE(a) *DKP |= (a);*DKP &= ~(a) 37*38623Skarels 38*38623Skarels #define Mxmit 01 39*38623Skarels #define Mrecv 02 40*38623Skarels #define Mkint 04 41*38623Skarels #define Mint 010 42*38623Skarels #define Mcmd 020 43*38623Skarels 44*38623Skarels #else 45*38623Skarels #define M_ON(a) 46*38623Skarels #define M_OFF(a) 47*38623Skarels #define M_TRACE(a) 48*38623Skarels #endif 49*38623Skarels 50*38623Skarels extern int dk_nchan; 51*38623Skarels 52*38623Skarels struct dkchan dkit[NDATAKIT]; 53*38623Skarels 54*38623Skarels #define DKNCMDB 20 55*38623Skarels #define DKNSTB 20 56*38623Skarels 57*38623Skarels int dkk_ncmd = DKNCMDB; 58*38623Skarels struct dkkin dkkcmdbuf[DKNCMDB]; 59*38623Skarels int dkk_nstat = DKNSTB; 60*38623Skarels struct dkkin dkkstat[DKNSTB]; 61*38623Skarels char dkkbuf[16*1024]; 62*38623Skarels int dkubmbuf; 63*38623Skarels 64*38623Skarels static struct kdevice *dkkaddr; 65*38623Skarels 66*38623Skarels /* 67*38623Skarels * initial information to the KMC 68*38623Skarels */ 69*38623Skarels struct dkinit { 70*38623Skarels caddr_t cmdaddr; /* command buffer */ 71*38623Skarels caddr_t stataddr; /* status buffer */ 72*38623Skarels caddr_t bufaddr ; /* kmc workspace */ 73*38623Skarels caddr_t csraddr; /* for KMC/DR DR register address */ 74*38623Skarels } dkkmcinit; 75*38623Skarels 76*38623Skarels /* 77*38623Skarels * structure of data in first mbuf on chain (type DKM_HDR) 78*38623Skarels * 79*38623Skarels */ 80*38623Skarels struct mpacket { 81*38623Skarels short mp_len; /* Total length left */ 82*38623Skarels char mp_ctl; /* Control character */ 83*38623Skarels int mp_eob; /* Send end-of-block indicator */ 84*38623Skarels int (*mp_endfcn)(); /* End-action function */ 85*38623Skarels caddr_t mp_endparm; /* Parameter to above function */ 86*38623Skarels }; 87*38623Skarels 88*38623Skarels 89*38623Skarels /* 90*38623Skarels * The circular buffer, cmdbuf, is used to pass command to kmc: 91*38623Skarels * while the circular buffer statbuf is used to report status. 92*38623Skarels * There are 8 control and status registers (csr) accessible to 93*38623Skarels * both cpu and kmc. 94*38623Skarels * Csr4-csr5 are used to indicate the head and tail respectively 95*38623Skarels * of the cmdbuf. Likewise, csr6-csr7 for statbuf. 96*38623Skarels * At initialization time, the cpu and kmc would agree on the beginning 97*38623Skarels * address of both buffers and their sizes. 98*38623Skarels */ 99*38623Skarels #define csr0 dkkaddr->un.bsel.bsel0 /* kmc state */ 100*38623Skarels #define csr1 dkkaddr->un.bsel.bsel1 101*38623Skarels #define csr2 dkkaddr->un.bsel.bsel2 /* used at init time, to pass */ 102*38623Skarels #define csr3 dkkaddr->un.bsel.bsel3 /* addresses to the kmc */ 103*38623Skarels #define csr4 dkkaddr->un.bsel.bsel4 /* head cmdbuf */ 104*38623Skarels #define csr5 dkkaddr->un.bsel.bsel5 /* tail cmdbuf */ 105*38623Skarels #define csr6 dkkaddr->un.bsel.bsel6 /* head statbuf */ 106*38623Skarels #define csr7 dkkaddr->un.bsel.bsel7 /* tail statbuf */ 107*38623Skarels 108*38623Skarels 109*38623Skarels /* 110*38623Skarels * kmc device registers 111*38623Skarels */ 112*38623Skarels struct kdevice { 113*38623Skarels union { 114*38623Skarels struct { short sel0, sel2, sel4, sel6;} wsel ; 115*38623Skarels struct { char bsel0, bsel1, bsel2, bsel3; 116*38623Skarels char bsel4, bsel5, bsel6, bsel7; } bsel ; 117*38623Skarels } un; 118*38623Skarels }; 119*38623Skarels 120*38623Skarels 121*38623Skarels /* 122*38623Skarels * For the moment, only support one kmc (kmc0) 123*38623Skarels * More need be done for multiple kmc's 124*38623Skarels */ 125*38623Skarels 126*38623Skarels int dkdebug = 512 ; 127*38623Skarels int dkactive = 0 ; 128*38623Skarels int dkbindex ; 129*38623Skarels static int kseqchk = 0; /* used to check seq. #'s in statbuf */ 130*38623Skarels static int dkpanic = 0; /* # of dk_close(0)'s in this run */ 131*38623Skarels static int kseq = 0; /* # kmc responses mod 0377 */ 132*38623Skarels static int pseq = 0; 133*38623Skarels 134*38623Skarels static struct dkkin *cmd4; /* dkkcmdbuf[csr4] pointer */ 135*38623Skarels static struct dkkin *stat7; /* dkkstat[csr7] pointer */ 136*38623Skarels 137*38623Skarels int dkk_cnt ; 138*38623Skarels static struct uba_device *ui; 139*38623Skarels 140*38623Skarels dkkmc_attach(kui) struct uba_device *kui; 141*38623Skarels { 142*38623Skarels ui = kui; 143*38623Skarels dkk_cnt = kui->ui_unit; 144*38623Skarels } 145*38623Skarels 146*38623Skarels dk_init() 147*38623Skarels { 148*38623Skarels int t, kt ; 149*38623Skarels extern dkkint() ; 150*38623Skarels 151*38623Skarels /* 152*38623Skarels * On the first open of the hardware interface 153*38623Skarels */ 154*38623Skarels if (!ui) return -ENXIO; 155*38623Skarels if (kmcset((dkk_cnt)<<6,03,dkkint)) { 156*38623Skarels /* debug */ log(LOG_ERR, "dkkmcinit bad: kmcset failed\n"); 157*38623Skarels return -1; 158*38623Skarels } 159*38623Skarels dkkaddr = ((struct kdevice *) ui->ui_addr); 160*38623Skarels 161*38623Skarels /* if csr0 != 0, then error 162*38623Skarels else pass the address of struct init 163*38623Skarels in csr2~4 and set csr0 to 1 */ 164*38623Skarels 165*38623Skarels if ((csr0 & 3) != 0) { 166*38623Skarels /* debug */ log(LOG_ERR, "dkkmcinit: csr0 != 0\n"); 167*38623Skarels return EIO; 168*38623Skarels } 169*38623Skarels 170*38623Skarels /* Map UBA registers to point to our stuff */ 171*38623Skarels kt = dk_ubainit(); 172*38623Skarels if (kt == 0) { 173*38623Skarels log(LOG_ERR, "dkkmcinit: no uba resources\n"); 174*38623Skarels return ENOBUFS; 175*38623Skarels } 176*38623Skarels 177*38623Skarels /* Address of DR11-C (if any) */ 178*38623Skarels t = ui->ui_flags & ~03 ; 179*38623Skarels dkkmcinit.csraddr = (caddr_t) ((t<<16) + 3) ; /* bits 17 + 18 must be 1 */ 180*38623Skarels 181*38623Skarels /* append new init info here, if it is needed */ 182*38623Skarels 183*38623Skarels dkkaddr->un.wsel.sel2 = (short)(kt & 0xFFFF); /* bits 0-15 */ 184*38623Skarels dkkaddr->un.bsel.bsel4 = (char)((kt & 0xFF0000) >> 16); /* bits 16-23 */ 185*38623Skarels 186*38623Skarels csr0 = 1; /* tell KMC to read csr2 */ 187*38623Skarels kseq = 0 ; 188*38623Skarels 189*38623Skarels cmd4 = &dkkcmdbuf[0] ; /* driver's pointers into cmdbuf and statbuf */ 190*38623Skarels stat7 = &dkkstat[0] ; 191*38623Skarels dkactive = 1 ; 192*38623Skarels return 0 ; 193*38623Skarels } 194*38623Skarels 195*38623Skarels int dk_ubaed = 0; 196*38623Skarels 197*38623Skarels dk_ubainit() 198*38623Skarels { 199*38623Skarels int t; 200*38623Skarels static int kt; 201*38623Skarels 202*38623Skarels if (dk_ubaed) { 203*38623Skarels if (dkdebug < dk_nchan) 204*38623Skarels log(LOG_ERR, "dk_ubainit: reinit\n"); 205*38623Skarels return kt; 206*38623Skarels } 207*38623Skarels dk_ubaed = 1; 208*38623Skarels 209*38623Skarels /* Initialization buffer */ 210*38623Skarels kt = uballoc(ui->ui_ubanum, (caddr_t) &dkkmcinit, sizeof dkkmcinit, UBA_CANTWAIT); 211*38623Skarels if (kt == 0) return 0; 212*38623Skarels 213*38623Skarels /* Command input buffer */ 214*38623Skarels t = uballoc(ui->ui_ubanum, (caddr_t) dkkcmdbuf, sizeof dkkcmdbuf, UBA_CANTWAIT) ; 215*38623Skarels if (t == 0) return 0; 216*38623Skarels dkkmcinit.cmdaddr = (caddr_t) ((t<<16) + ((t>>16) & 03)); /* must swap bytes for unibus */ 217*38623Skarels 218*38623Skarels /* Status out buffer */ 219*38623Skarels t = uballoc(ui->ui_ubanum, (caddr_t) dkkstat, sizeof dkkstat, UBA_CANTWAIT); 220*38623Skarels if (t == 0) return 0; 221*38623Skarels dkkmcinit.stataddr = (caddr_t) ((t<<16) + ((t>>16) & 03)); 222*38623Skarels 223*38623Skarels /* KMC buffer */ 224*38623Skarels dkubmbuf = uballoc(ui->ui_ubanum, (caddr_t) dkkbuf, sizeof dkkbuf, UBA_CANTWAIT); 225*38623Skarels if (t == 0) return 0; 226*38623Skarels dkkmcinit.bufaddr = (caddr_t) ((dkubmbuf<<16) + ((dkubmbuf>>16) & 03)); 227*38623Skarels if (dkdebug < dk_nchan) 228*38623Skarels log(LOG_ERR, "dk_ubainit: bufaddr %x mapped %x\n", (caddr_t)dkkbuf, 229*38623Skarels dkubmbuf); 230*38623Skarels 231*38623Skarels return kt; 232*38623Skarels } 233*38623Skarels 234*38623Skarels dk_open(chan, supfcn) 235*38623Skarels register chan ; 236*38623Skarels int (*supfcn)() ; 237*38623Skarels { 238*38623Skarels register struct dkchan *dkp; 239*38623Skarels register s ; 240*38623Skarels extern dkkint() ; 241*38623Skarels extern int commchan; 242*38623Skarels int init; 243*38623Skarels 244*38623Skarels if (chan >= dk_nchan) 245*38623Skarels return -ENXIO ; 246*38623Skarels if (dkactive == -1) /* fail request if reset is in progress */ 247*38623Skarels return(-ENETRESET) ; 248*38623Skarels dkp = &dkit[chan] ; 249*38623Skarels s = splimp() ; 250*38623Skarels /* 251*38623Skarels * Channel 0 (0-3 in ISN) is reserved for maintenance. 252*38623Skarels * An open on channel 0 is interpreted as a request 253*38623Skarels * for an unused channel. Channel 1 (4 in ISN or RADIAN) 254*38623Skarels * is the common supervisory channel. 255*38623Skarels */ 256*38623Skarels if (chan == 0) { 257*38623Skarels chan = commchan+1; /* Start above commchan */ 258*38623Skarels while (1) { 259*38623Skarels dkp = &dkit[chan] ; 260*38623Skarels if (dkp->dk_state == 0) 261*38623Skarels break ; 262*38623Skarels chan++ ; 263*38623Skarels if (chan >= dk_nchan) { 264*38623Skarels splx(s) ; 265*38623Skarels return -EADDRNOTAVAIL ; 266*38623Skarels } 267*38623Skarels } 268*38623Skarels } 269*38623Skarels splx(s) ; 270*38623Skarels 271*38623Skarels if (dkactive == 0) 272*38623Skarels if ((init = dk_init()) < 0) 273*38623Skarels return init ; 274*38623Skarels 275*38623Skarels /* 276*38623Skarels * On first use of a channel, we must 277*38623Skarels * allocate per-channel UBA resource for transmit. 278*38623Skarels * Some day, when we convert the receivers to use mbufs, 279*38623Skarels * we'll do the same for reads. 280*38623Skarels * Note that these resources can't easily be freed (I think). 281*38623Skarels */ 282*38623Skarels if (!dkp->dk_uba.ifu_uba) { 283*38623Skarels dkp->dk_uba.ifu_flags = UBA_CANTWAIT; 284*38623Skarels if (if_ubaminit(&dkp->dk_uba.ifu_info, ui->ui_ubanum, 0, 285*38623Skarels btoc(CLBYTES), 286*38623Skarels &dkp->dk_uba.ifu_r, 0, 287*38623Skarels &dkp->dk_uba.ifu_xmt, 1) == 0) { 288*38623Skarels log(LOG_ERR, "dkkmc: no ubamap for channel %d\n", chan); 289*38623Skarels return -ENOBUFS; 290*38623Skarels } 291*38623Skarels dkp->dk_outq.ifq_maxlen = 20; 292*38623Skarels } 293*38623Skarels 294*38623Skarels /* 295*38623Skarels * Finish setting up dkp struct. 296*38623Skarels */ 297*38623Skarels if ((dkp->dk_state & DK_OPEN) ==0) { 298*38623Skarels dkcmd(KC_XINIT, chan, (caddr_t)0, (unsigned) 0, 0, 0) ; 299*38623Skarels flushall(dkp, 0); 300*38623Skarels dkp->dk_state |= DK_OPEN; 301*38623Skarels dkp->dk_state &= ~DK_LINGR; 302*38623Skarels dkactive++ ; 303*38623Skarels } 304*38623Skarels dkp->dk_supfcn = supfcn ; 305*38623Skarels return chan ; 306*38623Skarels } 307*38623Skarels 308*38623Skarels 309*38623Skarels /* 310*38623Skarels * Close a channel: 311*38623Skarels */ 312*38623Skarels 313*38623Skarels dk_close(chan) 314*38623Skarels { 315*38623Skarels register struct dkchan *dkp; 316*38623Skarels register s ; 317*38623Skarels int init; 318*38623Skarels 319*38623Skarels if (dkkaddr == 0) return(-ENODEV); /* if no init, can't close */ 320*38623Skarels /* ie: can't do dkmaint */ 321*38623Skarels 322*38623Skarels s = splimp() ; 323*38623Skarels dkp = &dkit[chan] ; 324*38623Skarels if (chan == 0) { 325*38623Skarels for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) { 326*38623Skarels if (dkp->dk_state & (DK_OPEN|DK_BUSY|DK_RCV)) { 327*38623Skarels dkp->dk_state |= DK_RESET ; 328*38623Skarels flushall(dkp, 0) ; 329*38623Skarels dkp->dk_state = DK_RESET ; 330*38623Skarels } 331*38623Skarels } 332*38623Skarels dkpanic++ ; 333*38623Skarels kseq = 0 ; 334*38623Skarels pseq = 0 ; 335*38623Skarels #ifdef notdef 336*38623Skarels if(dkubmbuf){ /* only deallocate mem if still allocated */ 337*38623Skarels ubarelse(ui->ui_ubanum, &dkubmbuf); 338*38623Skarels dkubmbuf = NULL; 339*38623Skarels } 340*38623Skarels #endif 341*38623Skarels /* wait for protocols to close channels */ 342*38623Skarels dkactive = -1 ; 343*38623Skarels DELAY(4 * hz) ; 344*38623Skarels /* do a dk_free for all channels */ 345*38623Skarels for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) { 346*38623Skarels dkp->dk_state &= ~DK_LINGR ; 347*38623Skarels } 348*38623Skarels dkactive = 0 ; 349*38623Skarels csr0 = 0 ; /* set kmc to idle mode */ 350*38623Skarels if ((init = dk_init()) < 0) { 351*38623Skarels splx(s) ; 352*38623Skarels return init ; 353*38623Skarels } 354*38623Skarels } else { 355*38623Skarels flushall(dkp, 0) ; 356*38623Skarels dkp->dk_state = DK_LINGR ; /* set while UNIXP protocol 357*38623Skarels closes up channel with DK */ 358*38623Skarels } 359*38623Skarels splx(s) ; 360*38623Skarels return 0; 361*38623Skarels } 362*38623Skarels 363*38623Skarels 364*38623Skarels 365*38623Skarels 366*38623Skarels /* 367*38623Skarels * Close phase 2 - mark available for reassignment 368*38623Skarels */ 369*38623Skarels dk_free(chan) 370*38623Skarels { 371*38623Skarels if (chan > dkdebug) 372*38623Skarels log(LOG_ERR, "dk_free %d\n", chan) ; 373*38623Skarels dkit[chan].dk_state &= ~DK_LINGR ; 374*38623Skarels } 375*38623Skarels 376*38623Skarels 377*38623Skarels /* 378*38623Skarels * Reset a channel 379*38623Skarels * prevents further I/O until close 380*38623Skarels */ 381*38623Skarels dk_reset(chan) 382*38623Skarels { 383*38623Skarels register struct dkchan *dkp ; 384*38623Skarels register s ; 385*38623Skarels 386*38623Skarels if (chan > dkdebug) 387*38623Skarels log(LOG_ERR, "dk_reset %d\n", chan) ; 388*38623Skarels s = splimp() ; 389*38623Skarels dkp = &dkit[chan] ; 390*38623Skarels dkp->dk_state |= DK_RESET ; 391*38623Skarels flushall(dkp, 0) ; 392*38623Skarels splx(s) ; 393*38623Skarels } 394*38623Skarels 395*38623Skarels 396*38623Skarels 397*38623Skarels /* 398*38623Skarels * Xmit a short control (interrupt) packet (max 2 bytes) 399*38623Skarels */ 400*38623Skarels dk_xint(chan, intr) 401*38623Skarels { 402*38623Skarels register s ; 403*38623Skarels 404*38623Skarels s = splimp() ; 405*38623Skarels dkcmd(KC_SOI, chan, (caddr_t)0, (unsigned) intr, 0, 0) ; 406*38623Skarels splx(s) ; 407*38623Skarels return 0 ; 408*38623Skarels } 409*38623Skarels 410*38623Skarels 411*38623Skarels /* 412*38623Skarels * Adjust window size 413*38623Skarels */ 414*38623Skarels /*ARGSUSED*/ 415*38623Skarels dk_winsize(chan, win) 416*38623Skarels struct diocxwin *win; 417*38623Skarels { 418*38623Skarels return EINVAL; /* For now... */ 419*38623Skarels } 420*38623Skarels 421*38623Skarels 422*38623Skarels 423*38623Skarels /* 424*38623Skarels * Xmit data on a channel 425*38623Skarels */ 426*38623Skarels dk_xmit(chan, m, eob, ctlchar, endfcn, endparm) 427*38623Skarels struct mbuf *m ; 428*38623Skarels int (*endfcn)() ; 429*38623Skarels caddr_t endparm ; 430*38623Skarels { 431*38623Skarels register struct dkchan *dkp ; 432*38623Skarels short s ; 433*38623Skarels register struct mpacket *mbp ; 434*38623Skarels register struct mbuf *mb; 435*38623Skarels int len; 436*38623Skarels 437*38623Skarels M_ON(Mxmit) ; 438*38623Skarels s = splimp() ; 439*38623Skarels dkp = &dkit[chan] ; 440*38623Skarels if ((dkp->dk_state & DK_RESET) || (mb = m_get(M_DONTWAIT,DKMT_HDR)) == NULL) { 441*38623Skarels m_freem(m); 442*38623Skarels splx(s) ; 443*38623Skarels return 0 ; 444*38623Skarels } 445*38623Skarels 446*38623Skarels mb->m_len = 0; 447*38623Skarels mbp = mtod(mb, struct mpacket *); 448*38623Skarels mbp->mp_endfcn = endfcn ; 449*38623Skarels mbp->mp_endparm = endparm ; 450*38623Skarels mbp->mp_eob = eob; 451*38623Skarels mbp->mp_ctl = ctlchar; 452*38623Skarels 453*38623Skarels if ((dkp->dk_state & DK_BUSY) == 0) { 454*38623Skarels dkp->dk_state |= DK_BUSY ; 455*38623Skarels dkp->dk_obuf = mbp ; 456*38623Skarels mb->m_next = NULL; 457*38623Skarels len = if_wubaput(&dkp->dk_uba, m); 458*38623Skarels dkcmd(KC_SEND, chan, (caddr_t) UBAI_ADDR(dkp->dk_uba.ifu_w.ifrw_info), 459*38623Skarels (unsigned) len, eob ? SBOT : SBOTM, ctlchar) ; 460*38623Skarels splx(s) ; 461*38623Skarels M_OFF(Mxmit) ; 462*38623Skarels return dkp->dk_state ; 463*38623Skarels } 464*38623Skarels 465*38623Skarels mb->m_next = m; 466*38623Skarels if (IF_QFULL(&dkp->dk_outq)) { 467*38623Skarels IF_DROP(&dkp->dk_outq); 468*38623Skarels m_freem(mb); 469*38623Skarels } 470*38623Skarels else 471*38623Skarels IF_ENQUEUE(&dkp->dk_outq, mb); 472*38623Skarels splx(s) ; 473*38623Skarels M_OFF(Mxmit) ; 474*38623Skarels return dkp->dk_state ; 475*38623Skarels } 476*38623Skarels 477*38623Skarels /* 478*38623Skarels * Receive into a block buffer 479*38623Skarels */ 480*38623Skarels dk_recv(chan, addr, len, mode, endfcn, endparm) 481*38623Skarels int len; 482*38623Skarels int (*endfcn)() ; 483*38623Skarels caddr_t addr, endparm ; 484*38623Skarels { 485*38623Skarels register struct dkchan *dkp ; 486*38623Skarels int s; 487*38623Skarels 488*38623Skarels s = splimp() ; 489*38623Skarels M_ON(Mrecv) ; 490*38623Skarels dkp = &dkit[chan] ; 491*38623Skarels if (dkp->dk_state & (DK_RCV | DK_RESET)) { 492*38623Skarels splx(s) ; 493*38623Skarels return(0) ; 494*38623Skarels } 495*38623Skarels dkp->dk_ubmbase = uballoc(ui->ui_ubanum, addr, len, UBA_CANTWAIT); 496*38623Skarels if (dkp->dk_ubmbase == NULL) { 497*38623Skarels splx(s) ; 498*38623Skarels return(0) ; 499*38623Skarels } 500*38623Skarels dkp->dk_state |= DK_RCV ; 501*38623Skarels dkp->dk_endfcn = endfcn ; 502*38623Skarels dkp->dk_endparm = endparm ; 503*38623Skarels dkp->dk_rlen = len; 504*38623Skarels dkcmd(KC_RCVB, chan, (caddr_t) UBAI_ADDR(dkp->dk_ubmbase), (unsigned) len, mode&0377, mode>>8); 505*38623Skarels M_OFF(Mrecv) ; 506*38623Skarels splx(s); 507*38623Skarels return dkp->dk_state ; 508*38623Skarels } 509*38623Skarels 510*38623Skarels /* Abort pending receive */ 511*38623Skarels 512*38623Skarels 513*38623Skarels dk_rabort(chan, nendfcn, nendparm) 514*38623Skarels int (*nendfcn)() ; 515*38623Skarels caddr_t nendparm; 516*38623Skarels { 517*38623Skarels register struct dkchan *dkp ; 518*38623Skarels register s ; 519*38623Skarels 520*38623Skarels dkp = &dkit[chan] ; 521*38623Skarels s = splimp() ; 522*38623Skarels if (dkp->dk_state & DK_RCV) { /* cancel outstanding receive */ 523*38623Skarels dkcmd(KC_RCVB, chan, (caddr_t)0, (unsigned) 0, 0, 0) ; 524*38623Skarels dkp->dk_endfcn = nendfcn ; 525*38623Skarels dkp->dk_endparm = nendparm ; 526*38623Skarels } 527*38623Skarels splx(s) ; 528*38623Skarels return dkp->dk_state ; 529*38623Skarels } 530*38623Skarels 531*38623Skarels 532*38623Skarels 533*38623Skarels dk_status(chan) 534*38623Skarels { 535*38623Skarels if (chan >= dk_nchan) 536*38623Skarels return 0 ; 537*38623Skarels return dkit[chan].dk_state ; 538*38623Skarels } 539*38623Skarels 540*38623Skarels 541*38623Skarels /* 542*38623Skarels * Various control commands to KMC 543*38623Skarels */ 544*38623Skarels dk_cmd(chan, cmd) 545*38623Skarels { 546*38623Skarels register struct dkchan *dkp ; 547*38623Skarels register s ; 548*38623Skarels 549*38623Skarels dkp = &dkit[chan] ; 550*38623Skarels if (cmd & (DKC_XINIT|DKC_FLUSH)) { 551*38623Skarels /*for either command do the same thing: 552*38623Skarels * reinit the transmitter and flush any pending output. 553*38623Skarels * NOTE: for the kmc, there is no response to XINIT 554*38623Skarels * and no send complete for flush 555*38623Skarels */ 556*38623Skarels s = splimp() ; 557*38623Skarels dkcmd(KC_XINIT, chan, (caddr_t)0, (unsigned) 0, 0, 0) ; 558*38623Skarels flushall(dkp, -1) ; 559*38623Skarels dkcmd(KC_CMD, chan, (caddr_t)0, (unsigned) DKC_FLUSH, 0, 0) ; 560*38623Skarels splx(s); 561*38623Skarels cmd &= ~(DKC_XINIT|DKC_FLUSH) ; 562*38623Skarels } 563*38623Skarels if (cmd) 564*38623Skarels dkcmd(KC_CMD, chan, (caddr_t)0, (unsigned) cmd, 0, 0) ; 565*38623Skarels } 566*38623Skarels 567*38623Skarels 568*38623Skarels /* 569*38623Skarels * Note that flushall is often recursive when a tty driver 570*38623Skarels * is involved. 571*38623Skarels */ 572*38623Skarels 573*38623Skarels static 574*38623Skarels flushall(dkp, rwflag) 575*38623Skarels register struct dkchan *dkp ; 576*38623Skarels { 577*38623Skarels register s ; 578*38623Skarels register struct mpacket *mbp ; 579*38623Skarels int (*endfcn)(); 580*38623Skarels 581*38623Skarels s = splimp() ; 582*38623Skarels if ((dkp->dk_state & DK_RCV) && (rwflag >= 0)) { 583*38623Skarels dkcmd(KC_RCVB, dkp-dkit, (caddr_t)0, (unsigned) 0, 0, 0) ; 584*38623Skarels dkp->dk_state &= ~DK_RCV ; 585*38623Skarels if (dkp->dk_ubmbase) { 586*38623Skarels ubarelse(ui->ui_ubanum, &dkp->dk_ubmbase); 587*38623Skarels dkp->dk_ubmbase = NULL; 588*38623Skarels } 589*38623Skarels if (endfcn = dkp->dk_endfcn) { 590*38623Skarels dkp->dk_endfcn = NULL ; 591*38623Skarels (*endfcn)(dkp->dk_endparm, dkp-dkit, dkp->dk_rlen, DKR_ABORT, 0) ; 592*38623Skarels } 593*38623Skarels } 594*38623Skarels 595*38623Skarels /* flush all writes current and pending */ 596*38623Skarels 597*38623Skarels if ((dkp->dk_state & DK_BUSY) && (rwflag <= 0)) { 598*38623Skarels register struct mbuf *m ; 599*38623Skarels 600*38623Skarels /* flush current write */ 601*38623Skarels if (mbp = dkp->dk_obuf) { 602*38623Skarels dkp->dk_obuf = NULL; 603*38623Skarels if (endfcn = mbp->mp_endfcn) { 604*38623Skarels mbp->mp_endfcn = NULL; 605*38623Skarels (endfcn)(mbp->mp_endparm, dkp-dkit); 606*38623Skarels } 607*38623Skarels m_free(dtom(mbp)); 608*38623Skarels } 609*38623Skarels /* flush any pending writes which may be queued up */ 610*38623Skarels while (1) { 611*38623Skarels IF_DEQUEUE(&dkp->dk_outq, m); 612*38623Skarels if (!m) break; 613*38623Skarels mbp = mtod(m, struct mpacket *); 614*38623Skarels if (endfcn = mbp->mp_endfcn) { 615*38623Skarels mbp->mp_endfcn = NULL; 616*38623Skarels (endfcn)(mbp->mp_endparm, dkp-dkit); 617*38623Skarels } 618*38623Skarels m_freem(m); 619*38623Skarels } 620*38623Skarels /* mark channel as not busy */ 621*38623Skarels dkp->dk_state &= ~DK_BUSY ; 622*38623Skarels } 623*38623Skarels if ((dkp->dk_state & DK_OPEN) && (rwflag >= 0)) { 624*38623Skarels dkcmd(KC_CLOSE, dkp-dkit, (caddr_t)0, (unsigned) 0, 0, 0) ; 625*38623Skarels if (dkp->dk_state & DK_BUSY){ 626*38623Skarels mbp = dkp->dk_obuf; 627*38623Skarels dkp->dk_obuf = NULL; 628*38623Skarels if (endfcn = mbp->mp_endfcn) { 629*38623Skarels mbp->mp_endfcn = NULL; 630*38623Skarels (endfcn)(mbp->mp_endparm, dkp-dkit); 631*38623Skarels } 632*38623Skarels m_free(dtom(mbp)); 633*38623Skarels dkp->dk_state &= ~DK_BUSY ; 634*38623Skarels } 635*38623Skarels } 636*38623Skarels splx(s) ; 637*38623Skarels } 638*38623Skarels 639*38623Skarels 640*38623Skarels short dup_count = 0; /* counter for number of duplicate sends */ 641*38623Skarels 642*38623Skarels /* 643*38623Skarels * Routine to handle interrupts from the KMC 644*38623Skarels * 645*38623Skarels * This routine is called when 646*38623Skarels * the KMC generates an unsolicited interrupt (VEC4 == 1) 647*38623Skarels * 648*38623Skarels * These interrupts are used by the KMC to notify dkit_kmc.c 649*38623Skarels * of events such as output buffer completions 650*38623Skarels * csr6 & csr7 point to dkkstat 651*38623Skarels */ 652*38623Skarels dkkint() 653*38623Skarels { 654*38623Skarels register struct dkchan *dkp; 655*38623Skarels register struct dkkin *sp; 656*38623Skarels register chan; 657*38623Skarels struct mpacket *mbp ; 658*38623Skarels int (*endfcn)(); 659*38623Skarels 660*38623Skarels M_ON(Mkint) ; 661*38623Skarels 662*38623Skarels chan = csr0 ; /* temp for cc -O bug */ 663*38623Skarels if((chan & 01) == 1) /* 1 or 3 -> ignore */ 664*38623Skarels return; 665*38623Skarels sp = stat7 ; /* next response to be processed */ 666*38623Skarels while (csr6 != csr7) { 667*38623Skarels if (kseqchk) 668*38623Skarels if ((((sp->k_chan >> 8)&0377) != kseq) || 669*38623Skarels (((sp->k_type >> 8)&0377) != kseq)) { 670*38623Skarels log(LOG_ERR, "dkkint: kseq %x chan %d type %x\n", 671*38623Skarels kseq, sp->k_chan, sp->k_type) ; 672*38623Skarels goto reset ; 673*38623Skarels } 674*38623Skarels kseq = (kseq + 1) & 0377 ; 675*38623Skarels sp->k_addr = pseq ; 676*38623Skarels pseq++ ; 677*38623Skarels chan = sp->k_chan & 0377 ; /* mask off seq. # */ 678*38623Skarels dkp = &dkit[chan]; 679*38623Skarels if (chan > dkdebug) { 680*38623Skarels log(LOG_ERR, " dkkint: head %d tail %d", csr6, csr7) ; 681*38623Skarels log(LOG_ERR, " type %x chan %d len %d mode %x ctl %x\n", sp->k_type&0377, sp->k_chan&0377, sp->k_len, sp->k_mode, sp->k_ctl) ; 682*38623Skarels } 683*38623Skarels switch(sp->k_type & 0377) { 684*38623Skarels case KS_CNTL: 685*38623Skarels if (dkp->dk_supfcn) 686*38623Skarels (*dkp->dk_supfcn)(chan, sp->k_ctl) ; 687*38623Skarels break ; 688*38623Skarels case KS_EOI: 689*38623Skarels break ; 690*38623Skarels case KS_SEND: 691*38623Skarels mbp = dkp->dk_obuf ; 692*38623Skarels if (mbp == NULL) { 693*38623Skarels if (dkp->dk_state & (DK_RESET|DK_LINGR)) 694*38623Skarels break; /* flushall was already called */ 695*38623Skarels log(LOG_ERR, "dkkint: xbufout chan %d state %x\n", chan, dkp->dk_state) ; 696*38623Skarels log(LOG_ERR, "head %d tail %d", csr6, csr7) ; 697*38623Skarels log(LOG_ERR, " type %x len %d mode %x ctl %x\n", 698*38623Skarels sp->k_type&0377, sp->k_len, sp->k_mode, sp->k_ctl) ; 699*38623Skarels break ; 700*38623Skarels } 701*38623Skarels dkp->dk_state &= ~DK_BUSY; 702*38623Skarels dkp->dk_obuf = NULL ; 703*38623Skarels if (endfcn = mbp->mp_endfcn) { 704*38623Skarels mbp->mp_endfcn = NULL; 705*38623Skarels (endfcn)(mbp->mp_endparm, chan) ; 706*38623Skarels } 707*38623Skarels m_free(dtom(mbp)) ; 708*38623Skarels if (dkp->dk_uba.ifu_xtofree) { 709*38623Skarels m_freem(dkp->dk_uba.ifu_xtofree); 710*38623Skarels dkp->dk_uba.ifu_xtofree = 0; 711*38623Skarels } 712*38623Skarels if (dkp->dk_outq.ifq_head) 713*38623Skarels dkstart(dkp) ; 714*38623Skarels break; 715*38623Skarels case KS_RDB: 716*38623Skarels if (((dkp->dk_state & DK_RCV) == 0) && dkp->dk_endfcn) { 717*38623Skarels log(LOG_ERR, "dkkint: rbufin chan %d state %x\n", chan, dkp->dk_state) ; 718*38623Skarels log(LOG_ERR, " head %d tail %d\n", csr6, csr7) ; 719*38623Skarels log(LOG_ERR, " type %x len %d mode %x ctl %x\n", 720*38623Skarels sp->k_type&0377, sp->k_len, sp->k_mode, sp->k_ctl) ; 721*38623Skarels 722*38623Skarels if (sp->k_ctl) 723*38623Skarels break ; 724*38623Skarels else { 725*38623Skarels stat7 = sp ; /* save it for dump */ 726*38623Skarels csr0 = 3 ; /* stop KMC */ 727*38623Skarels panic("") ; /* KMC probably wrote 728*38623Skarels into a mbuf we don't own */ 729*38623Skarels } 730*38623Skarels } 731*38623Skarels dkp->dk_state &= ~DK_RCV ; 732*38623Skarels if (dkp->dk_ubmbase) { 733*38623Skarels ubarelse(ui->ui_ubanum, &dkp->dk_ubmbase); 734*38623Skarels dkp->dk_ubmbase = NULL; 735*38623Skarels } 736*38623Skarels if (endfcn = dkp->dk_endfcn) { 737*38623Skarels dkp->dk_endfcn = NULL; 738*38623Skarels (endfcn)(dkp->dk_endparm, chan, sp->k_len, sp->k_mode, sp->k_ctl) ; 739*38623Skarels } 740*38623Skarels break; 741*38623Skarels case KS_ERR: 742*38623Skarels log(LOG_ERR, "dkkint: err : chan %d, code %x\nchead: %d, ctail: %d, rhead: %d, rtail: %d\n", 743*38623Skarels chan, sp->k_len, csr4, csr5, csr6, csr7); 744*38623Skarels 745*38623Skarels /* if error is duplicate send, only close that chan, */ 746*38623Skarels /* not the whole interface */ 747*38623Skarels 748*38623Skarels if (sp->k_len == E_DUP) { 749*38623Skarels dup_count++; 750*38623Skarels if (dkp->dk_state & DK_OPEN) { 751*38623Skarels dk_reset(chan); 752*38623Skarels } 753*38623Skarels break; 754*38623Skarels } 755*38623Skarels reset: 756*38623Skarels (void) dk_close(0) ; 757*38623Skarels return ; 758*38623Skarels default: 759*38623Skarels log(LOG_ERR, "dkkint: chan %d, type %x, len %d, ctl %x, mode %x\n", 760*38623Skarels chan, sp->k_type&0377, sp->k_len, sp->k_ctl, sp->k_mode); 761*38623Skarels goto reset ; 762*38623Skarels } /* end switch */ 763*38623Skarels 764*38623Skarels if (csr7 == dkk_nstat-1) { 765*38623Skarels csr7 = 0 ; 766*38623Skarels sp = &dkkstat[0] ; 767*38623Skarels } else { 768*38623Skarels csr7++ ; 769*38623Skarels sp++ ; 770*38623Skarels } 771*38623Skarels 772*38623Skarels } /* end while */ 773*38623Skarels stat7 = sp ; 774*38623Skarels M_OFF(Mkint) ; 775*38623Skarels } 776*38623Skarels 777*38623Skarels /* 778*38623Skarels * Start (Restart) transmission on the given line 779*38623Skarels */ 780*38623Skarels dkstart(dkp) 781*38623Skarels register struct dkchan *dkp; 782*38623Skarels { 783*38623Skarels register struct mpacket *mbp; 784*38623Skarels register struct mbuf *m; 785*38623Skarels int len; 786*38623Skarels 787*38623Skarels /* 788*38623Skarels * If it is currently active, just return 789*38623Skarels */ 790*38623Skarels if (dkp->dk_state&DK_BUSY) 791*38623Skarels return; 792*38623Skarels 793*38623Skarels IF_DEQUEUE(&dkp->dk_outq, m); 794*38623Skarels if (!m) 795*38623Skarels return; 796*38623Skarels mbp = mtod(m, struct mpacket *); 797*38623Skarels 798*38623Skarels dkp->dk_state |= DK_BUSY ; 799*38623Skarels dkp->dk_obuf = mbp ; 800*38623Skarels len = if_wubaput(&dkp->dk_uba, m->m_next); 801*38623Skarels dkcmd(KC_SEND, dkp-dkit, (caddr_t) UBAI_ADDR(dkp->dk_uba.ifu_w.ifrw_info), 802*38623Skarels (unsigned) len, mbp->mp_eob ? SBOT : SBOTM, mbp->mp_ctl) ; 803*38623Skarels } 804*38623Skarels 805*38623Skarels /* 806*38623Skarels * Put command in dkkcmdbuf which is pointed by csr4~5 807*38623Skarels */ 808*38623Skarels dkcmd(type, chan, addr, len, mode, ctl) 809*38623Skarels int type, chan; 810*38623Skarels caddr_t addr ; 811*38623Skarels unsigned len ; 812*38623Skarels { 813*38623Skarels register struct dkkin *sp; 814*38623Skarels register s; 815*38623Skarels register next; 816*38623Skarels struct timeval tv1, tv2; 817*38623Skarels 818*38623Skarels M_ON(Mcmd) ; 819*38623Skarels s = csr0 ; 820*38623Skarels if ((s & 3) != 2) 821*38623Skarels return; 822*38623Skarels 823*38623Skarels s = splimp(); 824*38623Skarels next = (csr4+1)%dkk_ncmd; 825*38623Skarels if (csr5 == next) { 826*38623Skarels struct dkchan *dkp; 827*38623Skarels 828*38623Skarels csr0 = 3; 829*38623Skarels for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) 830*38623Skarels if (dkp->dk_state & (DK_OPEN|DK_BUSY|DK_RCV)) 831*38623Skarels dkp->dk_state |= DK_RESET; 832*38623Skarels splx(s); 833*38623Skarels log(LOG_ERR, "KMC RESET\n"); 834*38623Skarels return; 835*38623Skarels } 836*38623Skarels 837*38623Skarels sp = cmd4 ; 838*38623Skarels sp->k_type = type | ((pseq&0177)<<9) ; 839*38623Skarels sp->k_chan = chan | ((kseq&0377)<<8) ; 840*38623Skarels sp->k_addr = ((int)addr << 16) + ((int)addr >> 16) ; 841*38623Skarels sp->k_len = len ; 842*38623Skarels sp->k_mode = mode ; 843*38623Skarels sp->k_ctl = ctl ; 844*38623Skarels pseq++ ; 845*38623Skarels 846*38623Skarels csr4 = next; 847*38623Skarels cmd4 = &dkkcmdbuf[next]; 848*38623Skarels 849*38623Skarels if (chan > dkdebug) { 850*38623Skarels log(LOG_ERR, " dkcmd: head %d, tail %d", csr4, csr5); 851*38623Skarels log(LOG_ERR, " type %x, chan %d, addr %x, len %d", 852*38623Skarels type, chan, addr, len); 853*38623Skarels log(LOG_ERR, " mode %x, ctl %x\n", mode, ctl); 854*38623Skarels } 855*38623Skarels splx(s) ; 856*38623Skarels M_OFF(Mcmd) ; 857*38623Skarels } 858*38623Skarels 859*38623Skarels #endif 860