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*49300Shibler * @(#)dca.c 7.10 (Berkeley) 05/07/91 841480Smckusick */ 941480Smckusick 1041480Smckusick #include "dca.h" 1141480Smckusick #if NDCA > 0 1241480Smckusick /* 1341480Smckusick * 98626/98644/internal serial interface 14*49300Shibler * 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; 40*49300Shibler 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 7841480Smckusick extern int kgdb_dev; 7941480Smckusick extern int kgdb_rate; 8041480Smckusick extern int kgdb_debug_init; 8141480Smckusick #endif 8241480Smckusick 8341480Smckusick #define UNIT(x) minor(x) 8441480Smckusick 85*49300Shibler #ifdef DEBUG 86*49300Shibler long fifoin[17]; 87*49300Shibler long fifoout[17]; 88*49300Shibler long dcaintrcount[16]; 89*49300Shibler long dcamintcount[16]; 90*49300Shibler #endif 91*49300Shibler 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 110*49300Shibler /* look for a NS 16550AF UART with FIFOs */ 111*49300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 112*49300Shibler DELAY(100); 113*49300Shibler if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) 114*49300Shibler dca_hasfifo |= 1 << unit; 115*49300Shibler 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) 12741480Smckusick kgdb_dev = -1; /* can't debug over console port */ 12841480Smckusick else { 12949130Skarels (void) dcainit(unit, kgdb_rate); 13041480Smckusick if (kgdb_debug_init) { 13149130Skarels /* 13249130Skarels * Print prefix of device name, 13349130Skarels * let kgdb_connect print the rest. 13449130Skarels */ 13549130Skarels printf("dca%d: ", unit); 13649130Skarels kgdb_connect(1); 13741480Smckusick } else 13841480Smckusick printf("dca%d: kgdb enabled\n", unit); 13941480Smckusick } 14041480Smckusick } 14141480Smckusick #endif 14241480Smckusick dca->dca_ic = IC_IE; 14341480Smckusick /* 14449130Skarels * Need to reset baud rate, etc. of next print so reset dcaconsinit. 14549130Skarels * Also make sure console is always "hardwired." 14641480Smckusick */ 14741480Smckusick if (unit == dcaconsole) { 14849130Skarels dcaconsinit = 0; 14941480Smckusick dcasoftCAR |= (1 << unit); 15041480Smckusick } 15141480Smckusick return (1); 15241480Smckusick } 15341480Smckusick 15449130Skarels /* ARGSUSED */ 15549130Skarels #ifdef __STDC__ 15649130Skarels dcaopen(dev_t dev, int flag, int mode, struct proc *p) 15749130Skarels #else 15849130Skarels dcaopen(dev, flag, mode, p) 15941480Smckusick dev_t dev; 16049130Skarels int flag, mode; 16149130Skarels struct proc *p; 16249130Skarels #endif 16341480Smckusick { 16441480Smckusick register struct tty *tp; 16541480Smckusick register int unit; 16644762Skarels int error = 0; 16741480Smckusick 16841480Smckusick unit = UNIT(dev); 16941480Smckusick if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 17041480Smckusick return (ENXIO); 17141480Smckusick tp = &dca_tty[unit]; 17241480Smckusick tp->t_oproc = dcastart; 17341480Smckusick tp->t_param = dcaparam; 17441480Smckusick tp->t_dev = dev; 17541480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 17642950Smarc tp->t_state |= TS_WOPEN; 17741480Smckusick ttychars(tp); 17849130Skarels if (tp->t_ispeed == 0) { 17949130Skarels tp->t_iflag = TTYDEF_IFLAG; 18049130Skarels tp->t_oflag = TTYDEF_OFLAG; 18149130Skarels tp->t_cflag = TTYDEF_CFLAG; 18249130Skarels tp->t_lflag = TTYDEF_LFLAG; 18349130Skarels tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 18449130Skarels } 18541480Smckusick dcaparam(tp, &tp->t_termios); 18641480Smckusick ttsetwater(tp); 18749130Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 18841480Smckusick return (EBUSY); 18941480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 19041480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 19141480Smckusick tp->t_state |= TS_CARR_ON; 19241480Smckusick (void) spltty(); 19344295Shibler while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 19441480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 19541480Smckusick tp->t_state |= TS_WOPEN; 19644295Shibler if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 19744295Shibler ttopen, 0)) 19844295Shibler break; 19941480Smckusick } 20041480Smckusick (void) spl0(); 20144295Shibler if (error == 0) 20244295Shibler error = (*linesw[tp->t_line].l_open)(dev, tp); 20344295Shibler return (error); 20441480Smckusick } 20541480Smckusick 20641480Smckusick /*ARGSUSED*/ 20741480Smckusick dcaclose(dev, flag) 20841480Smckusick dev_t dev; 20941480Smckusick { 21041480Smckusick register struct tty *tp; 21141480Smckusick register struct dcadevice *dca; 21241480Smckusick register int unit; 21341480Smckusick 21441480Smckusick unit = UNIT(dev); 21541480Smckusick dca = dca_addr[unit]; 21641480Smckusick tp = &dca_tty[unit]; 21741480Smckusick (*linesw[tp->t_line].l_close)(tp); 21841480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 21941480Smckusick #ifdef KGDB 22041480Smckusick /* do not disable interrupts if debugging */ 22149130Skarels if (dev != kgdb_dev) 22241480Smckusick #endif 22341480Smckusick dca->dca_ier = 0; 22449130Skarels (void) dcamctl(dev, 0, DMSET); 22549130Skarels if (tp->t_state & TS_HUPCLS) 22649130Skarels (*linesw[tp->t_line].l_modem)(tp, 0); 22741480Smckusick ttyclose(tp); 22841480Smckusick return(0); 22941480Smckusick } 23041480Smckusick 23141480Smckusick dcaread(dev, uio, flag) 23241480Smckusick dev_t dev; 23341480Smckusick struct uio *uio; 23441480Smckusick { 23541480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 23641480Smckusick 23741480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 23841480Smckusick } 23941480Smckusick 24041480Smckusick dcawrite(dev, uio, flag) 24141480Smckusick dev_t dev; 24241480Smckusick struct uio *uio; 24341480Smckusick { 24441480Smckusick int unit = UNIT(dev); 24541480Smckusick register struct tty *tp = &dca_tty[unit]; 24641480Smckusick 24742353Smckusick /* 24842353Smckusick * (XXX) We disallow virtual consoles if the physical console is 24942353Smckusick * a serial port. This is in case there is a display attached that 25042353Smckusick * is not the console. In that situation we don't need/want the X 25142353Smckusick * server taking over the console. 25242353Smckusick */ 25342353Smckusick if (constty && unit == dcaconsole) 25442353Smckusick constty = NULL; 25541480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 25641480Smckusick } 25741480Smckusick 25841480Smckusick dcaintr(unit) 25941480Smckusick register int unit; 26041480Smckusick { 26141480Smckusick register struct dcadevice *dca; 26244318Shibler register u_char code; 26344318Shibler register struct tty *tp; 26441480Smckusick 26541480Smckusick dca = dca_addr[unit]; 26641480Smckusick if ((dca->dca_ic & IC_IR) == 0) 26741480Smckusick return(0); 26844318Shibler while (1) { 26944318Shibler code = dca->dca_iir; 270*49300Shibler #ifdef DEBUG 271*49300Shibler dcaintrcount[code & IIR_IMASK]++; 272*49300Shibler #endif 273*49300Shibler switch (code & IIR_IMASK) { 27444318Shibler case IIR_NOPEND: 27544318Shibler return (1); 276*49300Shibler case IIR_RXTOUT: 27744318Shibler case IIR_RXRDY: 27844318Shibler /* do time-critical read in-line */ 27944318Shibler tp = &dca_tty[unit]; 280*49300Shibler /* 281*49300Shibler * Process a received byte. Inline for speed... 282*49300Shibler */ 28344318Shibler #ifdef KGDB 284*49300Shibler #define RCVBYTE() \ 285*49300Shibler code = dca->dca_data; \ 286*49300Shibler if ((tp->t_state & TS_ISOPEN) == 0) { \ 287*49300Shibler if (kgdb_dev == makedev(dcamajor, unit) && \ 288*49300Shibler code == FRAME_END) \ 289*49300Shibler kgdb_connect(0); /* trap into kgdb */ \ 290*49300Shibler } else \ 291*49300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 292*49300Shibler #else 293*49300Shibler #define RCVBYTE() \ 294*49300Shibler code = dca->dca_data; \ 295*49300Shibler if ((tp->t_state & TS_ISOPEN) != 0) \ 296*49300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 29744318Shibler #endif 298*49300Shibler RCVBYTE(); 299*49300Shibler if (dca_hasfifo & (1 << unit)) { 300*49300Shibler #ifdef DEBUG 301*49300Shibler register int fifocnt = 1; 302*49300Shibler #endif 303*49300Shibler while ((code = dca->dca_lsr) & LSR_RCV_MASK) { 304*49300Shibler if (code == LSR_RXRDY) { 305*49300Shibler RCVBYTE(); 306*49300Shibler } else 307*49300Shibler dcaeint(unit, code, dca); 308*49300Shibler #ifdef DEBUG 309*49300Shibler fifocnt++; 310*49300Shibler #endif 311*49300Shibler } 312*49300Shibler #ifdef DEBUG 313*49300Shibler if (fifocnt > 16) 314*49300Shibler fifoin[0]++; 315*49300Shibler else 316*49300Shibler fifoin[fifocnt]++; 317*49300Shibler #endif 318*49300Shibler } 31944318Shibler break; 32044318Shibler case IIR_TXRDY: 32144318Shibler tp = &dca_tty[unit]; 32244318Shibler tp->t_state &=~ (TS_BUSY|TS_FLUSH); 32344318Shibler if (tp->t_line) 32444318Shibler (*linesw[tp->t_line].l_start)(tp); 32544318Shibler else 32644318Shibler dcastart(tp); 32744318Shibler break; 32844318Shibler case IIR_RLS: 329*49300Shibler dcaeint(unit, dca->dca_lsr, dca); 33044318Shibler break; 33144318Shibler default: 33244318Shibler if (code & IIR_NOPEND) 33344318Shibler return (1); 33444318Shibler log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 33544318Shibler unit, code); 33644318Shibler /* fall through */ 33744318Shibler case IIR_MLSC: 33841480Smckusick dcamint(unit, dca); 33944318Shibler break; 34044318Shibler } 34141480Smckusick } 34241480Smckusick } 34341480Smckusick 344*49300Shibler dcaeint(unit, stat, dca) 345*49300Shibler register int unit, stat; 34641480Smckusick register struct dcadevice *dca; 34741480Smckusick { 34841480Smckusick register struct tty *tp; 349*49300Shibler register int c; 35041480Smckusick 35141480Smckusick tp = &dca_tty[unit]; 35244318Shibler c = dca->dca_data; 35341480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 35441480Smckusick #ifdef KGDB 35541480Smckusick /* we don't care about parity errors */ 35641480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 35749130Skarels kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 35849130Skarels kgdb_connect(0); /* trap into kgdb */ 35941480Smckusick #endif 36041480Smckusick return; 36141480Smckusick } 36241480Smckusick if (stat & (LSR_BI | LSR_FE)) 36341480Smckusick c |= TTY_FE; 36441480Smckusick else if (stat & LSR_PE) 36541480Smckusick c |= TTY_PE; 36641480Smckusick else if (stat & LSR_OE) 36741480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 36841480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 36941480Smckusick } 37041480Smckusick 37141480Smckusick dcamint(unit, dca) 37241480Smckusick register int unit; 37341480Smckusick register struct dcadevice *dca; 37441480Smckusick { 37541480Smckusick register struct tty *tp; 37641480Smckusick register int stat; 37741480Smckusick 37841480Smckusick tp = &dca_tty[unit]; 37941480Smckusick stat = dca->dca_msr; 380*49300Shibler #ifdef DEBUG 381*49300Shibler dcamintcount[stat & 0xf]++; 382*49300Shibler #endif 38344318Shibler if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 38441480Smckusick if (stat & MSR_DCD) 38544318Shibler (void)(*linesw[tp->t_line].l_modem)(tp, 1); 38641480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 38741480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 38844318Shibler } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 38944318Shibler (tp->t_flags & CRTSCTS)) { 39044318Shibler /* the line is up and we want to do rts/cts flow control */ 39144318Shibler if (stat & MSR_CTS) { 39244318Shibler tp->t_state &=~ TS_TTSTOP; 39344318Shibler ttstart(tp); 39444318Shibler } else 39544318Shibler tp->t_state |= TS_TTSTOP; 39641480Smckusick } 39741480Smckusick } 39841480Smckusick 39941480Smckusick dcaioctl(dev, cmd, data, flag) 40041480Smckusick dev_t dev; 40141480Smckusick caddr_t data; 40241480Smckusick { 40341480Smckusick register struct tty *tp; 40441480Smckusick register int unit = UNIT(dev); 40541480Smckusick register struct dcadevice *dca; 40641480Smckusick register int error; 40741480Smckusick 40841480Smckusick tp = &dca_tty[unit]; 40941480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 41041480Smckusick if (error >= 0) 41141480Smckusick return (error); 41241480Smckusick error = ttioctl(tp, cmd, data, flag); 41341480Smckusick if (error >= 0) 41441480Smckusick return (error); 41541480Smckusick 41641480Smckusick dca = dca_addr[unit]; 41741480Smckusick switch (cmd) { 41841480Smckusick 41941480Smckusick case TIOCSBRK: 42041480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 42141480Smckusick break; 42241480Smckusick 42341480Smckusick case TIOCCBRK: 42441480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 42541480Smckusick break; 42641480Smckusick 42741480Smckusick case TIOCSDTR: 42841480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 42941480Smckusick break; 43041480Smckusick 43141480Smckusick case TIOCCDTR: 43241480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 43341480Smckusick break; 43441480Smckusick 43541480Smckusick case TIOCMSET: 43641480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 43741480Smckusick break; 43841480Smckusick 43941480Smckusick case TIOCMBIS: 44041480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 44141480Smckusick break; 44241480Smckusick 44341480Smckusick case TIOCMBIC: 44441480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 44541480Smckusick break; 44641480Smckusick 44741480Smckusick case TIOCMGET: 44841480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 44941480Smckusick break; 45041480Smckusick 45141480Smckusick default: 45241480Smckusick return (ENOTTY); 45341480Smckusick } 45441480Smckusick return (0); 45541480Smckusick } 45641480Smckusick 45741480Smckusick dcaparam(tp, t) 45841480Smckusick register struct tty *tp; 45941480Smckusick register struct termios *t; 46041480Smckusick { 46141480Smckusick register struct dcadevice *dca; 46241480Smckusick register int cfcr, cflag = t->c_cflag; 46341480Smckusick int unit = UNIT(tp->t_dev); 46441480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 46541480Smckusick 46641480Smckusick /* check requested parameters */ 46741480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 46841480Smckusick return(EINVAL); 46941480Smckusick /* and copy to tty */ 47041480Smckusick tp->t_ispeed = t->c_ispeed; 47141480Smckusick tp->t_ospeed = t->c_ospeed; 47241480Smckusick tp->t_cflag = cflag; 47341480Smckusick 47441480Smckusick dca = dca_addr[unit]; 47541480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 47641480Smckusick if (ospeed == 0) { 47741480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 47841480Smckusick return(0); 47941480Smckusick } 48041480Smckusick dca->dca_cfcr |= CFCR_DLAB; 48141480Smckusick dca->dca_data = ospeed & 0xFF; 48241480Smckusick dca->dca_ier = ospeed >> 8; 48341480Smckusick switch (cflag&CSIZE) { 48441480Smckusick case CS5: 48541480Smckusick cfcr = CFCR_5BITS; break; 48641480Smckusick case CS6: 48741480Smckusick cfcr = CFCR_6BITS; break; 48841480Smckusick case CS7: 48941480Smckusick cfcr = CFCR_7BITS; break; 49041480Smckusick case CS8: 49141480Smckusick cfcr = CFCR_8BITS; break; 49241480Smckusick } 49341480Smckusick if (cflag&PARENB) { 49441480Smckusick cfcr |= CFCR_PENAB; 49541480Smckusick if ((cflag&PARODD) == 0) 49641480Smckusick cfcr |= CFCR_PEVEN; 49741480Smckusick } 49841480Smckusick if (cflag&CSTOPB) 49941480Smckusick cfcr |= CFCR_STOPB; 50041480Smckusick dca->dca_cfcr = cfcr; 501*49300Shibler if (dca_hasfifo & (1 << unit)) 502*49300Shibler dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 50341480Smckusick return(0); 50441480Smckusick } 50541480Smckusick 50641480Smckusick dcastart(tp) 50741480Smckusick register struct tty *tp; 50841480Smckusick { 50941480Smckusick register struct dcadevice *dca; 51041480Smckusick int s, unit, c; 51141480Smckusick 51241480Smckusick unit = UNIT(tp->t_dev); 51341480Smckusick dca = dca_addr[unit]; 51441480Smckusick s = spltty(); 51544318Shibler if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 51641480Smckusick goto out; 51741480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 51841480Smckusick if (tp->t_state&TS_ASLEEP) { 51941480Smckusick tp->t_state &= ~TS_ASLEEP; 52041480Smckusick wakeup((caddr_t)&tp->t_outq); 52141480Smckusick } 52241480Smckusick if (tp->t_wsel) { 52341480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 52441480Smckusick tp->t_wsel = 0; 52541480Smckusick tp->t_state &= ~TS_WCOLL; 52641480Smckusick } 52741480Smckusick } 52841480Smckusick if (tp->t_outq.c_cc == 0) 52941480Smckusick goto out; 53044318Shibler if (dca->dca_lsr & LSR_TXRDY) { 53144318Shibler c = getc(&tp->t_outq); 53244318Shibler tp->t_state |= TS_BUSY; 53344318Shibler dca->dca_data = c; 534*49300Shibler if (dca_hasfifo & (1 << unit)) { 535*49300Shibler for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 536*49300Shibler dca->dca_data = getc(&tp->t_outq); 537*49300Shibler #ifdef DEBUG 538*49300Shibler if (c > 16) 539*49300Shibler fifoout[0]++; 540*49300Shibler else 541*49300Shibler fifoout[c]++; 542*49300Shibler #endif 543*49300Shibler } 54444318Shibler } 54541480Smckusick out: 54641480Smckusick splx(s); 54741480Smckusick } 54841480Smckusick 54941480Smckusick /* 55041480Smckusick * Stop output on a line. 55141480Smckusick */ 55241480Smckusick /*ARGSUSED*/ 55341480Smckusick dcastop(tp, flag) 55441480Smckusick register struct tty *tp; 55541480Smckusick { 55641480Smckusick register int s; 55741480Smckusick 55841480Smckusick s = spltty(); 55941480Smckusick if (tp->t_state & TS_BUSY) { 56041480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 56141480Smckusick tp->t_state |= TS_FLUSH; 56241480Smckusick } 56341480Smckusick splx(s); 56441480Smckusick } 56541480Smckusick 56641480Smckusick dcamctl(dev, bits, how) 56741480Smckusick dev_t dev; 56841480Smckusick int bits, how; 56941480Smckusick { 57041480Smckusick register struct dcadevice *dca; 57141480Smckusick register int unit; 57241480Smckusick int s; 57341480Smckusick 57441480Smckusick unit = UNIT(dev); 57541480Smckusick dca = dca_addr[unit]; 57641480Smckusick s = spltty(); 57741480Smckusick switch (how) { 57841480Smckusick 57941480Smckusick case DMSET: 58041480Smckusick dca->dca_mcr = bits; 58141480Smckusick break; 58241480Smckusick 58341480Smckusick case DMBIS: 58441480Smckusick dca->dca_mcr |= bits; 58541480Smckusick break; 58641480Smckusick 58741480Smckusick case DMBIC: 58841480Smckusick dca->dca_mcr &= ~bits; 58941480Smckusick break; 59041480Smckusick 59141480Smckusick case DMGET: 59241480Smckusick bits = dca->dca_msr; 59341480Smckusick break; 59441480Smckusick } 59541480Smckusick (void) splx(s); 59641480Smckusick return(bits); 59741480Smckusick } 59841480Smckusick 59941480Smckusick /* 60041480Smckusick * Following are all routines needed for DCA to act as console 60141480Smckusick */ 60245788Sbostic #include "../hp300/cons.h" 60341480Smckusick 60441480Smckusick dcacnprobe(cp) 60541480Smckusick struct consdev *cp; 60641480Smckusick { 607*49300Shibler int unit; 60841480Smckusick 60949130Skarels /* locate the major number */ 61049130Skarels for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 61149130Skarels if (cdevsw[dcamajor].d_open == dcaopen) 61249130Skarels break; 61349130Skarels 61441480Smckusick /* XXX: ick */ 61541480Smckusick unit = CONUNIT; 616*49300Shibler dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 61741480Smckusick 61841480Smckusick /* make sure hardware exists */ 61941480Smckusick if (badaddr((short *)dca_addr[unit])) { 62041480Smckusick cp->cn_pri = CN_DEAD; 62141480Smckusick return; 62241480Smckusick } 62341480Smckusick 62441480Smckusick /* initialize required fields */ 62549130Skarels cp->cn_dev = makedev(dcamajor, unit); 62641480Smckusick cp->cn_tp = &dca_tty[unit]; 62741480Smckusick switch (dca_addr[unit]->dca_irid) { 62841480Smckusick case DCAID0: 62941480Smckusick case DCAID1: 63041480Smckusick cp->cn_pri = CN_NORMAL; 63141480Smckusick break; 63241480Smckusick case DCAREMID0: 63341480Smckusick case DCAREMID1: 63441480Smckusick cp->cn_pri = CN_REMOTE; 63541480Smckusick break; 63641480Smckusick default: 63741480Smckusick cp->cn_pri = CN_DEAD; 63841480Smckusick break; 63941480Smckusick } 64049130Skarels /* 641*49300Shibler * If dcaconsole is initialized, raise our priority. 64249130Skarels */ 64349130Skarels if (dcaconsole == unit) 64449130Skarels cp->cn_pri = CN_REMOTE; 645*49300Shibler #ifdef KGDB 64649130Skarels if (major(kgdb_dev) == 1) /* XXX */ 64749130Skarels kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 648*49300Shibler #endif 64941480Smckusick } 65041480Smckusick 65141480Smckusick dcacninit(cp) 65241480Smckusick struct consdev *cp; 65341480Smckusick { 65441480Smckusick int unit = UNIT(cp->cn_dev); 65541480Smckusick 65649130Skarels dcainit(unit, dcadefaultrate); 65741480Smckusick dcaconsole = unit; 65849130Skarels dcaconsinit = 1; 65941480Smckusick } 66041480Smckusick 66149130Skarels dcainit(unit, rate) 66249130Skarels int unit, rate; 66341480Smckusick { 66441480Smckusick register struct dcadevice *dca; 66549130Skarels int s; 66641480Smckusick short stat; 66741480Smckusick 66841480Smckusick #ifdef lint 66941480Smckusick stat = unit; if (stat) return; 67041480Smckusick #endif 67141480Smckusick dca = dca_addr[unit]; 67241480Smckusick s = splhigh(); 67341480Smckusick dca->dca_irid = 0xFF; 67441480Smckusick DELAY(100); 67541480Smckusick dca->dca_ic = IC_IE; 67641480Smckusick dca->dca_cfcr = CFCR_DLAB; 67749130Skarels rate = ttspeedtab(rate, dcaspeedtab); 67841480Smckusick dca->dca_data = rate & 0xFF; 67941480Smckusick dca->dca_ier = rate >> 8; 68041480Smckusick dca->dca_cfcr = CFCR_8BITS; 68141480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 682*49300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 68341480Smckusick stat = dca->dca_iir; 68441480Smckusick splx(s); 68541480Smckusick } 68641480Smckusick 68741480Smckusick dcacngetc(dev) 68841480Smckusick { 68941480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 69041480Smckusick short stat; 69141480Smckusick int c, s; 69241480Smckusick 69341480Smckusick #ifdef lint 69441480Smckusick stat = dev; if (stat) return(0); 69541480Smckusick #endif 69641480Smckusick s = splhigh(); 69741480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 69841480Smckusick ; 69941480Smckusick c = dca->dca_data; 70041480Smckusick stat = dca->dca_iir; 70141480Smckusick splx(s); 70241480Smckusick return(c); 70341480Smckusick } 70441480Smckusick 70541480Smckusick /* 70641480Smckusick * Console kernel output character routine. 70741480Smckusick */ 70841480Smckusick dcacnputc(dev, c) 70941480Smckusick dev_t dev; 71041480Smckusick register int c; 71141480Smckusick { 71241480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 71341480Smckusick register int timo; 71441480Smckusick short stat; 71541480Smckusick int s = splhigh(); 71641480Smckusick 71741480Smckusick #ifdef lint 71841480Smckusick stat = dev; if (stat) return; 71941480Smckusick #endif 72049130Skarels #ifdef KGDB 72149130Skarels if (dev != kgdb_dev) 72249130Skarels #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