141480Smckusick /* 241480Smckusick * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 341480Smckusick * All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*49130Skarels * @(#)dca.c 7.9 (Berkeley) 05/04/91 841480Smckusick */ 941480Smckusick 1041480Smckusick #include "dca.h" 1141480Smckusick #if NDCA > 0 1241480Smckusick /* 1341480Smckusick * 98626/98644/internal serial interface 1441480Smckusick */ 1545788Sbostic #include "sys/param.h" 1645788Sbostic #include "sys/systm.h" 1745788Sbostic #include "sys/ioctl.h" 1845788Sbostic #include "sys/tty.h" 19*49130Skarels #include "sys/proc.h" 2045788Sbostic #include "sys/conf.h" 2145788Sbostic #include "sys/file.h" 2245788Sbostic #include "sys/uio.h" 2345788Sbostic #include "sys/kernel.h" 2445788Sbostic #include "sys/syslog.h" 2541480Smckusick 2641480Smckusick #include "device.h" 2741480Smckusick #include "dcareg.h" 28*49130Skarels #include "machine/cpu.h" 2945788Sbostic #include "../hp300/isr.h" 3041480Smckusick 3141480Smckusick int dcaprobe(); 3241480Smckusick struct driver dcadriver = { 3341480Smckusick dcaprobe, "dca", 3441480Smckusick }; 3541480Smckusick 3641480Smckusick int dcastart(), dcaparam(), dcaintr(); 3741480Smckusick int dcasoftCAR; 3841480Smckusick int dca_active; 3941480Smckusick int ndca = NDCA; 40*49130Skarels #ifdef DCACONSOLE 41*49130Skarels int dcaconsole = DCACONSOLE; 42*49130Skarels #else 4341480Smckusick int dcaconsole = -1; 44*49130Skarels #endif 45*49130Skarels int dcaconsinit; 4641480Smckusick int dcadefaultrate = TTYDEF_SPEED; 47*49130Skarels int dcamajor; 4841480Smckusick struct dcadevice *dca_addr[NDCA]; 4941480Smckusick struct tty dca_tty[NDCA]; 5041480Smckusick struct isr dcaisr[NDCA]; 5141480Smckusick 5241480Smckusick struct speedtab dcaspeedtab[] = { 5341480Smckusick 0, 0, 5441480Smckusick 50, DCABRD(50), 5541480Smckusick 75, DCABRD(75), 5641480Smckusick 110, DCABRD(110), 5741480Smckusick 134, DCABRD(134), 5841480Smckusick 150, DCABRD(150), 5941480Smckusick 200, DCABRD(200), 6041480Smckusick 300, DCABRD(300), 6141480Smckusick 600, DCABRD(600), 6241480Smckusick 1200, DCABRD(1200), 6341480Smckusick 1800, DCABRD(1800), 6441480Smckusick 2400, DCABRD(2400), 6541480Smckusick 4800, DCABRD(4800), 6641480Smckusick 9600, DCABRD(9600), 6741480Smckusick 19200, DCABRD(19200), 6841480Smckusick 38400, DCABRD(38400), 6941480Smckusick -1, -1 7041480Smckusick }; 7141480Smckusick 7241480Smckusick extern struct tty *constty; 7341480Smckusick #ifdef KGDB 74*49130Skarels #include "machine/remote-sl.h" 75*49130Skarels 7641480Smckusick extern int kgdb_dev; 7741480Smckusick extern int kgdb_rate; 7841480Smckusick extern int kgdb_debug_init; 7941480Smckusick #endif 8041480Smckusick 8141480Smckusick #define UNIT(x) minor(x) 8241480Smckusick 8341480Smckusick dcaprobe(hd) 8441480Smckusick register struct hp_device *hd; 8541480Smckusick { 8641480Smckusick register struct dcadevice *dca; 8741480Smckusick register int unit; 8841480Smckusick 8941480Smckusick dca = (struct dcadevice *)hd->hp_addr; 9041480Smckusick if (dca->dca_irid != DCAID0 && 9141480Smckusick dca->dca_irid != DCAREMID0 && 9241480Smckusick dca->dca_irid != DCAID1 && 9341480Smckusick dca->dca_irid != DCAREMID1) 9441480Smckusick return (0); 9541480Smckusick unit = hd->hp_unit; 9641480Smckusick if (unit == dcaconsole) 9741480Smckusick DELAY(100000); 9841480Smckusick dca->dca_irid = 0xFF; 9941480Smckusick DELAY(100); 10041480Smckusick 10141480Smckusick hd->hp_ipl = DCAIPL(dca->dca_ic); 10241480Smckusick dcaisr[unit].isr_ipl = hd->hp_ipl; 10341480Smckusick dcaisr[unit].isr_arg = unit; 10441480Smckusick dcaisr[unit].isr_intr = dcaintr; 10541480Smckusick dca_addr[unit] = dca; 10641480Smckusick dca_active |= 1 << unit; 10741480Smckusick dcasoftCAR = hd->hp_flags; 10841480Smckusick isrlink(&dcaisr[unit]); 10941480Smckusick #ifdef KGDB 110*49130Skarels if (kgdb_dev == makedev(dcamajor, unit)) { 11141480Smckusick if (dcaconsole == unit) 11241480Smckusick kgdb_dev = -1; /* can't debug over console port */ 11341480Smckusick else { 114*49130Skarels (void) dcainit(unit, kgdb_rate); 11541480Smckusick if (kgdb_debug_init) { 116*49130Skarels /* 117*49130Skarels * Print prefix of device name, 118*49130Skarels * let kgdb_connect print the rest. 119*49130Skarels */ 120*49130Skarels printf("dca%d: ", unit); 121*49130Skarels kgdb_connect(1); 12241480Smckusick } else 12341480Smckusick printf("dca%d: kgdb enabled\n", unit); 12441480Smckusick } 12541480Smckusick } 12641480Smckusick #endif 12741480Smckusick dca->dca_ic = IC_IE; 12841480Smckusick /* 129*49130Skarels * Need to reset baud rate, etc. of next print so reset dcaconsinit. 130*49130Skarels * Also make sure console is always "hardwired." 13141480Smckusick */ 13241480Smckusick if (unit == dcaconsole) { 133*49130Skarels dcaconsinit = 0; 13441480Smckusick dcasoftCAR |= (1 << unit); 13541480Smckusick } 13641480Smckusick return (1); 13741480Smckusick } 13841480Smckusick 139*49130Skarels /* ARGSUSED */ 140*49130Skarels #ifdef __STDC__ 141*49130Skarels dcaopen(dev_t dev, int flag, int mode, struct proc *p) 142*49130Skarels #else 143*49130Skarels dcaopen(dev, flag, mode, p) 14441480Smckusick dev_t dev; 145*49130Skarels int flag, mode; 146*49130Skarels struct proc *p; 147*49130Skarels #endif 14841480Smckusick { 14941480Smckusick register struct tty *tp; 15041480Smckusick register int unit; 15144762Skarels int error = 0; 15241480Smckusick 15341480Smckusick unit = UNIT(dev); 15441480Smckusick if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 15541480Smckusick return (ENXIO); 15641480Smckusick tp = &dca_tty[unit]; 15741480Smckusick tp->t_oproc = dcastart; 15841480Smckusick tp->t_param = dcaparam; 15941480Smckusick tp->t_dev = dev; 16041480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 16142950Smarc tp->t_state |= TS_WOPEN; 16241480Smckusick ttychars(tp); 163*49130Skarels if (tp->t_ispeed == 0) { 164*49130Skarels tp->t_iflag = TTYDEF_IFLAG; 165*49130Skarels tp->t_oflag = TTYDEF_OFLAG; 166*49130Skarels tp->t_cflag = TTYDEF_CFLAG; 167*49130Skarels tp->t_lflag = TTYDEF_LFLAG; 168*49130Skarels tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 169*49130Skarels } 17041480Smckusick dcaparam(tp, &tp->t_termios); 17141480Smckusick ttsetwater(tp); 172*49130Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 17341480Smckusick return (EBUSY); 17441480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 17541480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 17641480Smckusick tp->t_state |= TS_CARR_ON; 17741480Smckusick (void) spltty(); 17844295Shibler while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 17941480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 18041480Smckusick tp->t_state |= TS_WOPEN; 18144295Shibler if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 18244295Shibler ttopen, 0)) 18344295Shibler break; 18441480Smckusick } 18541480Smckusick (void) spl0(); 18644295Shibler if (error == 0) 18744295Shibler error = (*linesw[tp->t_line].l_open)(dev, tp); 18844295Shibler return (error); 18941480Smckusick } 19041480Smckusick 19141480Smckusick /*ARGSUSED*/ 19241480Smckusick dcaclose(dev, flag) 19341480Smckusick dev_t dev; 19441480Smckusick { 19541480Smckusick register struct tty *tp; 19641480Smckusick register struct dcadevice *dca; 19741480Smckusick register int unit; 19841480Smckusick 19941480Smckusick unit = UNIT(dev); 20041480Smckusick dca = dca_addr[unit]; 20141480Smckusick tp = &dca_tty[unit]; 20241480Smckusick (*linesw[tp->t_line].l_close)(tp); 20341480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 20441480Smckusick #ifdef KGDB 20541480Smckusick /* do not disable interrupts if debugging */ 206*49130Skarels if (dev != kgdb_dev) 20741480Smckusick #endif 20841480Smckusick dca->dca_ier = 0; 209*49130Skarels (void) dcamctl(dev, 0, DMSET); 210*49130Skarels if (tp->t_state & TS_HUPCLS) 211*49130Skarels (*linesw[tp->t_line].l_modem)(tp, 0); 21241480Smckusick ttyclose(tp); 21341480Smckusick return(0); 21441480Smckusick } 21541480Smckusick 21641480Smckusick dcaread(dev, uio, flag) 21741480Smckusick dev_t dev; 21841480Smckusick struct uio *uio; 21941480Smckusick { 22041480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 22141480Smckusick 22241480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 22341480Smckusick } 22441480Smckusick 22541480Smckusick dcawrite(dev, uio, flag) 22641480Smckusick dev_t dev; 22741480Smckusick struct uio *uio; 22841480Smckusick { 22941480Smckusick int unit = UNIT(dev); 23041480Smckusick register struct tty *tp = &dca_tty[unit]; 23141480Smckusick 23242353Smckusick /* 23342353Smckusick * (XXX) We disallow virtual consoles if the physical console is 23442353Smckusick * a serial port. This is in case there is a display attached that 23542353Smckusick * is not the console. In that situation we don't need/want the X 23642353Smckusick * server taking over the console. 23742353Smckusick */ 23842353Smckusick if (constty && unit == dcaconsole) 23942353Smckusick constty = NULL; 24041480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 24141480Smckusick } 24241480Smckusick 24341480Smckusick dcaintr(unit) 24441480Smckusick register int unit; 24541480Smckusick { 24641480Smckusick register struct dcadevice *dca; 24744318Shibler register u_char code; 24844318Shibler register struct tty *tp; 24941480Smckusick 25041480Smckusick dca = dca_addr[unit]; 25141480Smckusick if ((dca->dca_ic & IC_IR) == 0) 25241480Smckusick return(0); 25344318Shibler while (1) { 25444318Shibler code = dca->dca_iir; 25544318Shibler switch (code) { 25644318Shibler case IIR_NOPEND: 25744318Shibler return (1); 25844318Shibler case IIR_RXRDY: 25944318Shibler /* do time-critical read in-line */ 26044318Shibler tp = &dca_tty[unit]; 26144318Shibler code = dca->dca_data; 26244318Shibler if ((tp->t_state & TS_ISOPEN) == 0) { 26344318Shibler #ifdef KGDB 264*49130Skarels if (kgdb_dev == makedev(dcamajor, unit) && 265*49130Skarels code == FRAME_END) 266*49130Skarels kgdb_connect(0); /* trap into kgdb */ 26744318Shibler #endif 26844318Shibler } else 26944318Shibler (*linesw[tp->t_line].l_rint)(code, tp); 27044318Shibler break; 27144318Shibler case IIR_TXRDY: 27244318Shibler tp = &dca_tty[unit]; 27344318Shibler tp->t_state &=~ (TS_BUSY|TS_FLUSH); 27444318Shibler if (tp->t_line) 27544318Shibler (*linesw[tp->t_line].l_start)(tp); 27644318Shibler else 27744318Shibler dcastart(tp); 27844318Shibler break; 27944318Shibler case IIR_RLS: 28041480Smckusick dcaeint(unit, dca); 28144318Shibler break; 28244318Shibler default: 28344318Shibler if (code & IIR_NOPEND) 28444318Shibler return (1); 28544318Shibler log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 28644318Shibler unit, code); 28744318Shibler /* fall through */ 28844318Shibler case IIR_MLSC: 28941480Smckusick dcamint(unit, dca); 29044318Shibler break; 29144318Shibler } 29241480Smckusick } 29341480Smckusick } 29441480Smckusick 29541480Smckusick dcaeint(unit, dca) 29641480Smckusick register int unit; 29741480Smckusick register struct dcadevice *dca; 29841480Smckusick { 29941480Smckusick register struct tty *tp; 30041480Smckusick register int stat, c; 30141480Smckusick 30241480Smckusick tp = &dca_tty[unit]; 30341480Smckusick stat = dca->dca_lsr; 30444318Shibler c = dca->dca_data; 30541480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 30641480Smckusick #ifdef KGDB 30741480Smckusick /* we don't care about parity errors */ 30841480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 309*49130Skarels kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 310*49130Skarels kgdb_connect(0); /* trap into kgdb */ 31141480Smckusick #endif 31241480Smckusick return; 31341480Smckusick } 31441480Smckusick if (stat & (LSR_BI | LSR_FE)) 31541480Smckusick c |= TTY_FE; 31641480Smckusick else if (stat & LSR_PE) 31741480Smckusick c |= TTY_PE; 31841480Smckusick else if (stat & LSR_OE) 31941480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 32041480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 32141480Smckusick } 32241480Smckusick 32341480Smckusick dcamint(unit, dca) 32441480Smckusick register int unit; 32541480Smckusick register struct dcadevice *dca; 32641480Smckusick { 32741480Smckusick register struct tty *tp; 32841480Smckusick register int stat; 32941480Smckusick 33041480Smckusick tp = &dca_tty[unit]; 33141480Smckusick stat = dca->dca_msr; 33244318Shibler if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 33341480Smckusick if (stat & MSR_DCD) 33444318Shibler (void)(*linesw[tp->t_line].l_modem)(tp, 1); 33541480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 33641480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 33744318Shibler } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 33844318Shibler (tp->t_flags & CRTSCTS)) { 33944318Shibler /* the line is up and we want to do rts/cts flow control */ 34044318Shibler if (stat & MSR_CTS) { 34144318Shibler tp->t_state &=~ TS_TTSTOP; 34244318Shibler ttstart(tp); 34344318Shibler } else 34444318Shibler tp->t_state |= TS_TTSTOP; 34541480Smckusick } 34641480Smckusick } 34741480Smckusick 34841480Smckusick dcaioctl(dev, cmd, data, flag) 34941480Smckusick dev_t dev; 35041480Smckusick caddr_t data; 35141480Smckusick { 35241480Smckusick register struct tty *tp; 35341480Smckusick register int unit = UNIT(dev); 35441480Smckusick register struct dcadevice *dca; 35541480Smckusick register int error; 35641480Smckusick 35741480Smckusick tp = &dca_tty[unit]; 35841480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 35941480Smckusick if (error >= 0) 36041480Smckusick return (error); 36141480Smckusick error = ttioctl(tp, cmd, data, flag); 36241480Smckusick if (error >= 0) 36341480Smckusick return (error); 36441480Smckusick 36541480Smckusick dca = dca_addr[unit]; 36641480Smckusick switch (cmd) { 36741480Smckusick 36841480Smckusick case TIOCSBRK: 36941480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 37041480Smckusick break; 37141480Smckusick 37241480Smckusick case TIOCCBRK: 37341480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 37441480Smckusick break; 37541480Smckusick 37641480Smckusick case TIOCSDTR: 37741480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 37841480Smckusick break; 37941480Smckusick 38041480Smckusick case TIOCCDTR: 38141480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 38241480Smckusick break; 38341480Smckusick 38441480Smckusick case TIOCMSET: 38541480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 38641480Smckusick break; 38741480Smckusick 38841480Smckusick case TIOCMBIS: 38941480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 39041480Smckusick break; 39141480Smckusick 39241480Smckusick case TIOCMBIC: 39341480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 39441480Smckusick break; 39541480Smckusick 39641480Smckusick case TIOCMGET: 39741480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 39841480Smckusick break; 39941480Smckusick 40041480Smckusick default: 40141480Smckusick return (ENOTTY); 40241480Smckusick } 40341480Smckusick return (0); 40441480Smckusick } 40541480Smckusick 40641480Smckusick dcaparam(tp, t) 40741480Smckusick register struct tty *tp; 40841480Smckusick register struct termios *t; 40941480Smckusick { 41041480Smckusick register struct dcadevice *dca; 41141480Smckusick register int cfcr, cflag = t->c_cflag; 41241480Smckusick int unit = UNIT(tp->t_dev); 41341480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 41441480Smckusick 41541480Smckusick /* check requested parameters */ 41641480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 41741480Smckusick return(EINVAL); 41841480Smckusick /* and copy to tty */ 41941480Smckusick tp->t_ispeed = t->c_ispeed; 42041480Smckusick tp->t_ospeed = t->c_ospeed; 42141480Smckusick tp->t_cflag = cflag; 42241480Smckusick 42341480Smckusick dca = dca_addr[unit]; 42441480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 42541480Smckusick if (ospeed == 0) { 42641480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 42741480Smckusick return(0); 42841480Smckusick } 42941480Smckusick dca->dca_cfcr |= CFCR_DLAB; 43041480Smckusick dca->dca_data = ospeed & 0xFF; 43141480Smckusick dca->dca_ier = ospeed >> 8; 43241480Smckusick switch (cflag&CSIZE) { 43341480Smckusick case CS5: 43441480Smckusick cfcr = CFCR_5BITS; break; 43541480Smckusick case CS6: 43641480Smckusick cfcr = CFCR_6BITS; break; 43741480Smckusick case CS7: 43841480Smckusick cfcr = CFCR_7BITS; break; 43941480Smckusick case CS8: 44041480Smckusick cfcr = CFCR_8BITS; break; 44141480Smckusick } 44241480Smckusick if (cflag&PARENB) { 44341480Smckusick cfcr |= CFCR_PENAB; 44441480Smckusick if ((cflag&PARODD) == 0) 44541480Smckusick cfcr |= CFCR_PEVEN; 44641480Smckusick } 44741480Smckusick if (cflag&CSTOPB) 44841480Smckusick cfcr |= CFCR_STOPB; 44941480Smckusick dca->dca_cfcr = cfcr; 45041480Smckusick return(0); 45141480Smckusick } 45241480Smckusick 45341480Smckusick dcastart(tp) 45441480Smckusick register struct tty *tp; 45541480Smckusick { 45641480Smckusick register struct dcadevice *dca; 45741480Smckusick int s, unit, c; 45841480Smckusick 45941480Smckusick unit = UNIT(tp->t_dev); 46041480Smckusick dca = dca_addr[unit]; 46141480Smckusick s = spltty(); 46244318Shibler if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 46341480Smckusick goto out; 46441480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 46541480Smckusick if (tp->t_state&TS_ASLEEP) { 46641480Smckusick tp->t_state &= ~TS_ASLEEP; 46741480Smckusick wakeup((caddr_t)&tp->t_outq); 46841480Smckusick } 46941480Smckusick if (tp->t_wsel) { 47041480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 47141480Smckusick tp->t_wsel = 0; 47241480Smckusick tp->t_state &= ~TS_WCOLL; 47341480Smckusick } 47441480Smckusick } 47541480Smckusick if (tp->t_outq.c_cc == 0) 47641480Smckusick goto out; 47744318Shibler if (dca->dca_lsr & LSR_TXRDY) { 47844318Shibler c = getc(&tp->t_outq); 47944318Shibler tp->t_state |= TS_BUSY; 48044318Shibler dca->dca_data = c; 48144318Shibler } 48241480Smckusick out: 48341480Smckusick splx(s); 48441480Smckusick } 48541480Smckusick 48641480Smckusick /* 48741480Smckusick * Stop output on a line. 48841480Smckusick */ 48941480Smckusick /*ARGSUSED*/ 49041480Smckusick dcastop(tp, flag) 49141480Smckusick register struct tty *tp; 49241480Smckusick { 49341480Smckusick register int s; 49441480Smckusick 49541480Smckusick s = spltty(); 49641480Smckusick if (tp->t_state & TS_BUSY) { 49741480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 49841480Smckusick tp->t_state |= TS_FLUSH; 49941480Smckusick } 50041480Smckusick splx(s); 50141480Smckusick } 50241480Smckusick 50341480Smckusick dcamctl(dev, bits, how) 50441480Smckusick dev_t dev; 50541480Smckusick int bits, how; 50641480Smckusick { 50741480Smckusick register struct dcadevice *dca; 50841480Smckusick register int unit; 50941480Smckusick int s; 51041480Smckusick 51141480Smckusick unit = UNIT(dev); 51241480Smckusick dca = dca_addr[unit]; 51341480Smckusick s = spltty(); 51441480Smckusick switch (how) { 51541480Smckusick 51641480Smckusick case DMSET: 51741480Smckusick dca->dca_mcr = bits; 51841480Smckusick break; 51941480Smckusick 52041480Smckusick case DMBIS: 52141480Smckusick dca->dca_mcr |= bits; 52241480Smckusick break; 52341480Smckusick 52441480Smckusick case DMBIC: 52541480Smckusick dca->dca_mcr &= ~bits; 52641480Smckusick break; 52741480Smckusick 52841480Smckusick case DMGET: 52941480Smckusick bits = dca->dca_msr; 53041480Smckusick break; 53141480Smckusick } 53241480Smckusick (void) splx(s); 53341480Smckusick return(bits); 53441480Smckusick } 53541480Smckusick 53641480Smckusick /* 53741480Smckusick * Following are all routines needed for DCA to act as console 53841480Smckusick */ 53945788Sbostic #include "../hp300/cons.h" 54041480Smckusick 54141480Smckusick dcacnprobe(cp) 54241480Smckusick struct consdev *cp; 54341480Smckusick { 54441480Smckusick int unit, i; 54541480Smckusick 546*49130Skarels /* locate the major number */ 547*49130Skarels for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 548*49130Skarels if (cdevsw[dcamajor].d_open == dcaopen) 549*49130Skarels break; 550*49130Skarels 55141480Smckusick /* XXX: ick */ 55241480Smckusick unit = CONUNIT; 55341480Smckusick dca_addr[CONUNIT] = CONADDR; 55441480Smckusick 55541480Smckusick /* make sure hardware exists */ 55641480Smckusick if (badaddr((short *)dca_addr[unit])) { 55741480Smckusick cp->cn_pri = CN_DEAD; 55841480Smckusick return; 55941480Smckusick } 56041480Smckusick 56141480Smckusick /* initialize required fields */ 562*49130Skarels cp->cn_dev = makedev(dcamajor, unit); 56341480Smckusick cp->cn_tp = &dca_tty[unit]; 56441480Smckusick switch (dca_addr[unit]->dca_irid) { 56541480Smckusick case DCAID0: 56641480Smckusick case DCAID1: 56741480Smckusick cp->cn_pri = CN_NORMAL; 56841480Smckusick break; 56941480Smckusick case DCAREMID0: 57041480Smckusick case DCAREMID1: 57141480Smckusick cp->cn_pri = CN_REMOTE; 57241480Smckusick break; 57341480Smckusick default: 57441480Smckusick cp->cn_pri = CN_DEAD; 57541480Smckusick break; 57641480Smckusick } 577*49130Skarels /* 578*49130Skarels * If dcmconsole is initialized, raise our priority. 579*49130Skarels */ 580*49130Skarels if (dcaconsole == unit) 581*49130Skarels cp->cn_pri = CN_REMOTE; 582*49130Skarels if (major(kgdb_dev) == 1) /* XXX */ 583*49130Skarels kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 58441480Smckusick } 58541480Smckusick 58641480Smckusick dcacninit(cp) 58741480Smckusick struct consdev *cp; 58841480Smckusick { 58941480Smckusick int unit = UNIT(cp->cn_dev); 59041480Smckusick 591*49130Skarels dcainit(unit, dcadefaultrate); 59241480Smckusick dcaconsole = unit; 593*49130Skarels dcaconsinit = 1; 59441480Smckusick } 59541480Smckusick 596*49130Skarels dcainit(unit, rate) 597*49130Skarels int unit, rate; 59841480Smckusick { 59941480Smckusick register struct dcadevice *dca; 600*49130Skarels int s; 60141480Smckusick short stat; 60241480Smckusick 60341480Smckusick #ifdef lint 60441480Smckusick stat = unit; if (stat) return; 60541480Smckusick #endif 60641480Smckusick dca = dca_addr[unit]; 60741480Smckusick s = splhigh(); 60841480Smckusick dca->dca_irid = 0xFF; 60941480Smckusick DELAY(100); 61041480Smckusick dca->dca_ic = IC_IE; 61141480Smckusick dca->dca_cfcr = CFCR_DLAB; 612*49130Skarels rate = ttspeedtab(rate, dcaspeedtab); 61341480Smckusick dca->dca_data = rate & 0xFF; 61441480Smckusick dca->dca_ier = rate >> 8; 61541480Smckusick dca->dca_cfcr = CFCR_8BITS; 61641480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 61741480Smckusick stat = dca->dca_iir; 61841480Smckusick splx(s); 61941480Smckusick } 62041480Smckusick 62141480Smckusick dcacngetc(dev) 62241480Smckusick { 62341480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 62441480Smckusick short stat; 62541480Smckusick int c, s; 62641480Smckusick 62741480Smckusick #ifdef lint 62841480Smckusick stat = dev; if (stat) return(0); 62941480Smckusick #endif 63041480Smckusick s = splhigh(); 63141480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 63241480Smckusick ; 63341480Smckusick c = dca->dca_data; 63441480Smckusick stat = dca->dca_iir; 63541480Smckusick splx(s); 63641480Smckusick return(c); 63741480Smckusick } 63841480Smckusick 63941480Smckusick /* 64041480Smckusick * Console kernel output character routine. 64141480Smckusick */ 64241480Smckusick dcacnputc(dev, c) 64341480Smckusick dev_t dev; 64441480Smckusick register int c; 64541480Smckusick { 64641480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 64741480Smckusick register int timo; 64841480Smckusick short stat; 64941480Smckusick int s = splhigh(); 65041480Smckusick 65141480Smckusick #ifdef lint 65241480Smckusick stat = dev; if (stat) return; 65341480Smckusick #endif 654*49130Skarels #ifdef KGDB 655*49130Skarels if (dev != kgdb_dev) 656*49130Skarels #endif 657*49130Skarels if (dcaconsinit == 0) { 658*49130Skarels (void) dcainit(UNIT(dev), dcadefaultrate); 659*49130Skarels dcaconsinit = 1; 66041480Smckusick } 66141480Smckusick /* wait for any pending transmission to finish */ 66241480Smckusick timo = 50000; 66341480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 66441480Smckusick ; 66541480Smckusick dca->dca_data = c; 66641480Smckusick /* wait for this transmission to complete */ 66741480Smckusick timo = 1500000; 66841480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 66941480Smckusick ; 67041480Smckusick /* clear any interrupts generated by this transmission */ 67141480Smckusick stat = dca->dca_iir; 67241480Smckusick splx(s); 67341480Smckusick } 67441480Smckusick #endif 675