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*52389Smckusick * @(#)dca.c 7.13 (Berkeley) 02/05/92 841480Smckusick */ 941480Smckusick 1041480Smckusick #include "dca.h" 1141480Smckusick #if NDCA > 0 1241480Smckusick /* 1341480Smckusick * 98626/98644/internal serial interface 1449300Shibler * uses National Semiconductor INS8250/NS16550AF UART 1541480Smckusick */ 1645788Sbostic #include "sys/param.h" 1745788Sbostic #include "sys/systm.h" 1845788Sbostic #include "sys/ioctl.h" 1945788Sbostic #include "sys/tty.h" 2049130Skarels #include "sys/proc.h" 2145788Sbostic #include "sys/conf.h" 2245788Sbostic #include "sys/file.h" 2345788Sbostic #include "sys/uio.h" 2445788Sbostic #include "sys/kernel.h" 2545788Sbostic #include "sys/syslog.h" 2641480Smckusick 2741480Smckusick #include "device.h" 2841480Smckusick #include "dcareg.h" 2949130Skarels #include "machine/cpu.h" 3045788Sbostic #include "../hp300/isr.h" 3141480Smckusick 3241480Smckusick int dcaprobe(); 3341480Smckusick struct driver dcadriver = { 3441480Smckusick dcaprobe, "dca", 3541480Smckusick }; 3641480Smckusick 37*52389Smckusick void dcastart(); 38*52389Smckusick int dcaparam(), dcaintr(); 3941480Smckusick int dcasoftCAR; 4041480Smckusick int dca_active; 4149300Shibler int dca_hasfifo; 4241480Smckusick int ndca = NDCA; 4349130Skarels #ifdef DCACONSOLE 4449130Skarels int dcaconsole = DCACONSOLE; 4549130Skarels #else 4641480Smckusick int dcaconsole = -1; 4749130Skarels #endif 4849130Skarels int dcaconsinit; 4941480Smckusick int dcadefaultrate = TTYDEF_SPEED; 5049130Skarels int dcamajor; 5141480Smckusick struct dcadevice *dca_addr[NDCA]; 5241480Smckusick struct tty dca_tty[NDCA]; 5341480Smckusick struct isr dcaisr[NDCA]; 5441480Smckusick 5541480Smckusick struct speedtab dcaspeedtab[] = { 5641480Smckusick 0, 0, 5741480Smckusick 50, DCABRD(50), 5841480Smckusick 75, DCABRD(75), 5941480Smckusick 110, DCABRD(110), 6041480Smckusick 134, DCABRD(134), 6141480Smckusick 150, DCABRD(150), 6241480Smckusick 200, DCABRD(200), 6341480Smckusick 300, DCABRD(300), 6441480Smckusick 600, DCABRD(600), 6541480Smckusick 1200, DCABRD(1200), 6641480Smckusick 1800, DCABRD(1800), 6741480Smckusick 2400, DCABRD(2400), 6841480Smckusick 4800, DCABRD(4800), 6941480Smckusick 9600, DCABRD(9600), 7041480Smckusick 19200, DCABRD(19200), 7141480Smckusick 38400, DCABRD(38400), 7241480Smckusick -1, -1 7341480Smckusick }; 7441480Smckusick 7541480Smckusick extern struct tty *constty; 7641480Smckusick #ifdef KGDB 7749130Skarels #include "machine/remote-sl.h" 7849130Skarels 7950219Skarels extern dev_t kgdb_dev; 8041480Smckusick extern int kgdb_rate; 8141480Smckusick extern int kgdb_debug_init; 8241480Smckusick #endif 8341480Smckusick 8441480Smckusick #define UNIT(x) minor(x) 8541480Smckusick 8649300Shibler #ifdef DEBUG 8749300Shibler long fifoin[17]; 8849300Shibler long fifoout[17]; 8949300Shibler long dcaintrcount[16]; 9049300Shibler long dcamintcount[16]; 9149300Shibler #endif 9249300Shibler 9341480Smckusick dcaprobe(hd) 9441480Smckusick register struct hp_device *hd; 9541480Smckusick { 9641480Smckusick register struct dcadevice *dca; 9741480Smckusick register int unit; 9841480Smckusick 9941480Smckusick dca = (struct dcadevice *)hd->hp_addr; 10041480Smckusick if (dca->dca_irid != DCAID0 && 10141480Smckusick dca->dca_irid != DCAREMID0 && 10241480Smckusick dca->dca_irid != DCAID1 && 10341480Smckusick dca->dca_irid != DCAREMID1) 10441480Smckusick return (0); 10541480Smckusick unit = hd->hp_unit; 10641480Smckusick if (unit == dcaconsole) 10741480Smckusick DELAY(100000); 10841480Smckusick dca->dca_irid = 0xFF; 10941480Smckusick DELAY(100); 11041480Smckusick 11149300Shibler /* look for a NS 16550AF UART with FIFOs */ 11249300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 11349300Shibler DELAY(100); 11449300Shibler if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) 11549300Shibler dca_hasfifo |= 1 << unit; 11649300Shibler 11741480Smckusick hd->hp_ipl = DCAIPL(dca->dca_ic); 11841480Smckusick dcaisr[unit].isr_ipl = hd->hp_ipl; 11941480Smckusick dcaisr[unit].isr_arg = unit; 12041480Smckusick dcaisr[unit].isr_intr = dcaintr; 12141480Smckusick dca_addr[unit] = dca; 12241480Smckusick dca_active |= 1 << unit; 12341480Smckusick dcasoftCAR = hd->hp_flags; 12441480Smckusick isrlink(&dcaisr[unit]); 12541480Smckusick #ifdef KGDB 12649130Skarels if (kgdb_dev == makedev(dcamajor, unit)) { 12741480Smckusick if (dcaconsole == unit) 12850219Skarels kgdb_dev = NODEV; /* can't debug over console port */ 12941480Smckusick else { 13049130Skarels (void) dcainit(unit, kgdb_rate); 13150219Skarels dcaconsinit = 1; /* don't re-init in dcaputc */ 13241480Smckusick if (kgdb_debug_init) { 13349130Skarels /* 13449130Skarels * Print prefix of device name, 13549130Skarels * let kgdb_connect print the rest. 13649130Skarels */ 13749130Skarels printf("dca%d: ", unit); 13849130Skarels kgdb_connect(1); 13941480Smckusick } else 14041480Smckusick printf("dca%d: kgdb enabled\n", unit); 14141480Smckusick } 14241480Smckusick } 14341480Smckusick #endif 14441480Smckusick dca->dca_ic = IC_IE; 14541480Smckusick /* 14649130Skarels * Need to reset baud rate, etc. of next print so reset dcaconsinit. 14749130Skarels * Also make sure console is always "hardwired." 14841480Smckusick */ 14941480Smckusick if (unit == dcaconsole) { 15049130Skarels dcaconsinit = 0; 15141480Smckusick dcasoftCAR |= (1 << unit); 15241480Smckusick } 15341480Smckusick return (1); 15441480Smckusick } 15541480Smckusick 15649130Skarels /* ARGSUSED */ 15749130Skarels #ifdef __STDC__ 15849130Skarels dcaopen(dev_t dev, int flag, int mode, struct proc *p) 15949130Skarels #else 16049130Skarels dcaopen(dev, flag, mode, p) 16141480Smckusick dev_t dev; 16249130Skarels int flag, mode; 16349130Skarels struct proc *p; 16449130Skarels #endif 16541480Smckusick { 16641480Smckusick register struct tty *tp; 16741480Smckusick register int unit; 16844762Skarels int error = 0; 16941480Smckusick 17041480Smckusick unit = UNIT(dev); 17141480Smckusick if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 17241480Smckusick return (ENXIO); 17341480Smckusick tp = &dca_tty[unit]; 17441480Smckusick tp->t_oproc = dcastart; 17541480Smckusick tp->t_param = dcaparam; 17641480Smckusick tp->t_dev = dev; 17741480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 17842950Smarc tp->t_state |= TS_WOPEN; 17941480Smckusick ttychars(tp); 18049130Skarels if (tp->t_ispeed == 0) { 18149130Skarels tp->t_iflag = TTYDEF_IFLAG; 18249130Skarels tp->t_oflag = TTYDEF_OFLAG; 18349130Skarels tp->t_cflag = TTYDEF_CFLAG; 18449130Skarels tp->t_lflag = TTYDEF_LFLAG; 18549130Skarels tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 18649130Skarels } 18741480Smckusick dcaparam(tp, &tp->t_termios); 18841480Smckusick ttsetwater(tp); 18949130Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 19041480Smckusick return (EBUSY); 19141480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 19241480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 19341480Smckusick tp->t_state |= TS_CARR_ON; 19441480Smckusick (void) spltty(); 19544295Shibler while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 19641480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 19741480Smckusick tp->t_state |= TS_WOPEN; 19844295Shibler if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 19944295Shibler ttopen, 0)) 20044295Shibler break; 20141480Smckusick } 20241480Smckusick (void) spl0(); 20344295Shibler if (error == 0) 20444295Shibler error = (*linesw[tp->t_line].l_open)(dev, tp); 20544295Shibler return (error); 20641480Smckusick } 20741480Smckusick 20841480Smckusick /*ARGSUSED*/ 20949750Smarc dcaclose(dev, flag, mode, p) 21041480Smckusick dev_t dev; 21149750Smarc int flag, mode; 21249750Smarc struct proc *p; 21341480Smckusick { 21441480Smckusick register struct tty *tp; 21541480Smckusick register struct dcadevice *dca; 21641480Smckusick register int unit; 21741480Smckusick 21841480Smckusick unit = UNIT(dev); 21941480Smckusick dca = dca_addr[unit]; 22041480Smckusick tp = &dca_tty[unit]; 22149750Smarc (*linesw[tp->t_line].l_close)(tp, flag); 22241480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 22341480Smckusick #ifdef KGDB 22441480Smckusick /* do not disable interrupts if debugging */ 22549130Skarels if (dev != kgdb_dev) 22641480Smckusick #endif 22741480Smckusick dca->dca_ier = 0; 22850219Skarels if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 22950219Skarels (tp->t_state&TS_ISOPEN) == 0) 23050219Skarels (void) dcamctl(dev, 0, DMSET); 23141480Smckusick ttyclose(tp); 23250219Skarels return (0); 23341480Smckusick } 23441480Smckusick 23541480Smckusick dcaread(dev, uio, flag) 23641480Smckusick dev_t dev; 23741480Smckusick struct uio *uio; 23841480Smckusick { 23941480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 24041480Smckusick 24141480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 24241480Smckusick } 24341480Smckusick 24441480Smckusick dcawrite(dev, uio, flag) 24541480Smckusick dev_t dev; 24641480Smckusick struct uio *uio; 24741480Smckusick { 24841480Smckusick int unit = UNIT(dev); 24941480Smckusick register struct tty *tp = &dca_tty[unit]; 25041480Smckusick 25142353Smckusick /* 25242353Smckusick * (XXX) We disallow virtual consoles if the physical console is 25342353Smckusick * a serial port. This is in case there is a display attached that 25442353Smckusick * is not the console. In that situation we don't need/want the X 25542353Smckusick * server taking over the console. 25642353Smckusick */ 25742353Smckusick if (constty && unit == dcaconsole) 25842353Smckusick constty = NULL; 25941480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 26041480Smckusick } 26141480Smckusick 26241480Smckusick dcaintr(unit) 26341480Smckusick register int unit; 26441480Smckusick { 26541480Smckusick register struct dcadevice *dca; 26644318Shibler register u_char code; 26744318Shibler register struct tty *tp; 26841480Smckusick 26941480Smckusick dca = dca_addr[unit]; 27041480Smckusick if ((dca->dca_ic & IC_IR) == 0) 27150219Skarels return (0); 27244318Shibler while (1) { 27344318Shibler code = dca->dca_iir; 27449300Shibler #ifdef DEBUG 27549300Shibler dcaintrcount[code & IIR_IMASK]++; 27649300Shibler #endif 27749300Shibler switch (code & IIR_IMASK) { 27844318Shibler case IIR_NOPEND: 27944318Shibler return (1); 28049300Shibler case IIR_RXTOUT: 28144318Shibler case IIR_RXRDY: 28244318Shibler /* do time-critical read in-line */ 28344318Shibler tp = &dca_tty[unit]; 28449300Shibler /* 28549300Shibler * Process a received byte. Inline for speed... 28649300Shibler */ 28744318Shibler #ifdef KGDB 28849300Shibler #define RCVBYTE() \ 28949300Shibler code = dca->dca_data; \ 29049300Shibler if ((tp->t_state & TS_ISOPEN) == 0) { \ 29150219Skarels if (code == FRAME_END && \ 29250219Skarels kgdb_dev == makedev(dcamajor, unit)) \ 29349300Shibler kgdb_connect(0); /* trap into kgdb */ \ 29449300Shibler } else \ 29549300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 29649300Shibler #else 29749300Shibler #define RCVBYTE() \ 29849300Shibler code = dca->dca_data; \ 29949300Shibler if ((tp->t_state & TS_ISOPEN) != 0) \ 30049300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 30144318Shibler #endif 30249300Shibler RCVBYTE(); 30349300Shibler if (dca_hasfifo & (1 << unit)) { 30449300Shibler #ifdef DEBUG 30549300Shibler register int fifocnt = 1; 30649300Shibler #endif 30749300Shibler while ((code = dca->dca_lsr) & LSR_RCV_MASK) { 30849300Shibler if (code == LSR_RXRDY) { 30949300Shibler RCVBYTE(); 31049300Shibler } else 31149300Shibler dcaeint(unit, code, dca); 31249300Shibler #ifdef DEBUG 31349300Shibler fifocnt++; 31449300Shibler #endif 31549300Shibler } 31649300Shibler #ifdef DEBUG 31749300Shibler if (fifocnt > 16) 31849300Shibler fifoin[0]++; 31949300Shibler else 32049300Shibler fifoin[fifocnt]++; 32149300Shibler #endif 32249300Shibler } 32344318Shibler break; 32444318Shibler case IIR_TXRDY: 32544318Shibler tp = &dca_tty[unit]; 32644318Shibler tp->t_state &=~ (TS_BUSY|TS_FLUSH); 32744318Shibler if (tp->t_line) 32844318Shibler (*linesw[tp->t_line].l_start)(tp); 32944318Shibler else 33044318Shibler dcastart(tp); 33144318Shibler break; 33244318Shibler case IIR_RLS: 33349300Shibler dcaeint(unit, dca->dca_lsr, dca); 33444318Shibler break; 33544318Shibler default: 33644318Shibler if (code & IIR_NOPEND) 33744318Shibler return (1); 33844318Shibler log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 33944318Shibler unit, code); 34044318Shibler /* fall through */ 34144318Shibler case IIR_MLSC: 34241480Smckusick dcamint(unit, dca); 34344318Shibler break; 34444318Shibler } 34541480Smckusick } 34641480Smckusick } 34741480Smckusick 34849300Shibler dcaeint(unit, stat, dca) 34949300Shibler register int unit, stat; 35041480Smckusick register struct dcadevice *dca; 35141480Smckusick { 35241480Smckusick register struct tty *tp; 35349300Shibler register int c; 35441480Smckusick 35541480Smckusick tp = &dca_tty[unit]; 35644318Shibler c = dca->dca_data; 35741480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 35841480Smckusick #ifdef KGDB 35941480Smckusick /* we don't care about parity errors */ 36041480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 36149130Skarels kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 36249130Skarels kgdb_connect(0); /* trap into kgdb */ 36341480Smckusick #endif 36441480Smckusick return; 36541480Smckusick } 36641480Smckusick if (stat & (LSR_BI | LSR_FE)) 36741480Smckusick c |= TTY_FE; 36841480Smckusick else if (stat & LSR_PE) 36941480Smckusick c |= TTY_PE; 37041480Smckusick else if (stat & LSR_OE) 37141480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 37241480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 37341480Smckusick } 37441480Smckusick 37541480Smckusick dcamint(unit, dca) 37641480Smckusick register int unit; 37741480Smckusick register struct dcadevice *dca; 37841480Smckusick { 37941480Smckusick register struct tty *tp; 38041480Smckusick register int stat; 38141480Smckusick 38241480Smckusick tp = &dca_tty[unit]; 38341480Smckusick stat = dca->dca_msr; 38449300Shibler #ifdef DEBUG 38549300Shibler dcamintcount[stat & 0xf]++; 38649300Shibler #endif 38744318Shibler if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 38841480Smckusick if (stat & MSR_DCD) 38944318Shibler (void)(*linesw[tp->t_line].l_modem)(tp, 1); 39041480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 39141480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 39244318Shibler } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 39344318Shibler (tp->t_flags & CRTSCTS)) { 39444318Shibler /* the line is up and we want to do rts/cts flow control */ 39544318Shibler if (stat & MSR_CTS) { 39644318Shibler tp->t_state &=~ TS_TTSTOP; 39744318Shibler ttstart(tp); 39844318Shibler } else 39944318Shibler tp->t_state |= TS_TTSTOP; 40041480Smckusick } 40141480Smckusick } 40241480Smckusick 40341480Smckusick dcaioctl(dev, cmd, data, flag) 40441480Smckusick dev_t dev; 40541480Smckusick caddr_t data; 40641480Smckusick { 40741480Smckusick register struct tty *tp; 40841480Smckusick register int unit = UNIT(dev); 40941480Smckusick register struct dcadevice *dca; 41041480Smckusick register int error; 41141480Smckusick 41241480Smckusick tp = &dca_tty[unit]; 41341480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 41441480Smckusick if (error >= 0) 41541480Smckusick return (error); 41641480Smckusick error = ttioctl(tp, cmd, data, flag); 41741480Smckusick if (error >= 0) 41841480Smckusick return (error); 41941480Smckusick 42041480Smckusick dca = dca_addr[unit]; 42141480Smckusick switch (cmd) { 42241480Smckusick 42341480Smckusick case TIOCSBRK: 42441480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 42541480Smckusick break; 42641480Smckusick 42741480Smckusick case TIOCCBRK: 42841480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 42941480Smckusick break; 43041480Smckusick 43141480Smckusick case TIOCSDTR: 43241480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 43341480Smckusick break; 43441480Smckusick 43541480Smckusick case TIOCCDTR: 43641480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 43741480Smckusick break; 43841480Smckusick 43941480Smckusick case TIOCMSET: 44041480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 44141480Smckusick break; 44241480Smckusick 44341480Smckusick case TIOCMBIS: 44441480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 44541480Smckusick break; 44641480Smckusick 44741480Smckusick case TIOCMBIC: 44841480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 44941480Smckusick break; 45041480Smckusick 45141480Smckusick case TIOCMGET: 45241480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 45341480Smckusick break; 45441480Smckusick 45541480Smckusick default: 45641480Smckusick return (ENOTTY); 45741480Smckusick } 45841480Smckusick return (0); 45941480Smckusick } 46041480Smckusick 46141480Smckusick dcaparam(tp, t) 46241480Smckusick register struct tty *tp; 46341480Smckusick register struct termios *t; 46441480Smckusick { 46541480Smckusick register struct dcadevice *dca; 46641480Smckusick register int cfcr, cflag = t->c_cflag; 46741480Smckusick int unit = UNIT(tp->t_dev); 46841480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 46941480Smckusick 47041480Smckusick /* check requested parameters */ 47141480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 47250219Skarels return (EINVAL); 47341480Smckusick /* and copy to tty */ 47441480Smckusick tp->t_ispeed = t->c_ispeed; 47541480Smckusick tp->t_ospeed = t->c_ospeed; 47641480Smckusick tp->t_cflag = cflag; 47741480Smckusick 47841480Smckusick dca = dca_addr[unit]; 47941480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 48041480Smckusick if (ospeed == 0) { 48141480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 48250219Skarels return (0); 48341480Smckusick } 48441480Smckusick dca->dca_cfcr |= CFCR_DLAB; 48541480Smckusick dca->dca_data = ospeed & 0xFF; 48641480Smckusick dca->dca_ier = ospeed >> 8; 48741480Smckusick switch (cflag&CSIZE) { 48841480Smckusick case CS5: 48941480Smckusick cfcr = CFCR_5BITS; break; 49041480Smckusick case CS6: 49141480Smckusick cfcr = CFCR_6BITS; break; 49241480Smckusick case CS7: 49341480Smckusick cfcr = CFCR_7BITS; break; 49441480Smckusick case CS8: 49541480Smckusick cfcr = CFCR_8BITS; break; 49641480Smckusick } 49741480Smckusick if (cflag&PARENB) { 49841480Smckusick cfcr |= CFCR_PENAB; 49941480Smckusick if ((cflag&PARODD) == 0) 50041480Smckusick cfcr |= CFCR_PEVEN; 50141480Smckusick } 50241480Smckusick if (cflag&CSTOPB) 50341480Smckusick cfcr |= CFCR_STOPB; 50441480Smckusick dca->dca_cfcr = cfcr; 50549300Shibler if (dca_hasfifo & (1 << unit)) 50649300Shibler dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 50750219Skarels return (0); 50841480Smckusick } 50941480Smckusick 510*52389Smckusick void 51141480Smckusick dcastart(tp) 51241480Smckusick register struct tty *tp; 51341480Smckusick { 51441480Smckusick register struct dcadevice *dca; 51541480Smckusick int s, unit, c; 51641480Smckusick 51741480Smckusick unit = UNIT(tp->t_dev); 51841480Smckusick dca = dca_addr[unit]; 51941480Smckusick s = spltty(); 52044318Shibler if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 52141480Smckusick goto out; 52241480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 52341480Smckusick if (tp->t_state&TS_ASLEEP) { 52441480Smckusick tp->t_state &= ~TS_ASLEEP; 52541480Smckusick wakeup((caddr_t)&tp->t_outq); 52641480Smckusick } 52741480Smckusick if (tp->t_wsel) { 52841480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 52941480Smckusick tp->t_wsel = 0; 53041480Smckusick tp->t_state &= ~TS_WCOLL; 53141480Smckusick } 53241480Smckusick } 53341480Smckusick if (tp->t_outq.c_cc == 0) 53441480Smckusick goto out; 53544318Shibler if (dca->dca_lsr & LSR_TXRDY) { 53644318Shibler c = getc(&tp->t_outq); 53744318Shibler tp->t_state |= TS_BUSY; 53844318Shibler dca->dca_data = c; 53949300Shibler if (dca_hasfifo & (1 << unit)) { 54049300Shibler for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 54149300Shibler dca->dca_data = getc(&tp->t_outq); 54249300Shibler #ifdef DEBUG 54349300Shibler if (c > 16) 54449300Shibler fifoout[0]++; 54549300Shibler else 54649300Shibler fifoout[c]++; 54749300Shibler #endif 54849300Shibler } 54944318Shibler } 55041480Smckusick out: 55141480Smckusick splx(s); 55241480Smckusick } 55341480Smckusick 55441480Smckusick /* 55541480Smckusick * Stop output on a line. 55641480Smckusick */ 55741480Smckusick /*ARGSUSED*/ 55841480Smckusick dcastop(tp, flag) 55941480Smckusick register struct tty *tp; 56041480Smckusick { 56141480Smckusick register int s; 56241480Smckusick 56341480Smckusick s = spltty(); 56441480Smckusick if (tp->t_state & TS_BUSY) { 56541480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 56641480Smckusick tp->t_state |= TS_FLUSH; 56741480Smckusick } 56841480Smckusick splx(s); 56941480Smckusick } 57041480Smckusick 57141480Smckusick dcamctl(dev, bits, how) 57241480Smckusick dev_t dev; 57341480Smckusick int bits, how; 57441480Smckusick { 57541480Smckusick register struct dcadevice *dca; 57641480Smckusick register int unit; 57741480Smckusick int s; 57841480Smckusick 57941480Smckusick unit = UNIT(dev); 58041480Smckusick dca = dca_addr[unit]; 58141480Smckusick s = spltty(); 58241480Smckusick switch (how) { 58341480Smckusick 58441480Smckusick case DMSET: 58541480Smckusick dca->dca_mcr = bits; 58641480Smckusick break; 58741480Smckusick 58841480Smckusick case DMBIS: 58941480Smckusick dca->dca_mcr |= bits; 59041480Smckusick break; 59141480Smckusick 59241480Smckusick case DMBIC: 59341480Smckusick dca->dca_mcr &= ~bits; 59441480Smckusick break; 59541480Smckusick 59641480Smckusick case DMGET: 59741480Smckusick bits = dca->dca_msr; 59841480Smckusick break; 59941480Smckusick } 60041480Smckusick (void) splx(s); 60150219Skarels return (bits); 60241480Smckusick } 60341480Smckusick 60441480Smckusick /* 60541480Smckusick * Following are all routines needed for DCA to act as console 60641480Smckusick */ 60745788Sbostic #include "../hp300/cons.h" 60841480Smckusick 60941480Smckusick dcacnprobe(cp) 61041480Smckusick struct consdev *cp; 61141480Smckusick { 61249300Shibler int unit; 61341480Smckusick 61449130Skarels /* locate the major number */ 61549130Skarels for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 61649130Skarels if (cdevsw[dcamajor].d_open == dcaopen) 61749130Skarels break; 61849130Skarels 61941480Smckusick /* XXX: ick */ 62041480Smckusick unit = CONUNIT; 62149300Shibler dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 62241480Smckusick 62341480Smckusick /* make sure hardware exists */ 62441480Smckusick if (badaddr((short *)dca_addr[unit])) { 62541480Smckusick cp->cn_pri = CN_DEAD; 62641480Smckusick return; 62741480Smckusick } 62841480Smckusick 62941480Smckusick /* initialize required fields */ 63049130Skarels cp->cn_dev = makedev(dcamajor, unit); 63141480Smckusick cp->cn_tp = &dca_tty[unit]; 63241480Smckusick switch (dca_addr[unit]->dca_irid) { 63341480Smckusick case DCAID0: 63441480Smckusick case DCAID1: 63541480Smckusick cp->cn_pri = CN_NORMAL; 63641480Smckusick break; 63741480Smckusick case DCAREMID0: 63841480Smckusick case DCAREMID1: 63941480Smckusick cp->cn_pri = CN_REMOTE; 64041480Smckusick break; 64141480Smckusick default: 64241480Smckusick cp->cn_pri = CN_DEAD; 64341480Smckusick break; 64441480Smckusick } 64549130Skarels /* 64649300Shibler * If dcaconsole is initialized, raise our priority. 64749130Skarels */ 64849130Skarels if (dcaconsole == unit) 64949130Skarels cp->cn_pri = CN_REMOTE; 65049300Shibler #ifdef KGDB 65149130Skarels if (major(kgdb_dev) == 1) /* XXX */ 65249130Skarels kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 65349300Shibler #endif 65441480Smckusick } 65541480Smckusick 65641480Smckusick dcacninit(cp) 65741480Smckusick struct consdev *cp; 65841480Smckusick { 65941480Smckusick int unit = UNIT(cp->cn_dev); 66041480Smckusick 66149130Skarels dcainit(unit, dcadefaultrate); 66241480Smckusick dcaconsole = unit; 66349130Skarels dcaconsinit = 1; 66441480Smckusick } 66541480Smckusick 66649130Skarels dcainit(unit, rate) 66749130Skarels int unit, rate; 66841480Smckusick { 66941480Smckusick register struct dcadevice *dca; 67049130Skarels int s; 67141480Smckusick short stat; 67241480Smckusick 67341480Smckusick #ifdef lint 67441480Smckusick stat = unit; if (stat) return; 67541480Smckusick #endif 67641480Smckusick dca = dca_addr[unit]; 67741480Smckusick s = splhigh(); 67841480Smckusick dca->dca_irid = 0xFF; 67941480Smckusick DELAY(100); 68041480Smckusick dca->dca_ic = IC_IE; 68141480Smckusick dca->dca_cfcr = CFCR_DLAB; 68249130Skarels rate = ttspeedtab(rate, dcaspeedtab); 68341480Smckusick dca->dca_data = rate & 0xFF; 68441480Smckusick dca->dca_ier = rate >> 8; 68541480Smckusick dca->dca_cfcr = CFCR_8BITS; 68641480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 68749300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 68841480Smckusick stat = dca->dca_iir; 68941480Smckusick splx(s); 69041480Smckusick } 69141480Smckusick 69241480Smckusick dcacngetc(dev) 69341480Smckusick { 69441480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 69541480Smckusick short stat; 69641480Smckusick int c, s; 69741480Smckusick 69841480Smckusick #ifdef lint 69950219Skarels stat = dev; if (stat) return (0); 70041480Smckusick #endif 70141480Smckusick s = splhigh(); 70241480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 70341480Smckusick ; 70441480Smckusick c = dca->dca_data; 70541480Smckusick stat = dca->dca_iir; 70641480Smckusick splx(s); 70750219Skarels return (c); 70841480Smckusick } 70941480Smckusick 71041480Smckusick /* 71141480Smckusick * Console kernel output character routine. 71241480Smckusick */ 71341480Smckusick dcacnputc(dev, c) 71441480Smckusick dev_t dev; 71541480Smckusick register int c; 71641480Smckusick { 71741480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 71841480Smckusick register int timo; 71941480Smckusick short stat; 72041480Smckusick int s = splhigh(); 72141480Smckusick 72241480Smckusick #ifdef lint 72341480Smckusick stat = dev; if (stat) return; 72441480Smckusick #endif 72549130Skarels if (dcaconsinit == 0) { 72649130Skarels (void) dcainit(UNIT(dev), dcadefaultrate); 72749130Skarels dcaconsinit = 1; 72841480Smckusick } 72941480Smckusick /* wait for any pending transmission to finish */ 73041480Smckusick timo = 50000; 73141480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 73241480Smckusick ; 73341480Smckusick dca->dca_data = c; 73441480Smckusick /* wait for this transmission to complete */ 73541480Smckusick timo = 1500000; 73641480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 73741480Smckusick ; 73841480Smckusick /* clear any interrupts generated by this transmission */ 73941480Smckusick stat = dca->dca_iir; 74041480Smckusick splx(s); 74141480Smckusick } 74241480Smckusick #endif 743