1*47752Swilliam /*- 2*47752Swilliam * Copyright (c) 1982, 1986, 1990, 1991 The Regents of the University of 3*47752Swilliam * California. All rights reserved. 4*47752Swilliam * 5*47752Swilliam * This code is derived from software contributed to Berkeley by 6*47752Swilliam * the University of Utah and William Jolitz. 7*47752Swilliam * 8*47752Swilliam * %sccs.include.redist.c% 9*47752Swilliam * 10*47752Swilliam * @(#)com.c 7.1 (Berkeley) 04/03/91 11*47752Swilliam */ 12*47752Swilliam 13*47752Swilliam #include "dca.h" 14*47752Swilliam #if NDCA > 0 15*47752Swilliam /* 16*47752Swilliam * COM driver, from hp300 dca.c 98626/98644/internal serial interface 17*47752Swilliam */ 18*47752Swilliam #include "sys/param.h" 19*47752Swilliam #include "sys/systm.h" 20*47752Swilliam #include "sys/ioctl.h" 21*47752Swilliam #include "sys/tty.h" 22*47752Swilliam #include "sys/user.h" 23*47752Swilliam #include "sys/conf.h" 24*47752Swilliam #include "sys/file.h" 25*47752Swilliam #include "sys/uio.h" 26*47752Swilliam #include "sys/kernel.h" 27*47752Swilliam #include "sys/syslog.h" 28*47752Swilliam 29*47752Swilliam #include "i386/isa/isa_device.h" 30*47752Swilliam #include "i386/isa/comreg.h" 31*47752Swilliam #include "i386/isa/ic/ns16450.h" 32*47752Swilliam 33*47752Swilliam int comprobe(), comattach(), comintr(), comstart(), comparam(); 34*47752Swilliam 35*47752Swilliam struct isa_driver comdriver = { 36*47752Swilliam comprobe, comattach, "com" 37*47752Swilliam }; 38*47752Swilliam 39*47752Swilliam int comsoftCAR; 40*47752Swilliam int com_active; 41*47752Swilliam int ncom = NDCA; 42*47752Swilliam int comconsole = -1; 43*47752Swilliam int comdefaultrate = TTYDEF_SPEED; 44*47752Swilliam short com_addr[NDCA]; 45*47752Swilliam struct tty com_tty[NDCA]; 46*47752Swilliam 47*47752Swilliam struct speedtab comspeedtab[] = { 48*47752Swilliam 0, 0, 49*47752Swilliam 50, COMBRD(50), 50*47752Swilliam 75, COMBRD(75), 51*47752Swilliam 110, COMBRD(110), 52*47752Swilliam 134, COMBRD(134), 53*47752Swilliam 150, COMBRD(150), 54*47752Swilliam 200, COMBRD(200), 55*47752Swilliam 300, COMBRD(300), 56*47752Swilliam 600, COMBRD(600), 57*47752Swilliam 1200, COMBRD(1200), 58*47752Swilliam 1800, COMBRD(1800), 59*47752Swilliam 2400, COMBRD(2400), 60*47752Swilliam 4800, COMBRD(4800), 61*47752Swilliam 9600, COMBRD(9600), 62*47752Swilliam 19200, COMBRD(19200), 63*47752Swilliam 38400, COMBRD(38400), 64*47752Swilliam 57600, COMBRD(57600), 65*47752Swilliam -1, -1 66*47752Swilliam }; 67*47752Swilliam 68*47752Swilliam extern struct tty *constty; 69*47752Swilliam #ifdef KGDB 70*47752Swilliam extern int kgdb_dev; 71*47752Swilliam extern int kgdb_rate; 72*47752Swilliam extern int kgdb_debug_init; 73*47752Swilliam #endif 74*47752Swilliam 75*47752Swilliam #define UNIT(x) minor(x) 76*47752Swilliam 77*47752Swilliam comprobe(dev) 78*47752Swilliam struct isa_device *dev; 79*47752Swilliam { 80*47752Swilliam if ((inb(dev->id_iobase+com_iir) & 0xf8) == 0) 81*47752Swilliam return(1); 82*47752Swilliam return(0); 83*47752Swilliam 84*47752Swilliam } 85*47752Swilliam 86*47752Swilliam 87*47752Swilliam int 88*47752Swilliam comattach(isdp) 89*47752Swilliam struct isa_device *isdp; 90*47752Swilliam { 91*47752Swilliam struct tty *tp; 92*47752Swilliam u_char unit; 93*47752Swilliam int port = isdp->id_iobase; 94*47752Swilliam 95*47752Swilliam if (unit == comconsole) 96*47752Swilliam DELAY(100000); 97*47752Swilliam unit = isdp->id_unit; 98*47752Swilliam com_addr[unit] = port; 99*47752Swilliam com_active |= 1 << unit; 100*47752Swilliam /* comsoftCAR = isdp->id_flags; */ 101*47752Swilliam outb(port+com_ier, 0); 102*47752Swilliam outb(port+com_mcr, 0 | MCR_IENABLE); 103*47752Swilliam #ifdef KGDB 104*47752Swilliam if (kgdb_dev == makedev(1, unit)) { 105*47752Swilliam if (comconsole == unit) 106*47752Swilliam kgdb_dev = -1; /* can't debug over console port */ 107*47752Swilliam else { 108*47752Swilliam (void) cominit(unit); 109*47752Swilliam comconsole = -2; /* XXX */ 110*47752Swilliam if (kgdb_debug_init) { 111*47752Swilliam printf("com%d: kgdb waiting...", unit); 112*47752Swilliam /* trap into kgdb */ 113*47752Swilliam asm("trap #15;"); 114*47752Swilliam printf("connected.\n"); 115*47752Swilliam } else 116*47752Swilliam printf("com%d: kgdb enabled\n", unit); 117*47752Swilliam } 118*47752Swilliam } 119*47752Swilliam #endif 120*47752Swilliam /* 121*47752Swilliam * Need to reset baud rate, etc. of next print so reset comconsole. 122*47752Swilliam * Also make sure console is always "hardwired" 123*47752Swilliam */ 124*47752Swilliam if (unit == comconsole) { 125*47752Swilliam comconsole = -1; 126*47752Swilliam comsoftCAR |= (1 << unit); 127*47752Swilliam } 128*47752Swilliam comsoftCAR |= (1 << unit); 129*47752Swilliam return (1); 130*47752Swilliam } 131*47752Swilliam 132*47752Swilliam comopen(dev, flag) 133*47752Swilliam dev_t dev; 134*47752Swilliam { 135*47752Swilliam register struct tty *tp; 136*47752Swilliam register int unit; 137*47752Swilliam int error = 0; 138*47752Swilliam 139*47752Swilliam unit = UNIT(dev); 140*47752Swilliam if (unit >= NDCA || (com_active & (1 << unit)) == 0) 141*47752Swilliam return (ENXIO); 142*47752Swilliam tp = &com_tty[unit]; 143*47752Swilliam tp->t_oproc = comstart; 144*47752Swilliam tp->t_param = comparam; 145*47752Swilliam tp->t_dev = dev; 146*47752Swilliam if ((tp->t_state & TS_ISOPEN) == 0) { 147*47752Swilliam tp->t_state |= TS_WOPEN; 148*47752Swilliam ttychars(tp); 149*47752Swilliam tp->t_iflag = TTYDEF_IFLAG; 150*47752Swilliam tp->t_oflag = TTYDEF_OFLAG; 151*47752Swilliam tp->t_cflag = TTYDEF_CFLAG; 152*47752Swilliam tp->t_lflag = TTYDEF_LFLAG; 153*47752Swilliam tp->t_ispeed = tp->t_ospeed = comdefaultrate; 154*47752Swilliam comparam(tp, &tp->t_termios); 155*47752Swilliam ttsetwater(tp); 156*47752Swilliam } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 157*47752Swilliam return (EBUSY); 158*47752Swilliam (void) spltty(); 159*47752Swilliam (void) commctl(dev, MCR_DTR | MCR_RTS, DMSET); 160*47752Swilliam if ((comsoftCAR & (1 << unit)) || (commctl(dev, 0, DMGET) & MSR_DCD)) 161*47752Swilliam tp->t_state |= TS_CARR_ON; 162*47752Swilliam while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 163*47752Swilliam (tp->t_state & TS_CARR_ON) == 0) { 164*47752Swilliam tp->t_state |= TS_WOPEN; 165*47752Swilliam if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 166*47752Swilliam ttopen, 0)) 167*47752Swilliam break; 168*47752Swilliam } 169*47752Swilliam (void) spl0(); 170*47752Swilliam if (error == 0) 171*47752Swilliam error = (*linesw[tp->t_line].l_open)(dev, tp); 172*47752Swilliam return (error); 173*47752Swilliam } 174*47752Swilliam 175*47752Swilliam /*ARGSUSED*/ 176*47752Swilliam comclose(dev, flag) 177*47752Swilliam dev_t dev; 178*47752Swilliam { 179*47752Swilliam register struct tty *tp; 180*47752Swilliam register com; 181*47752Swilliam register int unit; 182*47752Swilliam 183*47752Swilliam unit = UNIT(dev); 184*47752Swilliam com = com_addr[unit]; 185*47752Swilliam tp = &com_tty[unit]; 186*47752Swilliam (*linesw[tp->t_line].l_close)(tp); 187*47752Swilliam outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK); 188*47752Swilliam #ifdef KGDB 189*47752Swilliam /* do not disable interrupts if debugging */ 190*47752Swilliam if (kgdb_dev != makedev(1, unit)) 191*47752Swilliam #endif 192*47752Swilliam outb(com+com_ier, 0); 193*47752Swilliam if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 194*47752Swilliam (tp->t_state&TS_ISOPEN) == 0) 195*47752Swilliam (void) commctl(dev, 0, DMSET); 196*47752Swilliam ttyclose(tp); 197*47752Swilliam return(0); 198*47752Swilliam } 199*47752Swilliam 200*47752Swilliam comread(dev, uio, flag) 201*47752Swilliam dev_t dev; 202*47752Swilliam struct uio *uio; 203*47752Swilliam { 204*47752Swilliam register struct tty *tp = &com_tty[UNIT(dev)]; 205*47752Swilliam 206*47752Swilliam return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 207*47752Swilliam } 208*47752Swilliam 209*47752Swilliam comwrite(dev, uio, flag) 210*47752Swilliam dev_t dev; 211*47752Swilliam struct uio *uio; 212*47752Swilliam { 213*47752Swilliam int unit = UNIT(dev); 214*47752Swilliam register struct tty *tp = &com_tty[unit]; 215*47752Swilliam 216*47752Swilliam #ifdef notyet 217*47752Swilliam /* 218*47752Swilliam * (XXX) We disallow virtual consoles if the physical console is 219*47752Swilliam * a serial port. This is in case there is a display attached that 220*47752Swilliam * is not the console. In that situation we don't need/want the X 221*47752Swilliam * server taking over the console. 222*47752Swilliam */ 223*47752Swilliam if (constty && unit == comconsole) 224*47752Swilliam constty = NULL; 225*47752Swilliam #endif 226*47752Swilliam return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 227*47752Swilliam } 228*47752Swilliam 229*47752Swilliam comintr(unit) 230*47752Swilliam register int unit; 231*47752Swilliam { 232*47752Swilliam register com; 233*47752Swilliam register u_char code; 234*47752Swilliam register struct tty *tp; 235*47752Swilliam 236*47752Swilliam com = com_addr[unit]; 237*47752Swilliam while (1) { 238*47752Swilliam code = inb(com+com_iir); 239*47752Swilliam switch (code) { 240*47752Swilliam case IIR_NOPEND: 241*47752Swilliam return (1); 242*47752Swilliam case IIR_RXRDY: 243*47752Swilliam /* do time-critical read in-line */ 244*47752Swilliam tp = &com_tty[unit]; 245*47752Swilliam code = inb(com+com_data); 246*47752Swilliam if ((tp->t_state & TS_ISOPEN) == 0) { 247*47752Swilliam #ifdef KGDB 248*47752Swilliam if (kgdb_dev == makedev(1, unit) && 249*47752Swilliam code == '!') { 250*47752Swilliam printf("kgdb trap from com%d\n", unit); 251*47752Swilliam /* trap into kgdb */ 252*47752Swilliam asm("trap #15;"); 253*47752Swilliam } 254*47752Swilliam #endif 255*47752Swilliam } else 256*47752Swilliam (*linesw[tp->t_line].l_rint)(code, tp); 257*47752Swilliam break; 258*47752Swilliam case IIR_TXRDY: 259*47752Swilliam tp = &com_tty[unit]; 260*47752Swilliam tp->t_state &=~ (TS_BUSY|TS_FLUSH); 261*47752Swilliam if (tp->t_line) 262*47752Swilliam (*linesw[tp->t_line].l_start)(tp); 263*47752Swilliam else 264*47752Swilliam comstart(tp); 265*47752Swilliam break; 266*47752Swilliam case IIR_RLS: 267*47752Swilliam comeint(unit, com); 268*47752Swilliam break; 269*47752Swilliam default: 270*47752Swilliam if (code & IIR_NOPEND) 271*47752Swilliam return (1); 272*47752Swilliam log(LOG_WARNING, "com%d: weird interrupt: 0x%x\n", 273*47752Swilliam unit, code); 274*47752Swilliam /* fall through */ 275*47752Swilliam case IIR_MLSC: 276*47752Swilliam commint(unit, com); 277*47752Swilliam break; 278*47752Swilliam } 279*47752Swilliam } 280*47752Swilliam } 281*47752Swilliam 282*47752Swilliam comeint(unit, com) 283*47752Swilliam register int unit; 284*47752Swilliam register com; 285*47752Swilliam { 286*47752Swilliam register struct tty *tp; 287*47752Swilliam register int stat, c; 288*47752Swilliam 289*47752Swilliam tp = &com_tty[unit]; 290*47752Swilliam stat = inb(com+com_lsr); 291*47752Swilliam c = inb(com+com_data); 292*47752Swilliam if ((tp->t_state & TS_ISOPEN) == 0) { 293*47752Swilliam #ifdef KGDB 294*47752Swilliam /* we don't care about parity errors */ 295*47752Swilliam if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 296*47752Swilliam kgdb_dev == makedev(1, unit) && c == '!') { 297*47752Swilliam printf("kgdb trap from com%d\n", unit); 298*47752Swilliam /* trap into kgdb */ 299*47752Swilliam asm("trap #15;"); 300*47752Swilliam } 301*47752Swilliam #endif 302*47752Swilliam return; 303*47752Swilliam } 304*47752Swilliam if (stat & (LSR_BI | LSR_FE)) 305*47752Swilliam c |= TTY_FE; 306*47752Swilliam else if (stat & LSR_PE) 307*47752Swilliam c |= TTY_PE; 308*47752Swilliam else if (stat & LSR_OE) 309*47752Swilliam log(LOG_WARNING, "com%d: silo overflow\n", unit); 310*47752Swilliam (*linesw[tp->t_line].l_rint)(c, tp); 311*47752Swilliam } 312*47752Swilliam 313*47752Swilliam commint(unit, com) 314*47752Swilliam register int unit; 315*47752Swilliam register com; 316*47752Swilliam { 317*47752Swilliam register struct tty *tp; 318*47752Swilliam register int stat; 319*47752Swilliam 320*47752Swilliam tp = &com_tty[unit]; 321*47752Swilliam stat = inb(com+com_msr); 322*47752Swilliam if ((stat & MSR_DDCD) && (comsoftCAR & (1 << unit)) == 0) { 323*47752Swilliam if (stat & MSR_DCD) 324*47752Swilliam (void)(*linesw[tp->t_line].l_modem)(tp, 1); 325*47752Swilliam else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 326*47752Swilliam outb(com+com_mcr, 327*47752Swilliam inb(com+com_mcr) & ~(MCR_DTR | MCR_RTS) | MCR_IENABLE); 328*47752Swilliam } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 329*47752Swilliam (tp->t_flags & CRTSCTS)) { 330*47752Swilliam /* the line is up and we want to do rts/cts flow control */ 331*47752Swilliam if (stat & MSR_CTS) { 332*47752Swilliam tp->t_state &=~ TS_TTSTOP; 333*47752Swilliam ttstart(tp); 334*47752Swilliam } else 335*47752Swilliam tp->t_state |= TS_TTSTOP; 336*47752Swilliam } 337*47752Swilliam } 338*47752Swilliam 339*47752Swilliam comioctl(dev, cmd, data, flag) 340*47752Swilliam dev_t dev; 341*47752Swilliam caddr_t data; 342*47752Swilliam { 343*47752Swilliam register struct tty *tp; 344*47752Swilliam register int unit = UNIT(dev); 345*47752Swilliam register com; 346*47752Swilliam register int error; 347*47752Swilliam 348*47752Swilliam tp = &com_tty[unit]; 349*47752Swilliam error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 350*47752Swilliam if (error >= 0) 351*47752Swilliam return (error); 352*47752Swilliam error = ttioctl(tp, cmd, data, flag); 353*47752Swilliam if (error >= 0) 354*47752Swilliam return (error); 355*47752Swilliam 356*47752Swilliam com = com_addr[unit]; 357*47752Swilliam switch (cmd) { 358*47752Swilliam 359*47752Swilliam case TIOCSBRK: 360*47752Swilliam outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_SBREAK); 361*47752Swilliam break; 362*47752Swilliam 363*47752Swilliam case TIOCCBRK: 364*47752Swilliam outb(com+com_cfcr, inb(com+com_cfcr) & ~CFCR_SBREAK); 365*47752Swilliam break; 366*47752Swilliam 367*47752Swilliam case TIOCSDTR: 368*47752Swilliam (void) commctl(dev, MCR_DTR | MCR_RTS, DMBIS); 369*47752Swilliam break; 370*47752Swilliam 371*47752Swilliam case TIOCCDTR: 372*47752Swilliam (void) commctl(dev, MCR_DTR | MCR_RTS, DMBIC); 373*47752Swilliam break; 374*47752Swilliam 375*47752Swilliam case TIOCMSET: 376*47752Swilliam (void) commctl(dev, *(int *)data, DMSET); 377*47752Swilliam break; 378*47752Swilliam 379*47752Swilliam case TIOCMBIS: 380*47752Swilliam (void) commctl(dev, *(int *)data, DMBIS); 381*47752Swilliam break; 382*47752Swilliam 383*47752Swilliam case TIOCMBIC: 384*47752Swilliam (void) commctl(dev, *(int *)data, DMBIC); 385*47752Swilliam break; 386*47752Swilliam 387*47752Swilliam case TIOCMGET: 388*47752Swilliam *(int *)data = commctl(dev, 0, DMGET); 389*47752Swilliam break; 390*47752Swilliam 391*47752Swilliam default: 392*47752Swilliam return (ENOTTY); 393*47752Swilliam } 394*47752Swilliam return (0); 395*47752Swilliam } 396*47752Swilliam 397*47752Swilliam comparam(tp, t) 398*47752Swilliam register struct tty *tp; 399*47752Swilliam register struct termios *t; 400*47752Swilliam { 401*47752Swilliam register com; 402*47752Swilliam register int cfcr, cflag = t->c_cflag; 403*47752Swilliam int unit = UNIT(tp->t_dev); 404*47752Swilliam int ospeed = ttspeedtab(t->c_ospeed, comspeedtab); 405*47752Swilliam 406*47752Swilliam /* check requested parameters */ 407*47752Swilliam if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 408*47752Swilliam return(EINVAL); 409*47752Swilliam /* and copy to tty */ 410*47752Swilliam tp->t_ispeed = t->c_ispeed; 411*47752Swilliam tp->t_ospeed = t->c_ospeed; 412*47752Swilliam tp->t_cflag = cflag; 413*47752Swilliam 414*47752Swilliam com = com_addr[unit]; 415*47752Swilliam outb(com+com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS /*| IER_EMSC*/); 416*47752Swilliam if (ospeed == 0) { 417*47752Swilliam (void) commctl(unit, 0, DMSET); /* hang up line */ 418*47752Swilliam return(0); 419*47752Swilliam } 420*47752Swilliam outb(com+com_cfcr, inb(com+com_cfcr) | CFCR_DLAB); 421*47752Swilliam outb(com+com_data, ospeed & 0xFF); 422*47752Swilliam outb(com+com_ier, ospeed >> 8); 423*47752Swilliam switch (cflag&CSIZE) { 424*47752Swilliam case CS5: 425*47752Swilliam cfcr = CFCR_5BITS; break; 426*47752Swilliam case CS6: 427*47752Swilliam cfcr = CFCR_6BITS; break; 428*47752Swilliam case CS7: 429*47752Swilliam cfcr = CFCR_7BITS; break; 430*47752Swilliam case CS8: 431*47752Swilliam cfcr = CFCR_8BITS; break; 432*47752Swilliam } 433*47752Swilliam if (cflag&PARENB) { 434*47752Swilliam cfcr |= CFCR_PENAB; 435*47752Swilliam if ((cflag&PARODD) == 0) 436*47752Swilliam cfcr |= CFCR_PEVEN; 437*47752Swilliam } 438*47752Swilliam if (cflag&CSTOPB) 439*47752Swilliam cfcr |= CFCR_STOPB; 440*47752Swilliam outb(com+com_cfcr, cfcr); 441*47752Swilliam return(0); 442*47752Swilliam } 443*47752Swilliam 444*47752Swilliam comstart(tp) 445*47752Swilliam register struct tty *tp; 446*47752Swilliam { 447*47752Swilliam register com; 448*47752Swilliam int s, unit, c; 449*47752Swilliam 450*47752Swilliam unit = UNIT(tp->t_dev); 451*47752Swilliam com = com_addr[unit]; 452*47752Swilliam s = spltty(); 453*47752Swilliam if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 454*47752Swilliam goto out; 455*47752Swilliam if (tp->t_outq.c_cc <= tp->t_lowat) { 456*47752Swilliam if (tp->t_state&TS_ASLEEP) { 457*47752Swilliam tp->t_state &= ~TS_ASLEEP; 458*47752Swilliam wakeup((caddr_t)&tp->t_outq); 459*47752Swilliam } 460*47752Swilliam if (tp->t_wsel) { 461*47752Swilliam selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 462*47752Swilliam tp->t_wsel = 0; 463*47752Swilliam tp->t_state &= ~TS_WCOLL; 464*47752Swilliam } 465*47752Swilliam } 466*47752Swilliam if (tp->t_outq.c_cc == 0) 467*47752Swilliam goto out; 468*47752Swilliam if (inb(com+com_lsr) & LSR_TXRDY) { 469*47752Swilliam c = getc(&tp->t_outq); 470*47752Swilliam tp->t_state |= TS_BUSY; 471*47752Swilliam outb(com+com_data, c); 472*47752Swilliam } 473*47752Swilliam out: 474*47752Swilliam splx(s); 475*47752Swilliam } 476*47752Swilliam 477*47752Swilliam /* 478*47752Swilliam * Stop output on a line. 479*47752Swilliam */ 480*47752Swilliam /*ARGSUSED*/ 481*47752Swilliam comstop(tp, flag) 482*47752Swilliam register struct tty *tp; 483*47752Swilliam { 484*47752Swilliam register int s; 485*47752Swilliam 486*47752Swilliam s = spltty(); 487*47752Swilliam if (tp->t_state & TS_BUSY) { 488*47752Swilliam if ((tp->t_state&TS_TTSTOP)==0) 489*47752Swilliam tp->t_state |= TS_FLUSH; 490*47752Swilliam } 491*47752Swilliam splx(s); 492*47752Swilliam } 493*47752Swilliam 494*47752Swilliam commctl(dev, bits, how) 495*47752Swilliam dev_t dev; 496*47752Swilliam int bits, how; 497*47752Swilliam { 498*47752Swilliam register com; 499*47752Swilliam register int unit; 500*47752Swilliam int s; 501*47752Swilliam 502*47752Swilliam unit = UNIT(dev); 503*47752Swilliam com = com_addr[unit]; 504*47752Swilliam s = spltty(); 505*47752Swilliam switch (how) { 506*47752Swilliam 507*47752Swilliam case DMSET: 508*47752Swilliam outb(com+com_mcr, bits | MCR_IENABLE); 509*47752Swilliam break; 510*47752Swilliam 511*47752Swilliam case DMBIS: 512*47752Swilliam outb(com+com_mcr, inb(com+com_mcr) | bits | MCR_IENABLE); 513*47752Swilliam break; 514*47752Swilliam 515*47752Swilliam case DMBIC: 516*47752Swilliam outb(com+com_mcr, inb(com+com_mcr) & ~bits | MCR_IENABLE); 517*47752Swilliam break; 518*47752Swilliam 519*47752Swilliam case DMGET: 520*47752Swilliam bits = inb(com+com_msr); 521*47752Swilliam break; 522*47752Swilliam } 523*47752Swilliam (void) splx(s); 524*47752Swilliam return(bits); 525*47752Swilliam } 526*47752Swilliam #endif 527