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*49750Smarc * @(#)dca.c 7.11 (Berkeley) 05/16/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 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 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) 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*/ 207*49750Smarc dcaclose(dev, flag, mode, p) 20841480Smckusick dev_t dev; 209*49750Smarc int flag, mode; 210*49750Smarc struct proc *p; 21141480Smckusick { 21241480Smckusick register struct tty *tp; 21341480Smckusick register struct dcadevice *dca; 21441480Smckusick register int unit; 21541480Smckusick 21641480Smckusick unit = UNIT(dev); 21741480Smckusick dca = dca_addr[unit]; 21841480Smckusick tp = &dca_tty[unit]; 219*49750Smarc (*linesw[tp->t_line].l_close)(tp, flag); 22041480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 22141480Smckusick #ifdef KGDB 22241480Smckusick /* do not disable interrupts if debugging */ 22349130Skarels if (dev != kgdb_dev) 22441480Smckusick #endif 22541480Smckusick dca->dca_ier = 0; 22649130Skarels (void) dcamctl(dev, 0, DMSET); 22749130Skarels if (tp->t_state & TS_HUPCLS) 22849130Skarels (*linesw[tp->t_line].l_modem)(tp, 0); 22941480Smckusick ttyclose(tp); 23041480Smckusick return(0); 23141480Smckusick } 23241480Smckusick 23341480Smckusick dcaread(dev, uio, flag) 23441480Smckusick dev_t dev; 23541480Smckusick struct uio *uio; 23641480Smckusick { 23741480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 23841480Smckusick 23941480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 24041480Smckusick } 24141480Smckusick 24241480Smckusick dcawrite(dev, uio, flag) 24341480Smckusick dev_t dev; 24441480Smckusick struct uio *uio; 24541480Smckusick { 24641480Smckusick int unit = UNIT(dev); 24741480Smckusick register struct tty *tp = &dca_tty[unit]; 24841480Smckusick 24942353Smckusick /* 25042353Smckusick * (XXX) We disallow virtual consoles if the physical console is 25142353Smckusick * a serial port. This is in case there is a display attached that 25242353Smckusick * is not the console. In that situation we don't need/want the X 25342353Smckusick * server taking over the console. 25442353Smckusick */ 25542353Smckusick if (constty && unit == dcaconsole) 25642353Smckusick constty = NULL; 25741480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 25841480Smckusick } 25941480Smckusick 26041480Smckusick dcaintr(unit) 26141480Smckusick register int unit; 26241480Smckusick { 26341480Smckusick register struct dcadevice *dca; 26444318Shibler register u_char code; 26544318Shibler register struct tty *tp; 26641480Smckusick 26741480Smckusick dca = dca_addr[unit]; 26841480Smckusick if ((dca->dca_ic & IC_IR) == 0) 26941480Smckusick return(0); 27044318Shibler while (1) { 27144318Shibler code = dca->dca_iir; 27249300Shibler #ifdef DEBUG 27349300Shibler dcaintrcount[code & IIR_IMASK]++; 27449300Shibler #endif 27549300Shibler switch (code & IIR_IMASK) { 27644318Shibler case IIR_NOPEND: 27744318Shibler return (1); 27849300Shibler case IIR_RXTOUT: 27944318Shibler case IIR_RXRDY: 28044318Shibler /* do time-critical read in-line */ 28144318Shibler tp = &dca_tty[unit]; 28249300Shibler /* 28349300Shibler * Process a received byte. Inline for speed... 28449300Shibler */ 28544318Shibler #ifdef KGDB 28649300Shibler #define RCVBYTE() \ 28749300Shibler code = dca->dca_data; \ 28849300Shibler if ((tp->t_state & TS_ISOPEN) == 0) { \ 28949300Shibler if (kgdb_dev == makedev(dcamajor, unit) && \ 29049300Shibler code == FRAME_END) \ 29149300Shibler kgdb_connect(0); /* trap into kgdb */ \ 29249300Shibler } else \ 29349300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 29449300Shibler #else 29549300Shibler #define RCVBYTE() \ 29649300Shibler code = dca->dca_data; \ 29749300Shibler if ((tp->t_state & TS_ISOPEN) != 0) \ 29849300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 29944318Shibler #endif 30049300Shibler RCVBYTE(); 30149300Shibler if (dca_hasfifo & (1 << unit)) { 30249300Shibler #ifdef DEBUG 30349300Shibler register int fifocnt = 1; 30449300Shibler #endif 30549300Shibler while ((code = dca->dca_lsr) & LSR_RCV_MASK) { 30649300Shibler if (code == LSR_RXRDY) { 30749300Shibler RCVBYTE(); 30849300Shibler } else 30949300Shibler dcaeint(unit, code, dca); 31049300Shibler #ifdef DEBUG 31149300Shibler fifocnt++; 31249300Shibler #endif 31349300Shibler } 31449300Shibler #ifdef DEBUG 31549300Shibler if (fifocnt > 16) 31649300Shibler fifoin[0]++; 31749300Shibler else 31849300Shibler fifoin[fifocnt]++; 31949300Shibler #endif 32049300Shibler } 32144318Shibler break; 32244318Shibler case IIR_TXRDY: 32344318Shibler tp = &dca_tty[unit]; 32444318Shibler tp->t_state &=~ (TS_BUSY|TS_FLUSH); 32544318Shibler if (tp->t_line) 32644318Shibler (*linesw[tp->t_line].l_start)(tp); 32744318Shibler else 32844318Shibler dcastart(tp); 32944318Shibler break; 33044318Shibler case IIR_RLS: 33149300Shibler dcaeint(unit, dca->dca_lsr, dca); 33244318Shibler break; 33344318Shibler default: 33444318Shibler if (code & IIR_NOPEND) 33544318Shibler return (1); 33644318Shibler log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 33744318Shibler unit, code); 33844318Shibler /* fall through */ 33944318Shibler case IIR_MLSC: 34041480Smckusick dcamint(unit, dca); 34144318Shibler break; 34244318Shibler } 34341480Smckusick } 34441480Smckusick } 34541480Smckusick 34649300Shibler dcaeint(unit, stat, dca) 34749300Shibler register int unit, stat; 34841480Smckusick register struct dcadevice *dca; 34941480Smckusick { 35041480Smckusick register struct tty *tp; 35149300Shibler register int c; 35241480Smckusick 35341480Smckusick tp = &dca_tty[unit]; 35444318Shibler c = dca->dca_data; 35541480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 35641480Smckusick #ifdef KGDB 35741480Smckusick /* we don't care about parity errors */ 35841480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 35949130Skarels kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 36049130Skarels kgdb_connect(0); /* trap into kgdb */ 36141480Smckusick #endif 36241480Smckusick return; 36341480Smckusick } 36441480Smckusick if (stat & (LSR_BI | LSR_FE)) 36541480Smckusick c |= TTY_FE; 36641480Smckusick else if (stat & LSR_PE) 36741480Smckusick c |= TTY_PE; 36841480Smckusick else if (stat & LSR_OE) 36941480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 37041480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 37141480Smckusick } 37241480Smckusick 37341480Smckusick dcamint(unit, dca) 37441480Smckusick register int unit; 37541480Smckusick register struct dcadevice *dca; 37641480Smckusick { 37741480Smckusick register struct tty *tp; 37841480Smckusick register int stat; 37941480Smckusick 38041480Smckusick tp = &dca_tty[unit]; 38141480Smckusick stat = dca->dca_msr; 38249300Shibler #ifdef DEBUG 38349300Shibler dcamintcount[stat & 0xf]++; 38449300Shibler #endif 38544318Shibler if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 38641480Smckusick if (stat & MSR_DCD) 38744318Shibler (void)(*linesw[tp->t_line].l_modem)(tp, 1); 38841480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 38941480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 39044318Shibler } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 39144318Shibler (tp->t_flags & CRTSCTS)) { 39244318Shibler /* the line is up and we want to do rts/cts flow control */ 39344318Shibler if (stat & MSR_CTS) { 39444318Shibler tp->t_state &=~ TS_TTSTOP; 39544318Shibler ttstart(tp); 39644318Shibler } else 39744318Shibler tp->t_state |= TS_TTSTOP; 39841480Smckusick } 39941480Smckusick } 40041480Smckusick 40141480Smckusick dcaioctl(dev, cmd, data, flag) 40241480Smckusick dev_t dev; 40341480Smckusick caddr_t data; 40441480Smckusick { 40541480Smckusick register struct tty *tp; 40641480Smckusick register int unit = UNIT(dev); 40741480Smckusick register struct dcadevice *dca; 40841480Smckusick register int error; 40941480Smckusick 41041480Smckusick tp = &dca_tty[unit]; 41141480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 41241480Smckusick if (error >= 0) 41341480Smckusick return (error); 41441480Smckusick error = ttioctl(tp, cmd, data, flag); 41541480Smckusick if (error >= 0) 41641480Smckusick return (error); 41741480Smckusick 41841480Smckusick dca = dca_addr[unit]; 41941480Smckusick switch (cmd) { 42041480Smckusick 42141480Smckusick case TIOCSBRK: 42241480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 42341480Smckusick break; 42441480Smckusick 42541480Smckusick case TIOCCBRK: 42641480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 42741480Smckusick break; 42841480Smckusick 42941480Smckusick case TIOCSDTR: 43041480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 43141480Smckusick break; 43241480Smckusick 43341480Smckusick case TIOCCDTR: 43441480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 43541480Smckusick break; 43641480Smckusick 43741480Smckusick case TIOCMSET: 43841480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 43941480Smckusick break; 44041480Smckusick 44141480Smckusick case TIOCMBIS: 44241480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 44341480Smckusick break; 44441480Smckusick 44541480Smckusick case TIOCMBIC: 44641480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 44741480Smckusick break; 44841480Smckusick 44941480Smckusick case TIOCMGET: 45041480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 45141480Smckusick break; 45241480Smckusick 45341480Smckusick default: 45441480Smckusick return (ENOTTY); 45541480Smckusick } 45641480Smckusick return (0); 45741480Smckusick } 45841480Smckusick 45941480Smckusick dcaparam(tp, t) 46041480Smckusick register struct tty *tp; 46141480Smckusick register struct termios *t; 46241480Smckusick { 46341480Smckusick register struct dcadevice *dca; 46441480Smckusick register int cfcr, cflag = t->c_cflag; 46541480Smckusick int unit = UNIT(tp->t_dev); 46641480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 46741480Smckusick 46841480Smckusick /* check requested parameters */ 46941480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 47041480Smckusick return(EINVAL); 47141480Smckusick /* and copy to tty */ 47241480Smckusick tp->t_ispeed = t->c_ispeed; 47341480Smckusick tp->t_ospeed = t->c_ospeed; 47441480Smckusick tp->t_cflag = cflag; 47541480Smckusick 47641480Smckusick dca = dca_addr[unit]; 47741480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 47841480Smckusick if (ospeed == 0) { 47941480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 48041480Smckusick return(0); 48141480Smckusick } 48241480Smckusick dca->dca_cfcr |= CFCR_DLAB; 48341480Smckusick dca->dca_data = ospeed & 0xFF; 48441480Smckusick dca->dca_ier = ospeed >> 8; 48541480Smckusick switch (cflag&CSIZE) { 48641480Smckusick case CS5: 48741480Smckusick cfcr = CFCR_5BITS; break; 48841480Smckusick case CS6: 48941480Smckusick cfcr = CFCR_6BITS; break; 49041480Smckusick case CS7: 49141480Smckusick cfcr = CFCR_7BITS; break; 49241480Smckusick case CS8: 49341480Smckusick cfcr = CFCR_8BITS; break; 49441480Smckusick } 49541480Smckusick if (cflag&PARENB) { 49641480Smckusick cfcr |= CFCR_PENAB; 49741480Smckusick if ((cflag&PARODD) == 0) 49841480Smckusick cfcr |= CFCR_PEVEN; 49941480Smckusick } 50041480Smckusick if (cflag&CSTOPB) 50141480Smckusick cfcr |= CFCR_STOPB; 50241480Smckusick dca->dca_cfcr = cfcr; 50349300Shibler if (dca_hasfifo & (1 << unit)) 50449300Shibler dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 50541480Smckusick return(0); 50641480Smckusick } 50741480Smckusick 50841480Smckusick dcastart(tp) 50941480Smckusick register struct tty *tp; 51041480Smckusick { 51141480Smckusick register struct dcadevice *dca; 51241480Smckusick int s, unit, c; 51341480Smckusick 51441480Smckusick unit = UNIT(tp->t_dev); 51541480Smckusick dca = dca_addr[unit]; 51641480Smckusick s = spltty(); 51744318Shibler if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 51841480Smckusick goto out; 51941480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 52041480Smckusick if (tp->t_state&TS_ASLEEP) { 52141480Smckusick tp->t_state &= ~TS_ASLEEP; 52241480Smckusick wakeup((caddr_t)&tp->t_outq); 52341480Smckusick } 52441480Smckusick if (tp->t_wsel) { 52541480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 52641480Smckusick tp->t_wsel = 0; 52741480Smckusick tp->t_state &= ~TS_WCOLL; 52841480Smckusick } 52941480Smckusick } 53041480Smckusick if (tp->t_outq.c_cc == 0) 53141480Smckusick goto out; 53244318Shibler if (dca->dca_lsr & LSR_TXRDY) { 53344318Shibler c = getc(&tp->t_outq); 53444318Shibler tp->t_state |= TS_BUSY; 53544318Shibler dca->dca_data = c; 53649300Shibler if (dca_hasfifo & (1 << unit)) { 53749300Shibler for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 53849300Shibler dca->dca_data = getc(&tp->t_outq); 53949300Shibler #ifdef DEBUG 54049300Shibler if (c > 16) 54149300Shibler fifoout[0]++; 54249300Shibler else 54349300Shibler fifoout[c]++; 54449300Shibler #endif 54549300Shibler } 54644318Shibler } 54741480Smckusick out: 54841480Smckusick splx(s); 54941480Smckusick } 55041480Smckusick 55141480Smckusick /* 55241480Smckusick * Stop output on a line. 55341480Smckusick */ 55441480Smckusick /*ARGSUSED*/ 55541480Smckusick dcastop(tp, flag) 55641480Smckusick register struct tty *tp; 55741480Smckusick { 55841480Smckusick register int s; 55941480Smckusick 56041480Smckusick s = spltty(); 56141480Smckusick if (tp->t_state & TS_BUSY) { 56241480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 56341480Smckusick tp->t_state |= TS_FLUSH; 56441480Smckusick } 56541480Smckusick splx(s); 56641480Smckusick } 56741480Smckusick 56841480Smckusick dcamctl(dev, bits, how) 56941480Smckusick dev_t dev; 57041480Smckusick int bits, how; 57141480Smckusick { 57241480Smckusick register struct dcadevice *dca; 57341480Smckusick register int unit; 57441480Smckusick int s; 57541480Smckusick 57641480Smckusick unit = UNIT(dev); 57741480Smckusick dca = dca_addr[unit]; 57841480Smckusick s = spltty(); 57941480Smckusick switch (how) { 58041480Smckusick 58141480Smckusick case DMSET: 58241480Smckusick dca->dca_mcr = bits; 58341480Smckusick break; 58441480Smckusick 58541480Smckusick case DMBIS: 58641480Smckusick dca->dca_mcr |= bits; 58741480Smckusick break; 58841480Smckusick 58941480Smckusick case DMBIC: 59041480Smckusick dca->dca_mcr &= ~bits; 59141480Smckusick break; 59241480Smckusick 59341480Smckusick case DMGET: 59441480Smckusick bits = dca->dca_msr; 59541480Smckusick break; 59641480Smckusick } 59741480Smckusick (void) splx(s); 59841480Smckusick return(bits); 59941480Smckusick } 60041480Smckusick 60141480Smckusick /* 60241480Smckusick * Following are all routines needed for DCA to act as console 60341480Smckusick */ 60445788Sbostic #include "../hp300/cons.h" 60541480Smckusick 60641480Smckusick dcacnprobe(cp) 60741480Smckusick struct consdev *cp; 60841480Smckusick { 60949300Shibler int unit; 61041480Smckusick 61149130Skarels /* locate the major number */ 61249130Skarels for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 61349130Skarels if (cdevsw[dcamajor].d_open == dcaopen) 61449130Skarels break; 61549130Skarels 61641480Smckusick /* XXX: ick */ 61741480Smckusick unit = CONUNIT; 61849300Shibler dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 61941480Smckusick 62041480Smckusick /* make sure hardware exists */ 62141480Smckusick if (badaddr((short *)dca_addr[unit])) { 62241480Smckusick cp->cn_pri = CN_DEAD; 62341480Smckusick return; 62441480Smckusick } 62541480Smckusick 62641480Smckusick /* initialize required fields */ 62749130Skarels cp->cn_dev = makedev(dcamajor, unit); 62841480Smckusick cp->cn_tp = &dca_tty[unit]; 62941480Smckusick switch (dca_addr[unit]->dca_irid) { 63041480Smckusick case DCAID0: 63141480Smckusick case DCAID1: 63241480Smckusick cp->cn_pri = CN_NORMAL; 63341480Smckusick break; 63441480Smckusick case DCAREMID0: 63541480Smckusick case DCAREMID1: 63641480Smckusick cp->cn_pri = CN_REMOTE; 63741480Smckusick break; 63841480Smckusick default: 63941480Smckusick cp->cn_pri = CN_DEAD; 64041480Smckusick break; 64141480Smckusick } 64249130Skarels /* 64349300Shibler * If dcaconsole is initialized, raise our priority. 64449130Skarels */ 64549130Skarels if (dcaconsole == unit) 64649130Skarels cp->cn_pri = CN_REMOTE; 64749300Shibler #ifdef KGDB 64849130Skarels if (major(kgdb_dev) == 1) /* XXX */ 64949130Skarels kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 65049300Shibler #endif 65141480Smckusick } 65241480Smckusick 65341480Smckusick dcacninit(cp) 65441480Smckusick struct consdev *cp; 65541480Smckusick { 65641480Smckusick int unit = UNIT(cp->cn_dev); 65741480Smckusick 65849130Skarels dcainit(unit, dcadefaultrate); 65941480Smckusick dcaconsole = unit; 66049130Skarels dcaconsinit = 1; 66141480Smckusick } 66241480Smckusick 66349130Skarels dcainit(unit, rate) 66449130Skarels int unit, rate; 66541480Smckusick { 66641480Smckusick register struct dcadevice *dca; 66749130Skarels int s; 66841480Smckusick short stat; 66941480Smckusick 67041480Smckusick #ifdef lint 67141480Smckusick stat = unit; if (stat) return; 67241480Smckusick #endif 67341480Smckusick dca = dca_addr[unit]; 67441480Smckusick s = splhigh(); 67541480Smckusick dca->dca_irid = 0xFF; 67641480Smckusick DELAY(100); 67741480Smckusick dca->dca_ic = IC_IE; 67841480Smckusick dca->dca_cfcr = CFCR_DLAB; 67949130Skarels rate = ttspeedtab(rate, dcaspeedtab); 68041480Smckusick dca->dca_data = rate & 0xFF; 68141480Smckusick dca->dca_ier = rate >> 8; 68241480Smckusick dca->dca_cfcr = CFCR_8BITS; 68341480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 68449300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 68541480Smckusick stat = dca->dca_iir; 68641480Smckusick splx(s); 68741480Smckusick } 68841480Smckusick 68941480Smckusick dcacngetc(dev) 69041480Smckusick { 69141480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 69241480Smckusick short stat; 69341480Smckusick int c, s; 69441480Smckusick 69541480Smckusick #ifdef lint 69641480Smckusick stat = dev; if (stat) return(0); 69741480Smckusick #endif 69841480Smckusick s = splhigh(); 69941480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 70041480Smckusick ; 70141480Smckusick c = dca->dca_data; 70241480Smckusick stat = dca->dca_iir; 70341480Smckusick splx(s); 70441480Smckusick return(c); 70541480Smckusick } 70641480Smckusick 70741480Smckusick /* 70841480Smckusick * Console kernel output character routine. 70941480Smckusick */ 71041480Smckusick dcacnputc(dev, c) 71141480Smckusick dev_t dev; 71241480Smckusick register int c; 71341480Smckusick { 71441480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 71541480Smckusick register int timo; 71641480Smckusick short stat; 71741480Smckusick int s = splhigh(); 71841480Smckusick 71941480Smckusick #ifdef lint 72041480Smckusick stat = dev; if (stat) return; 72141480Smckusick #endif 72249130Skarels #ifdef KGDB 72349130Skarels if (dev != kgdb_dev) 72449130Skarels #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