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*50219Skarels * @(#)dca.c 7.12 (Berkeley) 06/27/91 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 3741480Smckusick int dcastart(), dcaparam(), dcaintr(); 3841480Smckusick int dcasoftCAR; 3941480Smckusick int dca_active; 4049300Shibler int dca_hasfifo; 4141480Smckusick int ndca = NDCA; 4249130Skarels #ifdef DCACONSOLE 4349130Skarels int dcaconsole = DCACONSOLE; 4449130Skarels #else 4541480Smckusick int dcaconsole = -1; 4649130Skarels #endif 4749130Skarels int dcaconsinit; 4841480Smckusick int dcadefaultrate = TTYDEF_SPEED; 4949130Skarels int dcamajor; 5041480Smckusick struct dcadevice *dca_addr[NDCA]; 5141480Smckusick struct tty dca_tty[NDCA]; 5241480Smckusick struct isr dcaisr[NDCA]; 5341480Smckusick 5441480Smckusick struct speedtab dcaspeedtab[] = { 5541480Smckusick 0, 0, 5641480Smckusick 50, DCABRD(50), 5741480Smckusick 75, DCABRD(75), 5841480Smckusick 110, DCABRD(110), 5941480Smckusick 134, DCABRD(134), 6041480Smckusick 150, DCABRD(150), 6141480Smckusick 200, DCABRD(200), 6241480Smckusick 300, DCABRD(300), 6341480Smckusick 600, DCABRD(600), 6441480Smckusick 1200, DCABRD(1200), 6541480Smckusick 1800, DCABRD(1800), 6641480Smckusick 2400, DCABRD(2400), 6741480Smckusick 4800, DCABRD(4800), 6841480Smckusick 9600, DCABRD(9600), 6941480Smckusick 19200, DCABRD(19200), 7041480Smckusick 38400, DCABRD(38400), 7141480Smckusick -1, -1 7241480Smckusick }; 7341480Smckusick 7441480Smckusick extern struct tty *constty; 7541480Smckusick #ifdef KGDB 7649130Skarels #include "machine/remote-sl.h" 7749130Skarels 78*50219Skarels extern dev_t kgdb_dev; 7941480Smckusick extern int kgdb_rate; 8041480Smckusick extern int kgdb_debug_init; 8141480Smckusick #endif 8241480Smckusick 8341480Smckusick #define UNIT(x) minor(x) 8441480Smckusick 8549300Shibler #ifdef DEBUG 8649300Shibler long fifoin[17]; 8749300Shibler long fifoout[17]; 8849300Shibler long dcaintrcount[16]; 8949300Shibler long dcamintcount[16]; 9049300Shibler #endif 9149300Shibler 9241480Smckusick dcaprobe(hd) 9341480Smckusick register struct hp_device *hd; 9441480Smckusick { 9541480Smckusick register struct dcadevice *dca; 9641480Smckusick register int unit; 9741480Smckusick 9841480Smckusick dca = (struct dcadevice *)hd->hp_addr; 9941480Smckusick if (dca->dca_irid != DCAID0 && 10041480Smckusick dca->dca_irid != DCAREMID0 && 10141480Smckusick dca->dca_irid != DCAID1 && 10241480Smckusick dca->dca_irid != DCAREMID1) 10341480Smckusick return (0); 10441480Smckusick unit = hd->hp_unit; 10541480Smckusick if (unit == dcaconsole) 10641480Smckusick DELAY(100000); 10741480Smckusick dca->dca_irid = 0xFF; 10841480Smckusick DELAY(100); 10941480Smckusick 11049300Shibler /* look for a NS 16550AF UART with FIFOs */ 11149300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 11249300Shibler DELAY(100); 11349300Shibler if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) 11449300Shibler dca_hasfifo |= 1 << unit; 11549300Shibler 11641480Smckusick hd->hp_ipl = DCAIPL(dca->dca_ic); 11741480Smckusick dcaisr[unit].isr_ipl = hd->hp_ipl; 11841480Smckusick dcaisr[unit].isr_arg = unit; 11941480Smckusick dcaisr[unit].isr_intr = dcaintr; 12041480Smckusick dca_addr[unit] = dca; 12141480Smckusick dca_active |= 1 << unit; 12241480Smckusick dcasoftCAR = hd->hp_flags; 12341480Smckusick isrlink(&dcaisr[unit]); 12441480Smckusick #ifdef KGDB 12549130Skarels if (kgdb_dev == makedev(dcamajor, unit)) { 12641480Smckusick if (dcaconsole == unit) 127*50219Skarels kgdb_dev = NODEV; /* can't debug over console port */ 12841480Smckusick else { 12949130Skarels (void) dcainit(unit, kgdb_rate); 130*50219Skarels dcaconsinit = 1; /* don't re-init in dcaputc */ 13141480Smckusick if (kgdb_debug_init) { 13249130Skarels /* 13349130Skarels * Print prefix of device name, 13449130Skarels * let kgdb_connect print the rest. 13549130Skarels */ 13649130Skarels printf("dca%d: ", unit); 13749130Skarels kgdb_connect(1); 13841480Smckusick } else 13941480Smckusick printf("dca%d: kgdb enabled\n", unit); 14041480Smckusick } 14141480Smckusick } 14241480Smckusick #endif 14341480Smckusick dca->dca_ic = IC_IE; 14441480Smckusick /* 14549130Skarels * Need to reset baud rate, etc. of next print so reset dcaconsinit. 14649130Skarels * Also make sure console is always "hardwired." 14741480Smckusick */ 14841480Smckusick if (unit == dcaconsole) { 14949130Skarels dcaconsinit = 0; 15041480Smckusick dcasoftCAR |= (1 << unit); 15141480Smckusick } 15241480Smckusick return (1); 15341480Smckusick } 15441480Smckusick 15549130Skarels /* ARGSUSED */ 15649130Skarels #ifdef __STDC__ 15749130Skarels dcaopen(dev_t dev, int flag, int mode, struct proc *p) 15849130Skarels #else 15949130Skarels dcaopen(dev, flag, mode, p) 16041480Smckusick dev_t dev; 16149130Skarels int flag, mode; 16249130Skarels struct proc *p; 16349130Skarels #endif 16441480Smckusick { 16541480Smckusick register struct tty *tp; 16641480Smckusick register int unit; 16744762Skarels int error = 0; 16841480Smckusick 16941480Smckusick unit = UNIT(dev); 17041480Smckusick if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 17141480Smckusick return (ENXIO); 17241480Smckusick tp = &dca_tty[unit]; 17341480Smckusick tp->t_oproc = dcastart; 17441480Smckusick tp->t_param = dcaparam; 17541480Smckusick tp->t_dev = dev; 17641480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 17742950Smarc tp->t_state |= TS_WOPEN; 17841480Smckusick ttychars(tp); 17949130Skarels if (tp->t_ispeed == 0) { 18049130Skarels tp->t_iflag = TTYDEF_IFLAG; 18149130Skarels tp->t_oflag = TTYDEF_OFLAG; 18249130Skarels tp->t_cflag = TTYDEF_CFLAG; 18349130Skarels tp->t_lflag = TTYDEF_LFLAG; 18449130Skarels tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 18549130Skarels } 18641480Smckusick dcaparam(tp, &tp->t_termios); 18741480Smckusick ttsetwater(tp); 18849130Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 18941480Smckusick return (EBUSY); 19041480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 19141480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 19241480Smckusick tp->t_state |= TS_CARR_ON; 19341480Smckusick (void) spltty(); 19444295Shibler while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 19541480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 19641480Smckusick tp->t_state |= TS_WOPEN; 19744295Shibler if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 19844295Shibler ttopen, 0)) 19944295Shibler break; 20041480Smckusick } 20141480Smckusick (void) spl0(); 20244295Shibler if (error == 0) 20344295Shibler error = (*linesw[tp->t_line].l_open)(dev, tp); 20444295Shibler return (error); 20541480Smckusick } 20641480Smckusick 20741480Smckusick /*ARGSUSED*/ 20849750Smarc dcaclose(dev, flag, mode, p) 20941480Smckusick dev_t dev; 21049750Smarc int flag, mode; 21149750Smarc struct proc *p; 21241480Smckusick { 21341480Smckusick register struct tty *tp; 21441480Smckusick register struct dcadevice *dca; 21541480Smckusick register int unit; 21641480Smckusick 21741480Smckusick unit = UNIT(dev); 21841480Smckusick dca = dca_addr[unit]; 21941480Smckusick tp = &dca_tty[unit]; 22049750Smarc (*linesw[tp->t_line].l_close)(tp, flag); 22141480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 22241480Smckusick #ifdef KGDB 22341480Smckusick /* do not disable interrupts if debugging */ 22449130Skarels if (dev != kgdb_dev) 22541480Smckusick #endif 22641480Smckusick dca->dca_ier = 0; 227*50219Skarels if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 228*50219Skarels (tp->t_state&TS_ISOPEN) == 0) 229*50219Skarels (void) dcamctl(dev, 0, DMSET); 23041480Smckusick ttyclose(tp); 231*50219Skarels return (0); 23241480Smckusick } 23341480Smckusick 23441480Smckusick dcaread(dev, uio, flag) 23541480Smckusick dev_t dev; 23641480Smckusick struct uio *uio; 23741480Smckusick { 23841480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 23941480Smckusick 24041480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 24141480Smckusick } 24241480Smckusick 24341480Smckusick dcawrite(dev, uio, flag) 24441480Smckusick dev_t dev; 24541480Smckusick struct uio *uio; 24641480Smckusick { 24741480Smckusick int unit = UNIT(dev); 24841480Smckusick register struct tty *tp = &dca_tty[unit]; 24941480Smckusick 25042353Smckusick /* 25142353Smckusick * (XXX) We disallow virtual consoles if the physical console is 25242353Smckusick * a serial port. This is in case there is a display attached that 25342353Smckusick * is not the console. In that situation we don't need/want the X 25442353Smckusick * server taking over the console. 25542353Smckusick */ 25642353Smckusick if (constty && unit == dcaconsole) 25742353Smckusick constty = NULL; 25841480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 25941480Smckusick } 26041480Smckusick 26141480Smckusick dcaintr(unit) 26241480Smckusick register int unit; 26341480Smckusick { 26441480Smckusick register struct dcadevice *dca; 26544318Shibler register u_char code; 26644318Shibler register struct tty *tp; 26741480Smckusick 26841480Smckusick dca = dca_addr[unit]; 26941480Smckusick if ((dca->dca_ic & IC_IR) == 0) 270*50219Skarels return (0); 27144318Shibler while (1) { 27244318Shibler code = dca->dca_iir; 27349300Shibler #ifdef DEBUG 27449300Shibler dcaintrcount[code & IIR_IMASK]++; 27549300Shibler #endif 27649300Shibler switch (code & IIR_IMASK) { 27744318Shibler case IIR_NOPEND: 27844318Shibler return (1); 27949300Shibler case IIR_RXTOUT: 28044318Shibler case IIR_RXRDY: 28144318Shibler /* do time-critical read in-line */ 28244318Shibler tp = &dca_tty[unit]; 28349300Shibler /* 28449300Shibler * Process a received byte. Inline for speed... 28549300Shibler */ 28644318Shibler #ifdef KGDB 28749300Shibler #define RCVBYTE() \ 28849300Shibler code = dca->dca_data; \ 28949300Shibler if ((tp->t_state & TS_ISOPEN) == 0) { \ 290*50219Skarels if (code == FRAME_END && \ 291*50219Skarels kgdb_dev == makedev(dcamajor, unit)) \ 29249300Shibler kgdb_connect(0); /* trap into kgdb */ \ 29349300Shibler } else \ 29449300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 29549300Shibler #else 29649300Shibler #define RCVBYTE() \ 29749300Shibler code = dca->dca_data; \ 29849300Shibler if ((tp->t_state & TS_ISOPEN) != 0) \ 29949300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 30044318Shibler #endif 30149300Shibler RCVBYTE(); 30249300Shibler if (dca_hasfifo & (1 << unit)) { 30349300Shibler #ifdef DEBUG 30449300Shibler register int fifocnt = 1; 30549300Shibler #endif 30649300Shibler while ((code = dca->dca_lsr) & LSR_RCV_MASK) { 30749300Shibler if (code == LSR_RXRDY) { 30849300Shibler RCVBYTE(); 30949300Shibler } else 31049300Shibler dcaeint(unit, code, dca); 31149300Shibler #ifdef DEBUG 31249300Shibler fifocnt++; 31349300Shibler #endif 31449300Shibler } 31549300Shibler #ifdef DEBUG 31649300Shibler if (fifocnt > 16) 31749300Shibler fifoin[0]++; 31849300Shibler else 31949300Shibler fifoin[fifocnt]++; 32049300Shibler #endif 32149300Shibler } 32244318Shibler break; 32344318Shibler case IIR_TXRDY: 32444318Shibler tp = &dca_tty[unit]; 32544318Shibler tp->t_state &=~ (TS_BUSY|TS_FLUSH); 32644318Shibler if (tp->t_line) 32744318Shibler (*linesw[tp->t_line].l_start)(tp); 32844318Shibler else 32944318Shibler dcastart(tp); 33044318Shibler break; 33144318Shibler case IIR_RLS: 33249300Shibler dcaeint(unit, dca->dca_lsr, dca); 33344318Shibler break; 33444318Shibler default: 33544318Shibler if (code & IIR_NOPEND) 33644318Shibler return (1); 33744318Shibler log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 33844318Shibler unit, code); 33944318Shibler /* fall through */ 34044318Shibler case IIR_MLSC: 34141480Smckusick dcamint(unit, dca); 34244318Shibler break; 34344318Shibler } 34441480Smckusick } 34541480Smckusick } 34641480Smckusick 34749300Shibler dcaeint(unit, stat, dca) 34849300Shibler register int unit, stat; 34941480Smckusick register struct dcadevice *dca; 35041480Smckusick { 35141480Smckusick register struct tty *tp; 35249300Shibler register int c; 35341480Smckusick 35441480Smckusick tp = &dca_tty[unit]; 35544318Shibler c = dca->dca_data; 35641480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 35741480Smckusick #ifdef KGDB 35841480Smckusick /* we don't care about parity errors */ 35941480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 36049130Skarels kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 36149130Skarels kgdb_connect(0); /* trap into kgdb */ 36241480Smckusick #endif 36341480Smckusick return; 36441480Smckusick } 36541480Smckusick if (stat & (LSR_BI | LSR_FE)) 36641480Smckusick c |= TTY_FE; 36741480Smckusick else if (stat & LSR_PE) 36841480Smckusick c |= TTY_PE; 36941480Smckusick else if (stat & LSR_OE) 37041480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 37141480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 37241480Smckusick } 37341480Smckusick 37441480Smckusick dcamint(unit, dca) 37541480Smckusick register int unit; 37641480Smckusick register struct dcadevice *dca; 37741480Smckusick { 37841480Smckusick register struct tty *tp; 37941480Smckusick register int stat; 38041480Smckusick 38141480Smckusick tp = &dca_tty[unit]; 38241480Smckusick stat = dca->dca_msr; 38349300Shibler #ifdef DEBUG 38449300Shibler dcamintcount[stat & 0xf]++; 38549300Shibler #endif 38644318Shibler if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 38741480Smckusick if (stat & MSR_DCD) 38844318Shibler (void)(*linesw[tp->t_line].l_modem)(tp, 1); 38941480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 39041480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 39144318Shibler } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 39244318Shibler (tp->t_flags & CRTSCTS)) { 39344318Shibler /* the line is up and we want to do rts/cts flow control */ 39444318Shibler if (stat & MSR_CTS) { 39544318Shibler tp->t_state &=~ TS_TTSTOP; 39644318Shibler ttstart(tp); 39744318Shibler } else 39844318Shibler tp->t_state |= TS_TTSTOP; 39941480Smckusick } 40041480Smckusick } 40141480Smckusick 40241480Smckusick dcaioctl(dev, cmd, data, flag) 40341480Smckusick dev_t dev; 40441480Smckusick caddr_t data; 40541480Smckusick { 40641480Smckusick register struct tty *tp; 40741480Smckusick register int unit = UNIT(dev); 40841480Smckusick register struct dcadevice *dca; 40941480Smckusick register int error; 41041480Smckusick 41141480Smckusick tp = &dca_tty[unit]; 41241480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 41341480Smckusick if (error >= 0) 41441480Smckusick return (error); 41541480Smckusick error = ttioctl(tp, cmd, data, flag); 41641480Smckusick if (error >= 0) 41741480Smckusick return (error); 41841480Smckusick 41941480Smckusick dca = dca_addr[unit]; 42041480Smckusick switch (cmd) { 42141480Smckusick 42241480Smckusick case TIOCSBRK: 42341480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 42441480Smckusick break; 42541480Smckusick 42641480Smckusick case TIOCCBRK: 42741480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 42841480Smckusick break; 42941480Smckusick 43041480Smckusick case TIOCSDTR: 43141480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 43241480Smckusick break; 43341480Smckusick 43441480Smckusick case TIOCCDTR: 43541480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 43641480Smckusick break; 43741480Smckusick 43841480Smckusick case TIOCMSET: 43941480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 44041480Smckusick break; 44141480Smckusick 44241480Smckusick case TIOCMBIS: 44341480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 44441480Smckusick break; 44541480Smckusick 44641480Smckusick case TIOCMBIC: 44741480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 44841480Smckusick break; 44941480Smckusick 45041480Smckusick case TIOCMGET: 45141480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 45241480Smckusick break; 45341480Smckusick 45441480Smckusick default: 45541480Smckusick return (ENOTTY); 45641480Smckusick } 45741480Smckusick return (0); 45841480Smckusick } 45941480Smckusick 46041480Smckusick dcaparam(tp, t) 46141480Smckusick register struct tty *tp; 46241480Smckusick register struct termios *t; 46341480Smckusick { 46441480Smckusick register struct dcadevice *dca; 46541480Smckusick register int cfcr, cflag = t->c_cflag; 46641480Smckusick int unit = UNIT(tp->t_dev); 46741480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 46841480Smckusick 46941480Smckusick /* check requested parameters */ 47041480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 471*50219Skarels return (EINVAL); 47241480Smckusick /* and copy to tty */ 47341480Smckusick tp->t_ispeed = t->c_ispeed; 47441480Smckusick tp->t_ospeed = t->c_ospeed; 47541480Smckusick tp->t_cflag = cflag; 47641480Smckusick 47741480Smckusick dca = dca_addr[unit]; 47841480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 47941480Smckusick if (ospeed == 0) { 48041480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 481*50219Skarels return (0); 48241480Smckusick } 48341480Smckusick dca->dca_cfcr |= CFCR_DLAB; 48441480Smckusick dca->dca_data = ospeed & 0xFF; 48541480Smckusick dca->dca_ier = ospeed >> 8; 48641480Smckusick switch (cflag&CSIZE) { 48741480Smckusick case CS5: 48841480Smckusick cfcr = CFCR_5BITS; break; 48941480Smckusick case CS6: 49041480Smckusick cfcr = CFCR_6BITS; break; 49141480Smckusick case CS7: 49241480Smckusick cfcr = CFCR_7BITS; break; 49341480Smckusick case CS8: 49441480Smckusick cfcr = CFCR_8BITS; break; 49541480Smckusick } 49641480Smckusick if (cflag&PARENB) { 49741480Smckusick cfcr |= CFCR_PENAB; 49841480Smckusick if ((cflag&PARODD) == 0) 49941480Smckusick cfcr |= CFCR_PEVEN; 50041480Smckusick } 50141480Smckusick if (cflag&CSTOPB) 50241480Smckusick cfcr |= CFCR_STOPB; 50341480Smckusick dca->dca_cfcr = cfcr; 50449300Shibler if (dca_hasfifo & (1 << unit)) 50549300Shibler dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 506*50219Skarels return (0); 50741480Smckusick } 50841480Smckusick 50941480Smckusick dcastart(tp) 51041480Smckusick register struct tty *tp; 51141480Smckusick { 51241480Smckusick register struct dcadevice *dca; 51341480Smckusick int s, unit, c; 51441480Smckusick 51541480Smckusick unit = UNIT(tp->t_dev); 51641480Smckusick dca = dca_addr[unit]; 51741480Smckusick s = spltty(); 51844318Shibler if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 51941480Smckusick goto out; 52041480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 52141480Smckusick if (tp->t_state&TS_ASLEEP) { 52241480Smckusick tp->t_state &= ~TS_ASLEEP; 52341480Smckusick wakeup((caddr_t)&tp->t_outq); 52441480Smckusick } 52541480Smckusick if (tp->t_wsel) { 52641480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 52741480Smckusick tp->t_wsel = 0; 52841480Smckusick tp->t_state &= ~TS_WCOLL; 52941480Smckusick } 53041480Smckusick } 53141480Smckusick if (tp->t_outq.c_cc == 0) 53241480Smckusick goto out; 53344318Shibler if (dca->dca_lsr & LSR_TXRDY) { 53444318Shibler c = getc(&tp->t_outq); 53544318Shibler tp->t_state |= TS_BUSY; 53644318Shibler dca->dca_data = c; 53749300Shibler if (dca_hasfifo & (1 << unit)) { 53849300Shibler for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 53949300Shibler dca->dca_data = getc(&tp->t_outq); 54049300Shibler #ifdef DEBUG 54149300Shibler if (c > 16) 54249300Shibler fifoout[0]++; 54349300Shibler else 54449300Shibler fifoout[c]++; 54549300Shibler #endif 54649300Shibler } 54744318Shibler } 54841480Smckusick out: 54941480Smckusick splx(s); 55041480Smckusick } 55141480Smckusick 55241480Smckusick /* 55341480Smckusick * Stop output on a line. 55441480Smckusick */ 55541480Smckusick /*ARGSUSED*/ 55641480Smckusick dcastop(tp, flag) 55741480Smckusick register struct tty *tp; 55841480Smckusick { 55941480Smckusick register int s; 56041480Smckusick 56141480Smckusick s = spltty(); 56241480Smckusick if (tp->t_state & TS_BUSY) { 56341480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 56441480Smckusick tp->t_state |= TS_FLUSH; 56541480Smckusick } 56641480Smckusick splx(s); 56741480Smckusick } 56841480Smckusick 56941480Smckusick dcamctl(dev, bits, how) 57041480Smckusick dev_t dev; 57141480Smckusick int bits, how; 57241480Smckusick { 57341480Smckusick register struct dcadevice *dca; 57441480Smckusick register int unit; 57541480Smckusick int s; 57641480Smckusick 57741480Smckusick unit = UNIT(dev); 57841480Smckusick dca = dca_addr[unit]; 57941480Smckusick s = spltty(); 58041480Smckusick switch (how) { 58141480Smckusick 58241480Smckusick case DMSET: 58341480Smckusick dca->dca_mcr = bits; 58441480Smckusick break; 58541480Smckusick 58641480Smckusick case DMBIS: 58741480Smckusick dca->dca_mcr |= bits; 58841480Smckusick break; 58941480Smckusick 59041480Smckusick case DMBIC: 59141480Smckusick dca->dca_mcr &= ~bits; 59241480Smckusick break; 59341480Smckusick 59441480Smckusick case DMGET: 59541480Smckusick bits = dca->dca_msr; 59641480Smckusick break; 59741480Smckusick } 59841480Smckusick (void) splx(s); 599*50219Skarels return (bits); 60041480Smckusick } 60141480Smckusick 60241480Smckusick /* 60341480Smckusick * Following are all routines needed for DCA to act as console 60441480Smckusick */ 60545788Sbostic #include "../hp300/cons.h" 60641480Smckusick 60741480Smckusick dcacnprobe(cp) 60841480Smckusick struct consdev *cp; 60941480Smckusick { 61049300Shibler int unit; 61141480Smckusick 61249130Skarels /* locate the major number */ 61349130Skarels for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 61449130Skarels if (cdevsw[dcamajor].d_open == dcaopen) 61549130Skarels break; 61649130Skarels 61741480Smckusick /* XXX: ick */ 61841480Smckusick unit = CONUNIT; 61949300Shibler dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 62041480Smckusick 62141480Smckusick /* make sure hardware exists */ 62241480Smckusick if (badaddr((short *)dca_addr[unit])) { 62341480Smckusick cp->cn_pri = CN_DEAD; 62441480Smckusick return; 62541480Smckusick } 62641480Smckusick 62741480Smckusick /* initialize required fields */ 62849130Skarels cp->cn_dev = makedev(dcamajor, unit); 62941480Smckusick cp->cn_tp = &dca_tty[unit]; 63041480Smckusick switch (dca_addr[unit]->dca_irid) { 63141480Smckusick case DCAID0: 63241480Smckusick case DCAID1: 63341480Smckusick cp->cn_pri = CN_NORMAL; 63441480Smckusick break; 63541480Smckusick case DCAREMID0: 63641480Smckusick case DCAREMID1: 63741480Smckusick cp->cn_pri = CN_REMOTE; 63841480Smckusick break; 63941480Smckusick default: 64041480Smckusick cp->cn_pri = CN_DEAD; 64141480Smckusick break; 64241480Smckusick } 64349130Skarels /* 64449300Shibler * If dcaconsole is initialized, raise our priority. 64549130Skarels */ 64649130Skarels if (dcaconsole == unit) 64749130Skarels cp->cn_pri = CN_REMOTE; 64849300Shibler #ifdef KGDB 64949130Skarels if (major(kgdb_dev) == 1) /* XXX */ 65049130Skarels kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 65149300Shibler #endif 65241480Smckusick } 65341480Smckusick 65441480Smckusick dcacninit(cp) 65541480Smckusick struct consdev *cp; 65641480Smckusick { 65741480Smckusick int unit = UNIT(cp->cn_dev); 65841480Smckusick 65949130Skarels dcainit(unit, dcadefaultrate); 66041480Smckusick dcaconsole = unit; 66149130Skarels dcaconsinit = 1; 66241480Smckusick } 66341480Smckusick 66449130Skarels dcainit(unit, rate) 66549130Skarels int unit, rate; 66641480Smckusick { 66741480Smckusick register struct dcadevice *dca; 66849130Skarels int s; 66941480Smckusick short stat; 67041480Smckusick 67141480Smckusick #ifdef lint 67241480Smckusick stat = unit; if (stat) return; 67341480Smckusick #endif 67441480Smckusick dca = dca_addr[unit]; 67541480Smckusick s = splhigh(); 67641480Smckusick dca->dca_irid = 0xFF; 67741480Smckusick DELAY(100); 67841480Smckusick dca->dca_ic = IC_IE; 67941480Smckusick dca->dca_cfcr = CFCR_DLAB; 68049130Skarels rate = ttspeedtab(rate, dcaspeedtab); 68141480Smckusick dca->dca_data = rate & 0xFF; 68241480Smckusick dca->dca_ier = rate >> 8; 68341480Smckusick dca->dca_cfcr = CFCR_8BITS; 68441480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 68549300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 68641480Smckusick stat = dca->dca_iir; 68741480Smckusick splx(s); 68841480Smckusick } 68941480Smckusick 69041480Smckusick dcacngetc(dev) 69141480Smckusick { 69241480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 69341480Smckusick short stat; 69441480Smckusick int c, s; 69541480Smckusick 69641480Smckusick #ifdef lint 697*50219Skarels stat = dev; if (stat) return (0); 69841480Smckusick #endif 69941480Smckusick s = splhigh(); 70041480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 70141480Smckusick ; 70241480Smckusick c = dca->dca_data; 70341480Smckusick stat = dca->dca_iir; 70441480Smckusick splx(s); 705*50219Skarels return (c); 70641480Smckusick } 70741480Smckusick 70841480Smckusick /* 70941480Smckusick * Console kernel output character routine. 71041480Smckusick */ 71141480Smckusick dcacnputc(dev, c) 71241480Smckusick dev_t dev; 71341480Smckusick register int c; 71441480Smckusick { 71541480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 71641480Smckusick register int timo; 71741480Smckusick short stat; 71841480Smckusick int s = splhigh(); 71941480Smckusick 72041480Smckusick #ifdef lint 72141480Smckusick stat = dev; if (stat) return; 72241480Smckusick #endif 72349130Skarels if (dcaconsinit == 0) { 72449130Skarels (void) dcainit(UNIT(dev), dcadefaultrate); 72549130Skarels dcaconsinit = 1; 72641480Smckusick } 72741480Smckusick /* wait for any pending transmission to finish */ 72841480Smckusick timo = 50000; 72941480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 73041480Smckusick ; 73141480Smckusick dca->dca_data = c; 73241480Smckusick /* wait for this transmission to complete */ 73341480Smckusick timo = 1500000; 73441480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 73541480Smckusick ; 73641480Smckusick /* clear any interrupts generated by this transmission */ 73741480Smckusick stat = dca->dca_iir; 73841480Smckusick splx(s); 73941480Smckusick } 74041480Smckusick #endif 741