1*41480Smckusick /* 2*41480Smckusick * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 3*41480Smckusick * All rights reserved. 4*41480Smckusick * 5*41480Smckusick * %sccs.include.redist.c% 6*41480Smckusick * 7*41480Smckusick * @(#)dca.c 7.1 (Berkeley) 05/08/90 8*41480Smckusick */ 9*41480Smckusick 10*41480Smckusick #include "dca.h" 11*41480Smckusick #if NDCA > 0 12*41480Smckusick /* 13*41480Smckusick * 98626/98644/internal serial interface 14*41480Smckusick */ 15*41480Smckusick #include "param.h" 16*41480Smckusick #include "systm.h" 17*41480Smckusick #include "ioctl.h" 18*41480Smckusick #include "tty.h" 19*41480Smckusick #include "user.h" 20*41480Smckusick #include "conf.h" 21*41480Smckusick #include "file.h" 22*41480Smckusick #include "uio.h" 23*41480Smckusick #include "kernel.h" 24*41480Smckusick #include "syslog.h" 25*41480Smckusick 26*41480Smckusick #include "device.h" 27*41480Smckusick #include "dcareg.h" 28*41480Smckusick #include "machine/cpu.h" 29*41480Smckusick #include "machine/isr.h" 30*41480Smckusick 31*41480Smckusick int dcaprobe(); 32*41480Smckusick struct driver dcadriver = { 33*41480Smckusick dcaprobe, "dca", 34*41480Smckusick }; 35*41480Smckusick 36*41480Smckusick int dcastart(), dcaparam(), dcaintr(); 37*41480Smckusick int dcasoftCAR; 38*41480Smckusick int dca_active; 39*41480Smckusick int ndca = NDCA; 40*41480Smckusick int dcaconsole = -1; 41*41480Smckusick int dcadefaultrate = TTYDEF_SPEED; 42*41480Smckusick struct dcadevice *dca_addr[NDCA]; 43*41480Smckusick struct tty dca_tty[NDCA]; 44*41480Smckusick struct isr dcaisr[NDCA]; 45*41480Smckusick 46*41480Smckusick struct speedtab dcaspeedtab[] = { 47*41480Smckusick 0, 0, 48*41480Smckusick 50, DCABRD(50), 49*41480Smckusick 75, DCABRD(75), 50*41480Smckusick 110, DCABRD(110), 51*41480Smckusick 134, DCABRD(134), 52*41480Smckusick 150, DCABRD(150), 53*41480Smckusick 200, DCABRD(200), 54*41480Smckusick 300, DCABRD(300), 55*41480Smckusick 600, DCABRD(600), 56*41480Smckusick 1200, DCABRD(1200), 57*41480Smckusick 1800, DCABRD(1800), 58*41480Smckusick 2400, DCABRD(2400), 59*41480Smckusick 4800, DCABRD(4800), 60*41480Smckusick 9600, DCABRD(9600), 61*41480Smckusick 19200, DCABRD(19200), 62*41480Smckusick 38400, DCABRD(38400), 63*41480Smckusick -1, -1 64*41480Smckusick }; 65*41480Smckusick 66*41480Smckusick extern struct tty *constty; 67*41480Smckusick #ifdef KGDB 68*41480Smckusick extern int kgdb_dev; 69*41480Smckusick extern int kgdb_rate; 70*41480Smckusick extern int kgdb_debug_init; 71*41480Smckusick #endif 72*41480Smckusick 73*41480Smckusick #define UNIT(x) minor(x) 74*41480Smckusick 75*41480Smckusick dcaprobe(hd) 76*41480Smckusick register struct hp_device *hd; 77*41480Smckusick { 78*41480Smckusick register struct dcadevice *dca; 79*41480Smckusick register int unit; 80*41480Smckusick 81*41480Smckusick dca = (struct dcadevice *)hd->hp_addr; 82*41480Smckusick if (dca->dca_irid != DCAID0 && 83*41480Smckusick dca->dca_irid != DCAREMID0 && 84*41480Smckusick dca->dca_irid != DCAID1 && 85*41480Smckusick dca->dca_irid != DCAREMID1) 86*41480Smckusick return (0); 87*41480Smckusick unit = hd->hp_unit; 88*41480Smckusick if (unit == dcaconsole) 89*41480Smckusick DELAY(100000); 90*41480Smckusick dca->dca_irid = 0xFF; 91*41480Smckusick DELAY(100); 92*41480Smckusick 93*41480Smckusick hd->hp_ipl = DCAIPL(dca->dca_ic); 94*41480Smckusick dcaisr[unit].isr_ipl = hd->hp_ipl; 95*41480Smckusick dcaisr[unit].isr_arg = unit; 96*41480Smckusick dcaisr[unit].isr_intr = dcaintr; 97*41480Smckusick dca_addr[unit] = dca; 98*41480Smckusick dca_active |= 1 << unit; 99*41480Smckusick dcasoftCAR = hd->hp_flags; 100*41480Smckusick isrlink(&dcaisr[unit]); 101*41480Smckusick #ifdef KGDB 102*41480Smckusick if (kgdb_dev == makedev(1, unit)) { 103*41480Smckusick if (dcaconsole == unit) 104*41480Smckusick kgdb_dev = -1; /* can't debug over console port */ 105*41480Smckusick else { 106*41480Smckusick (void) dcainit(unit); 107*41480Smckusick dcaconsole = -2; /* XXX */ 108*41480Smckusick if (kgdb_debug_init) { 109*41480Smckusick printf("dca%d: kgdb waiting...", unit); 110*41480Smckusick /* trap into kgdb */ 111*41480Smckusick asm("trap #15;"); 112*41480Smckusick printf("connected.\n"); 113*41480Smckusick } else 114*41480Smckusick printf("dca%d: kgdb enabled\n", unit); 115*41480Smckusick } 116*41480Smckusick } 117*41480Smckusick #endif 118*41480Smckusick dca->dca_ic = IC_IE; 119*41480Smckusick /* 120*41480Smckusick * Need to reset baud rate, etc. of next print so reset dcaconsole. 121*41480Smckusick * Also make sure console is always "hardwired" 122*41480Smckusick */ 123*41480Smckusick if (unit == dcaconsole) { 124*41480Smckusick dcaconsole = -1; 125*41480Smckusick dcasoftCAR |= (1 << unit); 126*41480Smckusick } 127*41480Smckusick return (1); 128*41480Smckusick } 129*41480Smckusick 130*41480Smckusick dcaopen(dev, flag) 131*41480Smckusick dev_t dev; 132*41480Smckusick { 133*41480Smckusick register struct tty *tp; 134*41480Smckusick register int unit; 135*41480Smckusick 136*41480Smckusick unit = UNIT(dev); 137*41480Smckusick if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 138*41480Smckusick return (ENXIO); 139*41480Smckusick tp = &dca_tty[unit]; 140*41480Smckusick tp->t_oproc = dcastart; 141*41480Smckusick tp->t_param = dcaparam; 142*41480Smckusick tp->t_dev = dev; 143*41480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 144*41480Smckusick ttychars(tp); 145*41480Smckusick tp->t_iflag = TTYDEF_IFLAG; 146*41480Smckusick tp->t_oflag = TTYDEF_OFLAG; 147*41480Smckusick tp->t_cflag = TTYDEF_CFLAG; 148*41480Smckusick tp->t_lflag = TTYDEF_LFLAG; 149*41480Smckusick tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 150*41480Smckusick dcaparam(tp, &tp->t_termios); 151*41480Smckusick ttsetwater(tp); 152*41480Smckusick } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 153*41480Smckusick return (EBUSY); 154*41480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 155*41480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 156*41480Smckusick tp->t_state |= TS_CARR_ON; 157*41480Smckusick (void) spltty(); 158*41480Smckusick while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 159*41480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 160*41480Smckusick tp->t_state |= TS_WOPEN; 161*41480Smckusick sleep((caddr_t)&tp->t_rawq, TTIPRI); 162*41480Smckusick } 163*41480Smckusick (void) spl0(); 164*41480Smckusick return ((*linesw[tp->t_line].l_open)(dev, tp)); 165*41480Smckusick } 166*41480Smckusick 167*41480Smckusick /*ARGSUSED*/ 168*41480Smckusick dcaclose(dev, flag) 169*41480Smckusick dev_t dev; 170*41480Smckusick { 171*41480Smckusick register struct tty *tp; 172*41480Smckusick register struct dcadevice *dca; 173*41480Smckusick register int unit; 174*41480Smckusick 175*41480Smckusick unit = UNIT(dev); 176*41480Smckusick dca = dca_addr[unit]; 177*41480Smckusick tp = &dca_tty[unit]; 178*41480Smckusick (*linesw[tp->t_line].l_close)(tp); 179*41480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 180*41480Smckusick #ifdef KGDB 181*41480Smckusick /* do not disable interrupts if debugging */ 182*41480Smckusick if (kgdb_dev != makedev(1, unit)) 183*41480Smckusick #endif 184*41480Smckusick dca->dca_ier = 0; 185*41480Smckusick if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 186*41480Smckusick (tp->t_state&TS_ISOPEN) == 0) 187*41480Smckusick (void) dcamctl(dev, 0, DMSET); 188*41480Smckusick ttyclose(tp); 189*41480Smckusick return(0); 190*41480Smckusick } 191*41480Smckusick 192*41480Smckusick dcaread(dev, uio, flag) 193*41480Smckusick dev_t dev; 194*41480Smckusick struct uio *uio; 195*41480Smckusick { 196*41480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 197*41480Smckusick 198*41480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 199*41480Smckusick } 200*41480Smckusick 201*41480Smckusick dcawrite(dev, uio, flag) 202*41480Smckusick dev_t dev; 203*41480Smckusick struct uio *uio; 204*41480Smckusick { 205*41480Smckusick int unit = UNIT(dev); 206*41480Smckusick register struct tty *tp = &dca_tty[unit]; 207*41480Smckusick 208*41480Smckusick if (unit == dcaconsole && constty && 209*41480Smckusick (constty->t_state&(TS_CARR_ON|TS_ISOPEN))==(TS_CARR_ON|TS_ISOPEN)) 210*41480Smckusick tp = constty; 211*41480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 212*41480Smckusick } 213*41480Smckusick 214*41480Smckusick dcaintr(unit) 215*41480Smckusick register int unit; 216*41480Smckusick { 217*41480Smckusick register struct dcadevice *dca; 218*41480Smckusick register int code; 219*41480Smckusick 220*41480Smckusick dca = dca_addr[unit]; 221*41480Smckusick if ((dca->dca_ic & IC_IR) == 0) 222*41480Smckusick return(0); 223*41480Smckusick while (((code = dca->dca_iir) & IIR_NOPEND) == 0) { 224*41480Smckusick code &= IIR_IMASK; 225*41480Smckusick if (code == IIR_RLS) 226*41480Smckusick dcaeint(unit, dca); 227*41480Smckusick else if (code == IIR_RXRDY) 228*41480Smckusick dcarint(unit, dca); 229*41480Smckusick else if (code == IIR_TXRDY) 230*41480Smckusick dcaxint(unit, dca); 231*41480Smckusick else 232*41480Smckusick dcamint(unit, dca); 233*41480Smckusick } 234*41480Smckusick return(1); 235*41480Smckusick } 236*41480Smckusick 237*41480Smckusick dcaeint(unit, dca) 238*41480Smckusick register int unit; 239*41480Smckusick register struct dcadevice *dca; 240*41480Smckusick { 241*41480Smckusick register struct tty *tp; 242*41480Smckusick register int stat, c; 243*41480Smckusick 244*41480Smckusick tp = &dca_tty[unit]; 245*41480Smckusick stat = dca->dca_lsr; 246*41480Smckusick c = dca->dca_data & 0xff; 247*41480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 248*41480Smckusick #ifdef KGDB 249*41480Smckusick /* we don't care about parity errors */ 250*41480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 251*41480Smckusick kgdb_dev == makedev(1, unit) && c == '!') { 252*41480Smckusick printf("kgdb trap from dca%d\n", unit); 253*41480Smckusick /* trap into kgdb */ 254*41480Smckusick asm("trap #15;"); 255*41480Smckusick } 256*41480Smckusick #endif 257*41480Smckusick return; 258*41480Smckusick } 259*41480Smckusick if (stat & (LSR_BI | LSR_FE)) 260*41480Smckusick c |= TTY_FE; 261*41480Smckusick else if (stat & LSR_PE) 262*41480Smckusick c |= TTY_PE; 263*41480Smckusick else if (stat & LSR_OE) 264*41480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 265*41480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 266*41480Smckusick } 267*41480Smckusick 268*41480Smckusick dcarint(unit, dca) 269*41480Smckusick int unit; 270*41480Smckusick register struct dcadevice *dca; 271*41480Smckusick { 272*41480Smckusick register struct tty *tp; 273*41480Smckusick register int c; 274*41480Smckusick 275*41480Smckusick tp = &dca_tty[unit]; 276*41480Smckusick c = dca->dca_data; 277*41480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 278*41480Smckusick #ifdef KGDB 279*41480Smckusick if (kgdb_dev == makedev(1, unit) && c == '!') { 280*41480Smckusick printf("kgdb trap from dca%d\n", unit); 281*41480Smckusick /* trap into kgdb */ 282*41480Smckusick asm("trap #15;"); 283*41480Smckusick } 284*41480Smckusick #endif 285*41480Smckusick return; 286*41480Smckusick } 287*41480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 288*41480Smckusick } 289*41480Smckusick 290*41480Smckusick /*ARGSUSED*/ 291*41480Smckusick dcaxint(unit, dca) 292*41480Smckusick int unit; 293*41480Smckusick struct dcadevice *dca; 294*41480Smckusick { 295*41480Smckusick register struct tty *tp; 296*41480Smckusick 297*41480Smckusick tp = &dca_tty[unit]; 298*41480Smckusick tp->t_state &= ~TS_BUSY; 299*41480Smckusick if (tp->t_state & TS_FLUSH) 300*41480Smckusick tp->t_state &= ~TS_FLUSH; 301*41480Smckusick if (tp->t_line) 302*41480Smckusick (*linesw[tp->t_line].l_start)(tp); 303*41480Smckusick else 304*41480Smckusick dcastart(tp); 305*41480Smckusick } 306*41480Smckusick 307*41480Smckusick dcamint(unit, dca) 308*41480Smckusick register int unit; 309*41480Smckusick register struct dcadevice *dca; 310*41480Smckusick { 311*41480Smckusick register struct tty *tp; 312*41480Smckusick register int stat; 313*41480Smckusick 314*41480Smckusick tp = &dca_tty[unit]; 315*41480Smckusick stat = dca->dca_msr; 316*41480Smckusick if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) { 317*41480Smckusick if (stat & MSR_DCD) 318*41480Smckusick (void) (*linesw[tp->t_line].l_modem)(tp, 1); 319*41480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 320*41480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 321*41480Smckusick } 322*41480Smckusick } 323*41480Smckusick 324*41480Smckusick dcaioctl(dev, cmd, data, flag) 325*41480Smckusick dev_t dev; 326*41480Smckusick caddr_t data; 327*41480Smckusick { 328*41480Smckusick register struct tty *tp; 329*41480Smckusick register int unit = UNIT(dev); 330*41480Smckusick register struct dcadevice *dca; 331*41480Smckusick register int error; 332*41480Smckusick 333*41480Smckusick tp = &dca_tty[unit]; 334*41480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 335*41480Smckusick if (error >= 0) 336*41480Smckusick return (error); 337*41480Smckusick error = ttioctl(tp, cmd, data, flag); 338*41480Smckusick if (error >= 0) 339*41480Smckusick return (error); 340*41480Smckusick 341*41480Smckusick dca = dca_addr[unit]; 342*41480Smckusick switch (cmd) { 343*41480Smckusick 344*41480Smckusick case TIOCSBRK: 345*41480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 346*41480Smckusick break; 347*41480Smckusick 348*41480Smckusick case TIOCCBRK: 349*41480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 350*41480Smckusick break; 351*41480Smckusick 352*41480Smckusick case TIOCSDTR: 353*41480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 354*41480Smckusick break; 355*41480Smckusick 356*41480Smckusick case TIOCCDTR: 357*41480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 358*41480Smckusick break; 359*41480Smckusick 360*41480Smckusick case TIOCMSET: 361*41480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 362*41480Smckusick break; 363*41480Smckusick 364*41480Smckusick case TIOCMBIS: 365*41480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 366*41480Smckusick break; 367*41480Smckusick 368*41480Smckusick case TIOCMBIC: 369*41480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 370*41480Smckusick break; 371*41480Smckusick 372*41480Smckusick case TIOCMGET: 373*41480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 374*41480Smckusick break; 375*41480Smckusick 376*41480Smckusick default: 377*41480Smckusick return (ENOTTY); 378*41480Smckusick } 379*41480Smckusick return (0); 380*41480Smckusick } 381*41480Smckusick 382*41480Smckusick dcaparam(tp, t) 383*41480Smckusick register struct tty *tp; 384*41480Smckusick register struct termios *t; 385*41480Smckusick { 386*41480Smckusick register struct dcadevice *dca; 387*41480Smckusick register int cfcr, cflag = t->c_cflag; 388*41480Smckusick int unit = UNIT(tp->t_dev); 389*41480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 390*41480Smckusick 391*41480Smckusick /* check requested parameters */ 392*41480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 393*41480Smckusick return(EINVAL); 394*41480Smckusick /* and copy to tty */ 395*41480Smckusick tp->t_ispeed = t->c_ispeed; 396*41480Smckusick tp->t_ospeed = t->c_ospeed; 397*41480Smckusick tp->t_cflag = cflag; 398*41480Smckusick 399*41480Smckusick dca = dca_addr[unit]; 400*41480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 401*41480Smckusick if (ospeed == 0) { 402*41480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 403*41480Smckusick return(0); 404*41480Smckusick } 405*41480Smckusick dca->dca_cfcr |= CFCR_DLAB; 406*41480Smckusick dca->dca_data = ospeed & 0xFF; 407*41480Smckusick dca->dca_ier = ospeed >> 8; 408*41480Smckusick switch (cflag&CSIZE) { 409*41480Smckusick case CS5: 410*41480Smckusick cfcr = CFCR_5BITS; break; 411*41480Smckusick case CS6: 412*41480Smckusick cfcr = CFCR_6BITS; break; 413*41480Smckusick case CS7: 414*41480Smckusick cfcr = CFCR_7BITS; break; 415*41480Smckusick case CS8: 416*41480Smckusick cfcr = CFCR_8BITS; break; 417*41480Smckusick } 418*41480Smckusick if (cflag&PARENB) { 419*41480Smckusick cfcr |= CFCR_PENAB; 420*41480Smckusick if ((cflag&PARODD) == 0) 421*41480Smckusick cfcr |= CFCR_PEVEN; 422*41480Smckusick } 423*41480Smckusick if (cflag&CSTOPB) 424*41480Smckusick cfcr |= CFCR_STOPB; 425*41480Smckusick dca->dca_cfcr = cfcr; 426*41480Smckusick return(0); 427*41480Smckusick } 428*41480Smckusick 429*41480Smckusick dcastart(tp) 430*41480Smckusick register struct tty *tp; 431*41480Smckusick { 432*41480Smckusick register struct dcadevice *dca; 433*41480Smckusick int s, unit, c; 434*41480Smckusick 435*41480Smckusick unit = UNIT(tp->t_dev); 436*41480Smckusick dca = dca_addr[unit]; 437*41480Smckusick s = spltty(); 438*41480Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 439*41480Smckusick goto out; 440*41480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 441*41480Smckusick if (tp->t_state&TS_ASLEEP) { 442*41480Smckusick tp->t_state &= ~TS_ASLEEP; 443*41480Smckusick wakeup((caddr_t)&tp->t_outq); 444*41480Smckusick } 445*41480Smckusick if (tp->t_wsel) { 446*41480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 447*41480Smckusick tp->t_wsel = 0; 448*41480Smckusick tp->t_state &= ~TS_WCOLL; 449*41480Smckusick } 450*41480Smckusick } 451*41480Smckusick if (tp->t_outq.c_cc == 0) 452*41480Smckusick goto out; 453*41480Smckusick c = getc(&tp->t_outq); 454*41480Smckusick tp->t_state |= TS_BUSY; 455*41480Smckusick dca->dca_data = c; 456*41480Smckusick out: 457*41480Smckusick splx(s); 458*41480Smckusick } 459*41480Smckusick 460*41480Smckusick /* 461*41480Smckusick * Stop output on a line. 462*41480Smckusick */ 463*41480Smckusick /*ARGSUSED*/ 464*41480Smckusick dcastop(tp, flag) 465*41480Smckusick register struct tty *tp; 466*41480Smckusick { 467*41480Smckusick register int s; 468*41480Smckusick 469*41480Smckusick s = spltty(); 470*41480Smckusick if (tp->t_state & TS_BUSY) { 471*41480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 472*41480Smckusick tp->t_state |= TS_FLUSH; 473*41480Smckusick } 474*41480Smckusick splx(s); 475*41480Smckusick } 476*41480Smckusick 477*41480Smckusick dcamctl(dev, bits, how) 478*41480Smckusick dev_t dev; 479*41480Smckusick int bits, how; 480*41480Smckusick { 481*41480Smckusick register struct dcadevice *dca; 482*41480Smckusick register int unit; 483*41480Smckusick int s; 484*41480Smckusick 485*41480Smckusick unit = UNIT(dev); 486*41480Smckusick dca = dca_addr[unit]; 487*41480Smckusick s = spltty(); 488*41480Smckusick switch (how) { 489*41480Smckusick 490*41480Smckusick case DMSET: 491*41480Smckusick dca->dca_mcr = bits; 492*41480Smckusick break; 493*41480Smckusick 494*41480Smckusick case DMBIS: 495*41480Smckusick dca->dca_mcr |= bits; 496*41480Smckusick break; 497*41480Smckusick 498*41480Smckusick case DMBIC: 499*41480Smckusick dca->dca_mcr &= ~bits; 500*41480Smckusick break; 501*41480Smckusick 502*41480Smckusick case DMGET: 503*41480Smckusick bits = dca->dca_msr; 504*41480Smckusick break; 505*41480Smckusick } 506*41480Smckusick (void) splx(s); 507*41480Smckusick return(bits); 508*41480Smckusick } 509*41480Smckusick 510*41480Smckusick /* 511*41480Smckusick * Following are all routines needed for DCA to act as console 512*41480Smckusick */ 513*41480Smckusick #include "machine/cons.h" 514*41480Smckusick 515*41480Smckusick dcacnprobe(cp) 516*41480Smckusick struct consdev *cp; 517*41480Smckusick { 518*41480Smckusick int unit, i; 519*41480Smckusick extern int dcaopen(); 520*41480Smckusick 521*41480Smckusick /* XXX: ick */ 522*41480Smckusick unit = CONUNIT; 523*41480Smckusick dca_addr[CONUNIT] = CONADDR; 524*41480Smckusick 525*41480Smckusick /* make sure hardware exists */ 526*41480Smckusick if (badaddr((short *)dca_addr[unit])) { 527*41480Smckusick cp->cn_pri = CN_DEAD; 528*41480Smckusick return; 529*41480Smckusick } 530*41480Smckusick 531*41480Smckusick /* locate the major number */ 532*41480Smckusick for (i = 0; i < nchrdev; i++) 533*41480Smckusick if (cdevsw[i].d_open == dcaopen) 534*41480Smckusick break; 535*41480Smckusick 536*41480Smckusick /* initialize required fields */ 537*41480Smckusick cp->cn_dev = makedev(i, unit); 538*41480Smckusick cp->cn_tp = &dca_tty[unit]; 539*41480Smckusick switch (dca_addr[unit]->dca_irid) { 540*41480Smckusick case DCAID0: 541*41480Smckusick case DCAID1: 542*41480Smckusick cp->cn_pri = CN_NORMAL; 543*41480Smckusick break; 544*41480Smckusick case DCAREMID0: 545*41480Smckusick case DCAREMID1: 546*41480Smckusick cp->cn_pri = CN_REMOTE; 547*41480Smckusick break; 548*41480Smckusick default: 549*41480Smckusick cp->cn_pri = CN_DEAD; 550*41480Smckusick break; 551*41480Smckusick } 552*41480Smckusick } 553*41480Smckusick 554*41480Smckusick dcacninit(cp) 555*41480Smckusick struct consdev *cp; 556*41480Smckusick { 557*41480Smckusick int unit = UNIT(cp->cn_dev); 558*41480Smckusick 559*41480Smckusick dcainit(unit); 560*41480Smckusick dcaconsole = unit; 561*41480Smckusick } 562*41480Smckusick 563*41480Smckusick dcainit(unit) 564*41480Smckusick int unit; 565*41480Smckusick { 566*41480Smckusick register struct dcadevice *dca; 567*41480Smckusick int s, rate; 568*41480Smckusick short stat; 569*41480Smckusick 570*41480Smckusick #ifdef lint 571*41480Smckusick stat = unit; if (stat) return; 572*41480Smckusick #endif 573*41480Smckusick dca = dca_addr[unit]; 574*41480Smckusick s = splhigh(); 575*41480Smckusick dca->dca_irid = 0xFF; 576*41480Smckusick DELAY(100); 577*41480Smckusick dca->dca_ic = IC_IE; 578*41480Smckusick dca->dca_cfcr = CFCR_DLAB; 579*41480Smckusick rate = ttspeedtab(dcadefaultrate, dcaspeedtab); 580*41480Smckusick dca->dca_data = rate & 0xFF; 581*41480Smckusick dca->dca_ier = rate >> 8; 582*41480Smckusick dca->dca_cfcr = CFCR_8BITS; 583*41480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 584*41480Smckusick stat = dca->dca_iir; 585*41480Smckusick splx(s); 586*41480Smckusick } 587*41480Smckusick 588*41480Smckusick dcacngetc(dev) 589*41480Smckusick { 590*41480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 591*41480Smckusick short stat; 592*41480Smckusick int c, s; 593*41480Smckusick 594*41480Smckusick #ifdef lint 595*41480Smckusick stat = dev; if (stat) return(0); 596*41480Smckusick #endif 597*41480Smckusick s = splhigh(); 598*41480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 599*41480Smckusick ; 600*41480Smckusick c = dca->dca_data; 601*41480Smckusick stat = dca->dca_iir; 602*41480Smckusick splx(s); 603*41480Smckusick return(c); 604*41480Smckusick } 605*41480Smckusick 606*41480Smckusick /* 607*41480Smckusick * Console kernel output character routine. 608*41480Smckusick */ 609*41480Smckusick dcacnputc(dev, c) 610*41480Smckusick dev_t dev; 611*41480Smckusick register int c; 612*41480Smckusick { 613*41480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 614*41480Smckusick register int timo; 615*41480Smckusick short stat; 616*41480Smckusick int s = splhigh(); 617*41480Smckusick 618*41480Smckusick #ifdef lint 619*41480Smckusick stat = dev; if (stat) return; 620*41480Smckusick #endif 621*41480Smckusick if (dcaconsole == -1) { 622*41480Smckusick (void) dcainit(UNIT(dev)); 623*41480Smckusick dcaconsole = UNIT(dev); 624*41480Smckusick } 625*41480Smckusick /* wait for any pending transmission to finish */ 626*41480Smckusick timo = 50000; 627*41480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 628*41480Smckusick ; 629*41480Smckusick dca->dca_data = c; 630*41480Smckusick /* wait for this transmission to complete */ 631*41480Smckusick timo = 1500000; 632*41480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 633*41480Smckusick ; 634*41480Smckusick /* clear any interrupts generated by this transmission */ 635*41480Smckusick stat = dca->dca_iir; 636*41480Smckusick splx(s); 637*41480Smckusick } 638*41480Smckusick #endif 639