1*6940Ssam /* dmf.c 4.1 82/05/26 */ 2*6940Ssam 3*6940Ssam #include "dmf.h" 4*6940Ssam #if NDMF > 0 5*6940Ssam /* 6*6940Ssam * DMF32 driver 7*6940Ssam * 8*6940Ssam * TODO: 9*6940Ssam * test with modem 10*6940Ssam * load as much as possible into silo 11*6940Ssam * get correct numbers for receive silo parameter timeout 12*6940Ssam * use auto XON/XOFF 13*6940Ssam * test reset code 14*6940Ssam * test with more than one unit 15*6940Ssam * optimize for efficient DMA and dynamically 16*6940Ssam * decide between silo and DMA mode 17*6940Ssam */ 18*6940Ssam #include "bk.h" 19*6940Ssam #include "../h/param.h" 20*6940Ssam #include "../h/conf.h" 21*6940Ssam #include "../h/dir.h" 22*6940Ssam #include "../h/user.h" 23*6940Ssam #include "../h/tty.h" 24*6940Ssam #include "../h/map.h" 25*6940Ssam #include "../h/pte.h" 26*6940Ssam #include "../h/buf.h" 27*6940Ssam #include "../h/vm.h" 28*6940Ssam #include "../h/ubareg.h" 29*6940Ssam #include "../h/ubavar.h" 30*6940Ssam #include "../h/bk.h" 31*6940Ssam #include "../h/clist.h" 32*6940Ssam #include "../h/mx.h" 33*6940Ssam #include "../h/file.h" 34*6940Ssam 35*6940Ssam /* 36*6940Ssam * Definition of the driver for the auto-configuration program. 37*6940Ssam */ 38*6940Ssam int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); 39*6940Ssam struct uba_device *dmfinfo[NDMF]; 40*6940Ssam u_short dmfstd[] = { 0 }; 41*6940Ssam struct uba_driver dmfdriver = 42*6940Ssam { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo }; 43*6940Ssam 44*6940Ssam /* 45*6940Ssam * In this driver, "dmf" (unqualified) refers to the async portion 46*6940Ssam * of the dmf32, "dmfc" to the combo portion, "dmfs" to the sync 47*6940Ssam * portion, "dmfl" to the lp portion, and "dmfd" to the dr portion. 48*6940Ssam */ 49*6940Ssam struct dmfdevice 50*6940Ssam { 51*6940Ssam short dmfccsr0; /* combo csr 0 */ 52*6940Ssam short dmfccsr1; /* combo csr 1 */ 53*6940Ssam short dmfs[4]; 54*6940Ssam short dmfcsr; /* control-status register */ 55*6940Ssam short dmflpr; /* line parameter register */ 56*6940Ssam short dmfrbuf; /* receiver buffer (ro) */ 57*6940Ssam union { 58*6940Ssam u_short dmfirw; /* indirect register word */ 59*6940Ssam u_char dmfirc[2]; /* " " bytes */ 60*6940Ssam } dmfun; 61*6940Ssam short dmfl[2]; 62*6940Ssam short dmfd[4]; 63*6940Ssam }; 64*6940Ssam 65*6940Ssam #define dmfrsp dmfrbuf /* receive silo parameter register (wo) */ 66*6940Ssam #define dmftbuf dmfun.dmfirc[0] /* transmit buffer */ 67*6940Ssam #define dmftsc dmfun.dmfirc[0] /* transmit silo count */ 68*6940Ssam #define dmfrms dmfun.dmfirc[1] /* receive modem status */ 69*6940Ssam #define dmflcr dmfun.dmfirc[0] /* line control register */ 70*6940Ssam #define dmftms dmfun.dmfirc[1] /* transmit modem status */ 71*6940Ssam #define dmftba dmfun.dmfirw /* transmit buffer address */ 72*6940Ssam #define dmftcc dmfun.dmfirw /* transmit character count */ 73*6940Ssam 74*6940Ssam /* bits in dmfcsr */ 75*6940Ssam #define DMF_TI 0100000 /* transmit interrupt */ 76*6940Ssam #define DMF_TIE 0040000 /* transmit interrupt enable */ 77*6940Ssam #define DMF_NXM 0020000 /* non-existant memory */ 78*6940Ssam #define DMF_LIN 0003400 /* transmit line number */ 79*6940Ssam #define DMF_RI 0000200 /* receiver interrupt */ 80*6940Ssam #define DMF_RIE 0000100 /* receiver interrupt enable */ 81*6940Ssam #define DMF_CLR 0000040 /* master reset */ 82*6940Ssam #define DMF_IAD 0000037 /* indirect address register */ 83*6940Ssam 84*6940Ssam #define DMFIR_TBUF 000 /* select tbuf indirect register */ 85*6940Ssam #define DMFIR_LCR 010 /* select lcr indirect register */ 86*6940Ssam #define DMFIR_TBA 020 /* select tba indirect register */ 87*6940Ssam #define DMFIR_TCC 030 /* select tcc indirect register */ 88*6940Ssam 89*6940Ssam /* bits in dmflpr */ 90*6940Ssam #define BITS6 (01<<3) 91*6940Ssam #define BITS7 (02<<3) 92*6940Ssam #define BITS8 (03<<3) 93*6940Ssam #define TWOSB 0200 94*6940Ssam #define PENABLE 040 95*6940Ssam /* DEC manuals incorrectly say this bit causes generation of even parity. */ 96*6940Ssam #define OPAR 0100 97*6940Ssam 98*6940Ssam #define DMF_IE (DMF_TIE|DMF_RIE) 99*6940Ssam 100*6940Ssam #define DMF_SILOCNT 32 /* size of DMF output silo (per line) */ 101*6940Ssam 102*6940Ssam /* bits in dmfrbuf */ 103*6940Ssam #define DMF_DSC 0004000 /* data set change */ 104*6940Ssam #define DMF_PE 0010000 /* parity error */ 105*6940Ssam #define DMF_FE 0020000 /* framing error */ 106*6940Ssam #define DMF_DO 0040000 /* data overrun */ 107*6940Ssam 108*6940Ssam /* bits in dmfrms */ 109*6940Ssam #define DMF_USRR 0004 /* user modem signal (pin 25) */ 110*6940Ssam #define DMF_SR 0010 /* secondary receive */ 111*6940Ssam #define DMF_CTS 0020 /* clear to send */ 112*6940Ssam #define DMF_CAR 0040 /* carrier detect */ 113*6940Ssam #define DMF_RNG 0100 /* ring */ 114*6940Ssam #define DMF_DSR 0200 /* data set ready */ 115*6940Ssam 116*6940Ssam /* bits in dmftms */ 117*6940Ssam #define DMF_USRW 0001 /* user modem signal (pin 18) */ 118*6940Ssam #define DMF_DTR 0002 /* data terminal ready */ 119*6940Ssam #define DMF_RATE 0004 /* data signal rate select */ 120*6940Ssam #define DMF_ST 0010 /* secondary transmit */ 121*6940Ssam #define DMF_RTS 0020 /* request to send */ 122*6940Ssam #define DMF_BRK 0040 /* pseudo break bit */ 123*6940Ssam #define DMF_PREEMPT 0200 /* preempt output */ 124*6940Ssam 125*6940Ssam /* flags for modem control */ 126*6940Ssam #define DMF_ON (DMF_DTR|DMF_RTS) 127*6940Ssam #define DMF_OFF 0 128*6940Ssam 129*6940Ssam /* bits in dmflcr */ 130*6940Ssam #define DMF_MIE 0040 /* modem interrupt enable */ 131*6940Ssam #define DMF_FLUSH 0020 /* flush transmit silo */ 132*6940Ssam #define DMF_RBRK 0010 /* real break bit */ 133*6940Ssam #define DMF_RE 0004 /* receive enable */ 134*6940Ssam #define DMF_AUTOX 0002 /* auto XON/XOFF */ 135*6940Ssam #define DMF_TE 0001 /* transmit enable */ 136*6940Ssam 137*6940Ssam #define DMFLCR_ENA (DMF_MIE|DMF_RE|DMF_TE) 138*6940Ssam 139*6940Ssam /* bits in dm lsr, copied from dh.c */ 140*6940Ssam #define DML_USR 0001000 /* usr modem sig, not a real DM bit */ 141*6940Ssam #define DML_DSR 0000400 /* data set ready, not a real DM bit */ 142*6940Ssam #define DML_RNG 0000200 /* ring */ 143*6940Ssam #define DML_CAR 0000100 /* carrier detect */ 144*6940Ssam #define DML_CTS 0000040 /* clear to send */ 145*6940Ssam #define DML_SR 0000020 /* secondary receive */ 146*6940Ssam #define DML_ST 0000010 /* secondary transmit */ 147*6940Ssam #define DML_RTS 0000004 /* request to send */ 148*6940Ssam #define DML_DTR 0000002 /* data terminal ready */ 149*6940Ssam #define DML_LE 0000001 /* line enable */ 150*6940Ssam 151*6940Ssam /* 152*6940Ssam * Local variables for the driver 153*6940Ssam */ 154*6940Ssam char dmf_speeds[] = 155*6940Ssam { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 }; 156*6940Ssam 157*6940Ssam struct tty dmf_tty[NDMF*8]; 158*6940Ssam char dmfsoftCAR[NDMF]; 159*6940Ssam int ndmf = NDMF*8; 160*6940Ssam int dmfact; /* mask of active dmf's */ 161*6940Ssam int dmfstart(), ttrstrt(); 162*6940Ssam 163*6940Ssam #ifdef DMFDMA 164*6940Ssam /* 165*6940Ssam * The clist space is mapped by the driver onto each UNIBUS. 166*6940Ssam * The UBACVT macro converts a clist space address for unibus uban 167*6940Ssam * into an i/o space address for the DMA routine. 168*6940Ssam */ 169*6940Ssam int dmf_ubinfo[MAXNUBA]; /* info about allocated unibus map */ 170*6940Ssam static int cbase[MAXNUBA]; /* base address in unibus map */ 171*6940Ssam #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) 172*6940Ssam #endif 173*6940Ssam 174*6940Ssam /* 175*6940Ssam * Routine for configuration to set dmf interrupt. 176*6940Ssam */ 177*6940Ssam /*ARGSUSED*/ 178*6940Ssam dmfprobe(reg, ctlr) 179*6940Ssam caddr_t reg; 180*6940Ssam int ctlr; 181*6940Ssam { 182*6940Ssam register int br, cvec; /* these are ``value-result'' */ 183*6940Ssam register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; 184*6940Ssam 185*6940Ssam #ifdef lint 186*6940Ssam br = 0; cvec = br; br = cvec; 187*6940Ssam #endif 188*6940Ssam br = 0x15; 189*6940Ssam cvec = (uba_hd[numuba].uh_lastiv -= 4*8); 190*6940Ssam dmfaddr->dmfccsr0 = cvec >> 2; 191*6940Ssam /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */ 192*6940Ssam return (1); 193*6940Ssam } 194*6940Ssam 195*6940Ssam /* 196*6940Ssam * Routine called to attach a dmf. 197*6940Ssam */ 198*6940Ssam dmfattach(ui) 199*6940Ssam struct uba_device *ui; 200*6940Ssam { 201*6940Ssam 202*6940Ssam dmfsoftCAR[ui->ui_unit] = ui->ui_flags; 203*6940Ssam } 204*6940Ssam 205*6940Ssam 206*6940Ssam /* 207*6940Ssam * Open a DMF32 line, mapping the clist onto the uba if this 208*6940Ssam * is the first dmf on this uba. Turn on this dmf if this is 209*6940Ssam * the first use of it. 210*6940Ssam */ 211*6940Ssam /*ARGSUSED*/ 212*6940Ssam dmfopen(dev, flag) 213*6940Ssam dev_t dev; 214*6940Ssam { 215*6940Ssam register struct tty *tp; 216*6940Ssam register int unit, dmf; 217*6940Ssam register struct dmfdevice *addr; 218*6940Ssam register struct uba_device *ui; 219*6940Ssam int s; 220*6940Ssam 221*6940Ssam unit = minor(dev); 222*6940Ssam dmf = unit >> 3; 223*6940Ssam if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) { 224*6940Ssam u.u_error = ENXIO; 225*6940Ssam return; 226*6940Ssam } 227*6940Ssam tp = &dmf_tty[unit]; 228*6940Ssam if (tp->t_state&XCLUDE && u.u_uid!=0) { 229*6940Ssam u.u_error = EBUSY; 230*6940Ssam return; 231*6940Ssam } 232*6940Ssam addr = (struct dmfdevice *)ui->ui_addr; 233*6940Ssam tp->t_addr = (caddr_t)addr; 234*6940Ssam tp->t_oproc = dmfstart; 235*6940Ssam tp->t_iproc = NULL; 236*6940Ssam tp->t_state |= WOPEN; 237*6940Ssam /* 238*6940Ssam * While setting up state for this uba and this dmf, 239*6940Ssam * block uba resets which can clear the state. 240*6940Ssam */ 241*6940Ssam s = spl5(); 242*6940Ssam #ifdef DMFDMA 243*6940Ssam if (dmf_ubinfo[ui->ui_ubanum] == 0) { 244*6940Ssam dmf_ubinfo[ui->ui_ubanum] = 245*6940Ssam uballoc(ui->ui_ubanum, (caddr_t)cfree, 246*6940Ssam nclist*sizeof(struct cblock), 0); 247*6940Ssam cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff; 248*6940Ssam } 249*6940Ssam #endif 250*6940Ssam if ((dmfact&(1<<dmf)) == 0) { 251*6940Ssam addr->dmfcsr |= DMF_IE; 252*6940Ssam dmfact |= (1<<dmf); 253*6940Ssam addr->dmfrsp = 1; /* DON'T KNOW WHAT TO SET IT TO YET */ 254*6940Ssam } 255*6940Ssam splx(s); 256*6940Ssam /* 257*6940Ssam * If this is first open, initialze tty state to default. 258*6940Ssam */ 259*6940Ssam if ((tp->t_state&ISOPEN) == 0) { 260*6940Ssam ttychars(tp); 261*6940Ssam if (tp->t_ispeed == 0) { 262*6940Ssam tp->t_ispeed = B300; 263*6940Ssam tp->t_ospeed = B300; 264*6940Ssam tp->t_flags = ODDP|EVENP|ECHO; 265*6940Ssam } 266*6940Ssam dmfparam(unit); 267*6940Ssam } 268*6940Ssam /* 269*6940Ssam * Wait for carrier, then process line discipline specific open. 270*6940Ssam */ 271*6940Ssam if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) || 272*6940Ssam (dmfsoftCAR[dmf] & (1<<(unit&07)))) 273*6940Ssam tp->t_state |= CARR_ON; 274*6940Ssam s = spl5(); 275*6940Ssam while ((tp->t_state & CARR_ON) == 0) { 276*6940Ssam tp->t_state |= WOPEN; 277*6940Ssam sleep((caddr_t)&tp->t_rawq, TTIPRI); 278*6940Ssam } 279*6940Ssam splx(s); 280*6940Ssam (*linesw[tp->t_line].l_open)(dev, tp); 281*6940Ssam } 282*6940Ssam 283*6940Ssam /* 284*6940Ssam * Close a DMF32 line. 285*6940Ssam */ 286*6940Ssam /*ARGSUSED*/ 287*6940Ssam dmfclose(dev, flag) 288*6940Ssam dev_t dev; 289*6940Ssam int flag; 290*6940Ssam { 291*6940Ssam register struct tty *tp; 292*6940Ssam register unit; 293*6940Ssam 294*6940Ssam unit = minor(dev); 295*6940Ssam tp = &dmf_tty[unit]; 296*6940Ssam (*linesw[tp->t_line].l_close)(tp); 297*6940Ssam dmfmctl(unit, DMF_BRK, DMBIC); 298*6940Ssam if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0) 299*6940Ssam dmfmctl(unit, DMF_OFF, DMSET); 300*6940Ssam ttyclose(tp); 301*6940Ssam } 302*6940Ssam 303*6940Ssam dmfread(dev) 304*6940Ssam dev_t dev; 305*6940Ssam { 306*6940Ssam register struct tty *tp; 307*6940Ssam 308*6940Ssam tp = &dmf_tty[minor(dev)]; 309*6940Ssam (*linesw[tp->t_line].l_read)(tp); 310*6940Ssam } 311*6940Ssam 312*6940Ssam dmfwrite(dev) 313*6940Ssam dev_t dev; 314*6940Ssam { 315*6940Ssam register struct tty *tp; 316*6940Ssam 317*6940Ssam tp = &dmf_tty[minor(dev)]; 318*6940Ssam (*linesw[tp->t_line].l_write)(tp); 319*6940Ssam } 320*6940Ssam 321*6940Ssam /* 322*6940Ssam * DMF32 receiver interrupt. 323*6940Ssam */ 324*6940Ssam dmfrint(dmf) 325*6940Ssam int dmf; 326*6940Ssam { 327*6940Ssam register struct tty *tp; 328*6940Ssam register c; 329*6940Ssam register struct dmfdevice *addr; 330*6940Ssam register struct tty *tp0; 331*6940Ssam register struct uba_device *ui; 332*6940Ssam int overrun = 0; 333*6940Ssam 334*6940Ssam ui = dmfinfo[dmf]; 335*6940Ssam if (ui == 0 || ui->ui_alive == 0) 336*6940Ssam return; 337*6940Ssam addr = (struct dmfdevice *)ui->ui_addr; 338*6940Ssam tp0 = &dmf_tty[dmf<<3]; 339*6940Ssam /* 340*6940Ssam * Loop fetching characters from the silo for this 341*6940Ssam * dmf until there are no more in the silo. 342*6940Ssam */ 343*6940Ssam while ((c = addr->dmfrbuf) < 0) { 344*6940Ssam tp = tp0 + ((c>>8)&07); 345*6940Ssam if (c & DMF_DSC) { 346*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | ((c>>8)&07); 347*6940Ssam if (addr->dmfrms & DMF_CAR) { 348*6940Ssam if ((tp->t_state & CARR_ON) == 0) { 349*6940Ssam wakeup((caddr_t)&tp->t_rawq); 350*6940Ssam tp->t_state |= CARR_ON; 351*6940Ssam } 352*6940Ssam } else { 353*6940Ssam if (tp->t_state & CARR_ON) { 354*6940Ssam gsignal(tp->t_pgrp, SIGHUP); 355*6940Ssam gsignal(tp->t_pgrp, SIGCONT); 356*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | 357*6940Ssam ((c>>8)&07); 358*6940Ssam addr->dmftms = 0; 359*6940Ssam flushtty(tp, FREAD|FWRITE); 360*6940Ssam } 361*6940Ssam tp->t_state &= ~CARR_ON; 362*6940Ssam } 363*6940Ssam continue; 364*6940Ssam } 365*6940Ssam if ((tp->t_state&ISOPEN)==0) { 366*6940Ssam wakeup((caddr_t)tp); 367*6940Ssam continue; 368*6940Ssam } 369*6940Ssam if (c & DMF_PE) 370*6940Ssam if ((tp->t_flags&(EVENP|ODDP))==EVENP 371*6940Ssam || (tp->t_flags&(EVENP|ODDP))==ODDP ) 372*6940Ssam continue; 373*6940Ssam if ((c & DMF_DO) && overrun == 0) { 374*6940Ssam printf("dmf%d: silo overflow\n", dmf); 375*6940Ssam overrun = 1; 376*6940Ssam } 377*6940Ssam if (c & DMF_FE) 378*6940Ssam /* 379*6940Ssam * At framing error (break) generate 380*6940Ssam * a null (in raw mode, for getty), or a 381*6940Ssam * interrupt (in cooked/cbreak mode). 382*6940Ssam */ 383*6940Ssam if (tp->t_flags&RAW) 384*6940Ssam c = 0; 385*6940Ssam else 386*6940Ssam c = tun.t_intrc; 387*6940Ssam #if NBK > 0 388*6940Ssam if (tp->t_line == NETLDISC) { 389*6940Ssam c &= 0177; 390*6940Ssam BKINPUT(c, tp); 391*6940Ssam } else 392*6940Ssam #endif 393*6940Ssam (*linesw[tp->t_line].l_rint)(c, tp); 394*6940Ssam } 395*6940Ssam } 396*6940Ssam 397*6940Ssam /* 398*6940Ssam * Ioctl for DMF32. 399*6940Ssam */ 400*6940Ssam /*ARGSUSED*/ 401*6940Ssam dmfioctl(dev, cmd, addr, flag) 402*6940Ssam dev_t dev; 403*6940Ssam caddr_t addr; 404*6940Ssam { 405*6940Ssam register struct tty *tp; 406*6940Ssam register int unit = minor(dev); 407*6940Ssam register int dmf = unit >> 3; 408*6940Ssam register struct device *dmfaddr; 409*6940Ssam int temp; 410*6940Ssam 411*6940Ssam tp = &dmf_tty[unit]; 412*6940Ssam cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 413*6940Ssam if (cmd == 0) 414*6940Ssam return; 415*6940Ssam if (ttioctl(tp, cmd, addr, flag)) { 416*6940Ssam if (cmd==TIOCSETP || cmd==TIOCSETN) 417*6940Ssam dmfparam(unit); 418*6940Ssam } else switch(cmd) { 419*6940Ssam 420*6940Ssam case TIOCSBRK: 421*6940Ssam dmfmctl(dev, DMF_BRK, DMBIS); 422*6940Ssam break; 423*6940Ssam case TIOCCBRK: 424*6940Ssam dmfmctl(dev, DMF_BRK, DMBIC); 425*6940Ssam break; 426*6940Ssam case TIOCSDTR: 427*6940Ssam dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); 428*6940Ssam break; 429*6940Ssam case TIOCCDTR: 430*6940Ssam dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); 431*6940Ssam break; 432*6940Ssam case TIOCMSET: 433*6940Ssam if (copyin(addr, (caddr_t) &temp, sizeof(temp))) 434*6940Ssam u.u_error = EFAULT; 435*6940Ssam else 436*6940Ssam dmfmctl(dev, dmtodmf(temp), DMSET); 437*6940Ssam break; 438*6940Ssam case TIOCMBIS: 439*6940Ssam if (copyin(addr, (caddr_t) &temp, sizeof(temp))) 440*6940Ssam u.u_error = EFAULT; 441*6940Ssam else 442*6940Ssam dmfmctl(dev, dmtodmf(temp), DMBIS); 443*6940Ssam break; 444*6940Ssam case TIOCMBIC: 445*6940Ssam if (copyin(addr, (caddr_t) &temp, sizeof(temp))) 446*6940Ssam u.u_error = EFAULT; 447*6940Ssam else 448*6940Ssam dmfmctl(dev, dmtodmf(temp), DMBIC); 449*6940Ssam break; 450*6940Ssam case TIOCMGET: 451*6940Ssam temp = dmftodm(dmfmctl(dev, 0, DMGET)); 452*6940Ssam if (copyout((caddr_t) &temp, addr, sizeof(temp))) 453*6940Ssam u.u_error = EFAULT; 454*6940Ssam break; 455*6940Ssam default: 456*6940Ssam u.u_error = ENOTTY; 457*6940Ssam } 458*6940Ssam } 459*6940Ssam 460*6940Ssam dmtodmf(bits) 461*6940Ssam register int bits; 462*6940Ssam { 463*6940Ssam register int b; 464*6940Ssam 465*6940Ssam b = bits & 012; 466*6940Ssam if (bits & DML_ST) b |= DMF_RATE; 467*6940Ssam if (bits & DML_RTS) b |= DMF_RTS; 468*6940Ssam if (bits & DML_USR) b |= DMF_USRW; 469*6940Ssam return(b); 470*6940Ssam } 471*6940Ssam 472*6940Ssam dmftodm(bits) 473*6940Ssam register int bits; 474*6940Ssam { 475*6940Ssam register int b; 476*6940Ssam 477*6940Ssam b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; 478*6940Ssam if (bits & DMF_USRR) b |= DML_USR; 479*6940Ssam if (bits & DMF_RTS) b |= DML_RTS; 480*6940Ssam return(b); 481*6940Ssam } 482*6940Ssam 483*6940Ssam 484*6940Ssam /* 485*6940Ssam * Set parameters from open or stty into the DMF hardware 486*6940Ssam * registers. 487*6940Ssam */ 488*6940Ssam dmfparam(unit) 489*6940Ssam register int unit; 490*6940Ssam { 491*6940Ssam register struct tty *tp; 492*6940Ssam register struct dmfdevice *addr; 493*6940Ssam register int lpar, lcr; 494*6940Ssam int s; 495*6940Ssam 496*6940Ssam tp = &dmf_tty[unit]; 497*6940Ssam addr = (struct dmfdevice *)tp->t_addr; 498*6940Ssam /* 499*6940Ssam * Block interrupts so parameters will be set 500*6940Ssam * before the line interrupts. 501*6940Ssam */ 502*6940Ssam s = spl5(); 503*6940Ssam addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE; 504*6940Ssam if ((tp->t_ispeed)==0) { 505*6940Ssam tp->t_state |= HUPCLS; 506*6940Ssam dmfmctl(unit, DMF_OFF, DMSET); 507*6940Ssam return; 508*6940Ssam } 509*6940Ssam lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8); 510*6940Ssam lcr = DMFLCR_ENA; 511*6940Ssam if ((tp->t_ispeed) == B134) 512*6940Ssam lpar |= BITS6|PENABLE; 513*6940Ssam else if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT)) 514*6940Ssam lpar |= BITS8; 515*6940Ssam else { 516*6940Ssam lpar |= BITS7|PENABLE; 517*6940Ssam /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */ 518*6940Ssam } 519*6940Ssam if ((tp->t_flags&EVENP) == 0) 520*6940Ssam lpar |= OPAR; 521*6940Ssam if ((tp->t_ospeed) == B110) 522*6940Ssam lpar |= TWOSB; 523*6940Ssam lpar |= (unit&07); 524*6940Ssam addr->dmflpr = lpar; 525*6940Ssam addr->dmflcr = lcr; 526*6940Ssam splx(s); 527*6940Ssam } 528*6940Ssam 529*6940Ssam /* 530*6940Ssam * DMF32 transmitter interrupt. 531*6940Ssam * Restart the idle line. 532*6940Ssam */ 533*6940Ssam dmfxint(dmf) 534*6940Ssam int dmf; 535*6940Ssam { 536*6940Ssam register struct tty *tp; 537*6940Ssam register struct dmfdevice *addr; 538*6940Ssam register struct uba_device *ui; 539*6940Ssam register int unit, t; 540*6940Ssam #ifdef DMFDMA 541*6940Ssam short cntr; 542*6940Ssam #endif 543*6940Ssam 544*6940Ssam ui = dmfinfo[dmf]; 545*6940Ssam addr = (struct dmfdevice *)ui->ui_addr; 546*6940Ssam while ((t = addr->dmfcsr) & DMF_TI) { 547*6940Ssam unit = dmf*8 + ((t>>8)&07); 548*6940Ssam tp = &dmf_tty[unit]; 549*6940Ssam tp->t_state &= ~BUSY; 550*6940Ssam if (t & DMF_NXM) { 551*6940Ssam printf("dmf%d: NXM line %d\n", dmf, unit&7); 552*6940Ssam /* SHOULD RESTART OR SOMETHING... */ 553*6940Ssam } 554*6940Ssam if (tp->t_state&FLUSH) 555*6940Ssam tp->t_state &= ~FLUSH; 556*6940Ssam #ifdef DMFDMA 557*6940Ssam else { 558*6940Ssam addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07); 559*6940Ssam if (addr->dmftsc == 0) { 560*6940Ssam /* 561*6940Ssam * Do arithmetic in a short to make up 562*6940Ssam * for lost 16&17 bits. 563*6940Ssam */ 564*6940Ssam addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07); 565*6940Ssam cntr = addr->dmftba - 566*6940Ssam UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); 567*6940Ssam ndflush(&tp->t_outq, (int)cntr); 568*6940Ssam } 569*6940Ssam } 570*6940Ssam #endif 571*6940Ssam if (tp->t_line) 572*6940Ssam (*linesw[tp->t_line].l_start)(tp); 573*6940Ssam else 574*6940Ssam dmfstart(tp); 575*6940Ssam } 576*6940Ssam } 577*6940Ssam 578*6940Ssam /* 579*6940Ssam * Start (restart) transmission on the given DMF32 line. 580*6940Ssam */ 581*6940Ssam dmfstart(tp) 582*6940Ssam register struct tty *tp; 583*6940Ssam { 584*6940Ssam register struct dmfdevice *addr; 585*6940Ssam register int car, dmf, unit, nch; 586*6940Ssam int s; 587*6940Ssam 588*6940Ssam unit = minor(tp->t_dev); 589*6940Ssam dmf = unit >> 3; 590*6940Ssam unit &= 07; 591*6940Ssam addr = (struct dmfdevice *)tp->t_addr; 592*6940Ssam 593*6940Ssam /* 594*6940Ssam * Must hold interrupts in following code to prevent 595*6940Ssam * state of the tp from changing. 596*6940Ssam */ 597*6940Ssam s = spl5(); 598*6940Ssam /* 599*6940Ssam * If it's currently active, or delaying, no need to do anything. 600*6940Ssam */ 601*6940Ssam if (tp->t_state&(TIMEOUT|BUSY|TTSTOP)) 602*6940Ssam goto out; 603*6940Ssam /* 604*6940Ssam * If there are still characters in the silo, 605*6940Ssam * just reenable the transmitter. 606*6940Ssam */ 607*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 608*6940Ssam if (addr->dmftsc) { 609*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 610*6940Ssam addr->dmflcr |= DMF_TE; 611*6940Ssam tp->t_state |= BUSY; 612*6940Ssam goto out; 613*6940Ssam } 614*6940Ssam /* 615*6940Ssam * If there are sleepers, and output has drained below low 616*6940Ssam * water mark, wake up the sleepers. 617*6940Ssam */ 618*6940Ssam if ((tp->t_state&ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { 619*6940Ssam tp->t_state &= ~ASLEEP; 620*6940Ssam if (tp->t_chan) 621*6940Ssam mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 622*6940Ssam else 623*6940Ssam wakeup((caddr_t)&tp->t_outq); 624*6940Ssam } 625*6940Ssam /* 626*6940Ssam * Now restart transmission unless the output queue is 627*6940Ssam * empty. 628*6940Ssam */ 629*6940Ssam if (tp->t_outq.c_cc == 0) 630*6940Ssam goto out; 631*6940Ssam if (tp->t_flags&RAW || tp->t_local&LLITOUT) 632*6940Ssam nch = ndqb(&tp->t_outq, 0); 633*6940Ssam else { 634*6940Ssam nch = ndqb(&tp->t_outq, 0200); 635*6940Ssam /* 636*6940Ssam * If first thing on queue is a delay process it. 637*6940Ssam */ 638*6940Ssam if (nch == 0) { 639*6940Ssam nch = getc(&tp->t_outq); 640*6940Ssam timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 641*6940Ssam tp->t_state |= TIMEOUT; 642*6940Ssam goto out; 643*6940Ssam } 644*6940Ssam } 645*6940Ssam /* 646*6940Ssam * If characters to transmit, restart transmission. 647*6940Ssam */ 648*6940Ssam if (nch) { 649*6940Ssam #ifdef DMFDMA 650*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 651*6940Ssam addr->dmflcr |= DMF_TE; 652*6940Ssam car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); 653*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBA | unit; 654*6940Ssam addr->dmftba = car; 655*6940Ssam addr->dmftcc = ((car>>2)&0xc000) | nch; 656*6940Ssam #else 657*6940Ssam register char *cp = tp->t_outq.c_cf; 658*6940Ssam register int i; 659*6940Ssam 660*6940Ssam nch = MIN(nch, DMF_SILOCNT); 661*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 662*6940Ssam addr->dmflcr |= DMF_TE; 663*6940Ssam addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 664*6940Ssam for (i = 0; i < nch; i++) 665*6940Ssam addr->dmftbuf = *cp++; 666*6940Ssam ndflush(&tp->t_outq, nch); 667*6940Ssam #endif 668*6940Ssam tp->t_state |= BUSY; 669*6940Ssam } 670*6940Ssam out: 671*6940Ssam splx(s); 672*6940Ssam } 673*6940Ssam 674*6940Ssam /* 675*6940Ssam * Stop output on a line, e.g. for ^S/^Q or output flush. 676*6940Ssam */ 677*6940Ssam /*ARGSUSED*/ 678*6940Ssam dmfstop(tp, flag) 679*6940Ssam register struct tty *tp; 680*6940Ssam { 681*6940Ssam register struct dmfdevice *addr; 682*6940Ssam register int unit, s; 683*6940Ssam 684*6940Ssam addr = (struct dmfdevice *)tp->t_addr; 685*6940Ssam /* 686*6940Ssam * Block input/output interrupts while messing with state. 687*6940Ssam */ 688*6940Ssam s = spl5(); 689*6940Ssam if (tp->t_state & BUSY) { 690*6940Ssam /* 691*6940Ssam * Device is transmitting; stop output 692*6940Ssam * by selecting the line and disabling 693*6940Ssam * the transmitter. If this is a flush 694*6940Ssam * request then flush the output silo, 695*6940Ssam * otherwise we will pick up where we 696*6940Ssam * left off by enabling the transmitter. 697*6940Ssam */ 698*6940Ssam unit = minor(tp->t_dev); 699*6940Ssam addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE; 700*6940Ssam addr->dmflcr &= ~DMF_TE; 701*6940Ssam if ((tp->t_state&TTSTOP)==0) { 702*6940Ssam tp->t_state |= FLUSH; 703*6940Ssam addr->dmflcr |= DMF_FLUSH; 704*6940Ssam } else 705*6940Ssam tp->t_state &= ~BUSY; 706*6940Ssam } 707*6940Ssam splx(s); 708*6940Ssam } 709*6940Ssam 710*6940Ssam /* 711*6940Ssam * DMF32 modem control 712*6940Ssam */ 713*6940Ssam dmfmctl(dev, bits, how) 714*6940Ssam dev_t dev; 715*6940Ssam int bits, how; 716*6940Ssam { 717*6940Ssam register struct dmfdevice *dmfaddr; 718*6940Ssam register int unit, mbits, lcr; 719*6940Ssam int s; 720*6940Ssam 721*6940Ssam unit = minor(dev); 722*6940Ssam dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); 723*6940Ssam unit &= 07; 724*6940Ssam s = spl5(); 725*6940Ssam dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 726*6940Ssam mbits = dmfaddr->dmfrms << 8; 727*6940Ssam dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 728*6940Ssam mbits |= dmfaddr->dmftms; 729*6940Ssam lcr = dmfaddr->dmflcr; 730*6940Ssam switch (how) { 731*6940Ssam case DMSET: 732*6940Ssam mbits = bits; 733*6940Ssam break; 734*6940Ssam 735*6940Ssam case DMBIS: 736*6940Ssam mbits |= bits; 737*6940Ssam break; 738*6940Ssam 739*6940Ssam case DMBIC: 740*6940Ssam mbits &= ~bits; 741*6940Ssam break; 742*6940Ssam 743*6940Ssam case DMGET: 744*6940Ssam (void) splx(s); 745*6940Ssam return(mbits); 746*6940Ssam } 747*6940Ssam dmfaddr->dmftms = mbits&037; 748*6940Ssam if (mbits & DMF_BRK) 749*6940Ssam lcr |= DMF_RBRK; 750*6940Ssam else 751*6940Ssam lcr &= ~DMF_RBRK; 752*6940Ssam dmfaddr->dmflcr = lcr; 753*6940Ssam (void) splx(s); 754*6940Ssam return(mbits); 755*6940Ssam } 756*6940Ssam 757*6940Ssam /* 758*6940Ssam * Reset state of driver if UBA reset was necessary. 759*6940Ssam * Reset the csr, lpr, and lcr registers on open lines, and 760*6940Ssam * restart transmitters. 761*6940Ssam */ 762*6940Ssam dmfreset(uban) 763*6940Ssam int uban; 764*6940Ssam { 765*6940Ssam register int dmf, unit; 766*6940Ssam register struct tty *tp; 767*6940Ssam register struct uba_device *ui; 768*6940Ssam register struct dmfdevice *addr; 769*6940Ssam int i; 770*6940Ssam 771*6940Ssam #ifdef DMFDMA 772*6940Ssam if (dmf_ubinfo[uban] == 0) 773*6940Ssam return; 774*6940Ssam ubarelse(uban, &dmf_ubinfo[uban]); 775*6940Ssam dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, 776*6940Ssam nclist*sizeof (struct cblock), 0); 777*6940Ssam cbase[uban] = dmf_ubinfo[uban]&0x3ffff; 778*6940Ssam #endif 779*6940Ssam for (dmf = 0; dmf < NDMF; dmf++) { 780*6940Ssam ui = dmfinfo[dmf]; 781*6940Ssam if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 782*6940Ssam continue; 783*6940Ssam printf(" dmf%d", dmf); 784*6940Ssam addr = (struct dmfdevice *)ui->ui_addr; 785*6940Ssam addr->dmfcsr = DMF_IE; 786*6940Ssam addr->dmfrsp = 1; 787*6940Ssam unit = dmf * 8; 788*6940Ssam for (i = 0; i < 8; i++) { 789*6940Ssam tp = &dmf_tty[unit]; 790*6940Ssam if (tp->t_state & (ISOPEN|WOPEN)) { 791*6940Ssam dmfparam(unit); 792*6940Ssam dmfmctl(unit, DMF_ON, DMSET); 793*6940Ssam tp->t_state &= ~BUSY; 794*6940Ssam dmfstart(tp); 795*6940Ssam } 796*6940Ssam unit++; 797*6940Ssam } 798*6940Ssam } 799*6940Ssam } 800*6940Ssam 801*6940Ssam /* stubs for interrupt routines for devices not yet supported */ 802*6940Ssam 803*6940Ssam dmfsrint() { printf("dmfsrint\n"); } 804*6940Ssam 805*6940Ssam dmfsxint() { printf("dmfsxint\n"); } 806*6940Ssam 807*6940Ssam dmfdaint() { printf("dmfdaint\n"); } 808*6940Ssam 809*6940Ssam dmfdbint() { printf("dmfdbint\n"); } 810*6940Ssam 811*6940Ssam dmflint() { printf("dmflint\n"); } 812*6940Ssam #endif 813