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*53923Shibler * @(#)dca.c 7.16 (Berkeley) 06/05/92 841480Smckusick */ 941480Smckusick 1041480Smckusick #include "dca.h" 1141480Smckusick #if NDCA > 0 1241480Smckusick /* 13*53923Shibler * Driver for National Semiconductor INS8250/NS16550AF/WD16C552 UARTs. 14*53923Shibler * Includes: 15*53923Shibler * 98626/98644/internal serial interface on hp300/hp400 16*53923Shibler * internal serial ports on hp700 17*53923Shibler * 18*53923Shibler * N.B. On the hp700, there is a "secret bit" with undocumented behavior. 19*53923Shibler * The third bit of the Modem Control Register (MCR_IEN == 0x08) must be 20*53923Shibler * set to enable interrupts. 2141480Smckusick */ 2245788Sbostic #include "sys/param.h" 2345788Sbostic #include "sys/systm.h" 2445788Sbostic #include "sys/ioctl.h" 2552529Storek #include "sys/proc.h" 2645788Sbostic #include "sys/tty.h" 2745788Sbostic #include "sys/conf.h" 2845788Sbostic #include "sys/file.h" 2945788Sbostic #include "sys/uio.h" 3045788Sbostic #include "sys/kernel.h" 3145788Sbostic #include "sys/syslog.h" 3241480Smckusick 33*53923Shibler #include "hp/dev/device.h" 3441480Smckusick #include "dcareg.h" 35*53923Shibler 3649130Skarels #include "machine/cpu.h" 37*53923Shibler #ifdef hp300 38*53923Shibler #include "../../hp300/hp300/isr.h" 39*53923Shibler #endif 40*53923Shibler #ifdef hp700 41*53923Shibler #include "machine/asp.h" 42*53923Shibler #endif 4341480Smckusick 4441480Smckusick int dcaprobe(); 4541480Smckusick struct driver dcadriver = { 4641480Smckusick dcaprobe, "dca", 4741480Smckusick }; 4841480Smckusick 4952389Smckusick void dcastart(); 5052389Smckusick int dcaparam(), dcaintr(); 5141480Smckusick int dcasoftCAR; 5241480Smckusick int dca_active; 5349300Shibler int dca_hasfifo; 5441480Smckusick int ndca = NDCA; 5549130Skarels #ifdef DCACONSOLE 5649130Skarels int dcaconsole = DCACONSOLE; 5749130Skarels #else 5841480Smckusick int dcaconsole = -1; 5949130Skarels #endif 6049130Skarels int dcaconsinit; 6141480Smckusick int dcadefaultrate = TTYDEF_SPEED; 6249130Skarels int dcamajor; 6341480Smckusick struct dcadevice *dca_addr[NDCA]; 6441480Smckusick struct tty dca_tty[NDCA]; 65*53923Shibler #ifdef hp300 6641480Smckusick struct isr dcaisr[NDCA]; 67*53923Shibler #endif 6841480Smckusick 6941480Smckusick struct speedtab dcaspeedtab[] = { 7041480Smckusick 0, 0, 7141480Smckusick 50, DCABRD(50), 7241480Smckusick 75, DCABRD(75), 7341480Smckusick 110, DCABRD(110), 7441480Smckusick 134, DCABRD(134), 7541480Smckusick 150, DCABRD(150), 7641480Smckusick 200, DCABRD(200), 7741480Smckusick 300, DCABRD(300), 7841480Smckusick 600, DCABRD(600), 7941480Smckusick 1200, DCABRD(1200), 8041480Smckusick 1800, DCABRD(1800), 8141480Smckusick 2400, DCABRD(2400), 8241480Smckusick 4800, DCABRD(4800), 8341480Smckusick 9600, DCABRD(9600), 8441480Smckusick 19200, DCABRD(19200), 8541480Smckusick 38400, DCABRD(38400), 8641480Smckusick -1, -1 8741480Smckusick }; 8841480Smckusick 8941480Smckusick #ifdef KGDB 9049130Skarels #include "machine/remote-sl.h" 9149130Skarels 9250219Skarels extern dev_t kgdb_dev; 9341480Smckusick extern int kgdb_rate; 9441480Smckusick extern int kgdb_debug_init; 9541480Smckusick #endif 9641480Smckusick 9741480Smckusick #define UNIT(x) minor(x) 9841480Smckusick 9949300Shibler #ifdef DEBUG 10049300Shibler long fifoin[17]; 10149300Shibler long fifoout[17]; 10249300Shibler long dcaintrcount[16]; 10349300Shibler long dcamintcount[16]; 10449300Shibler #endif 10549300Shibler 10641480Smckusick dcaprobe(hd) 10741480Smckusick register struct hp_device *hd; 10841480Smckusick { 10941480Smckusick register struct dcadevice *dca; 11041480Smckusick register int unit; 11141480Smckusick 11241480Smckusick dca = (struct dcadevice *)hd->hp_addr; 113*53923Shibler #ifdef hp300 114*53923Shibler if (dca->dca_id != DCAID0 && 115*53923Shibler dca->dca_id != DCAREMID0 && 116*53923Shibler dca->dca_id != DCAID1 && 117*53923Shibler dca->dca_id != DCAREMID1) 11841480Smckusick return (0); 119*53923Shibler #endif 12041480Smckusick unit = hd->hp_unit; 12141480Smckusick if (unit == dcaconsole) 12241480Smckusick DELAY(100000); 123*53923Shibler #ifdef hp300 124*53923Shibler dca->dca_reset = 0xFF; 12541480Smckusick DELAY(100); 126*53923Shibler #endif 12741480Smckusick 12849300Shibler /* look for a NS 16550AF UART with FIFOs */ 12949300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 13049300Shibler DELAY(100); 13149300Shibler if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK) 13249300Shibler dca_hasfifo |= 1 << unit; 13349300Shibler 134*53923Shibler dca_addr[unit] = dca; 135*53923Shibler #ifdef hp300 13641480Smckusick hd->hp_ipl = DCAIPL(dca->dca_ic); 13741480Smckusick dcaisr[unit].isr_ipl = hd->hp_ipl; 13841480Smckusick dcaisr[unit].isr_arg = unit; 13941480Smckusick dcaisr[unit].isr_intr = dcaintr; 140*53923Shibler isrlink(&dcaisr[unit]); 141*53923Shibler #endif 14241480Smckusick dca_active |= 1 << unit; 143*53923Shibler if (hd->hp_flags) 144*53923Shibler dcasoftCAR |= (1 << unit); 14541480Smckusick #ifdef KGDB 14649130Skarels if (kgdb_dev == makedev(dcamajor, unit)) { 14741480Smckusick if (dcaconsole == unit) 14850219Skarels kgdb_dev = NODEV; /* can't debug over console port */ 14941480Smckusick else { 15049130Skarels (void) dcainit(unit, kgdb_rate); 15150219Skarels dcaconsinit = 1; /* don't re-init in dcaputc */ 15241480Smckusick if (kgdb_debug_init) { 15349130Skarels /* 15449130Skarels * Print prefix of device name, 15549130Skarels * let kgdb_connect print the rest. 15649130Skarels */ 15749130Skarels printf("dca%d: ", unit); 15849130Skarels kgdb_connect(1); 15941480Smckusick } else 16041480Smckusick printf("dca%d: kgdb enabled\n", unit); 16141480Smckusick } 16241480Smckusick } 16341480Smckusick #endif 164*53923Shibler #ifdef hp300 16541480Smckusick dca->dca_ic = IC_IE; 166*53923Shibler #endif 16741480Smckusick /* 16849130Skarels * Need to reset baud rate, etc. of next print so reset dcaconsinit. 16949130Skarels * Also make sure console is always "hardwired." 17041480Smckusick */ 17141480Smckusick if (unit == dcaconsole) { 17249130Skarels dcaconsinit = 0; 17341480Smckusick dcasoftCAR |= (1 << unit); 17441480Smckusick } 17541480Smckusick return (1); 17641480Smckusick } 17741480Smckusick 17849130Skarels /* ARGSUSED */ 17949130Skarels #ifdef __STDC__ 18049130Skarels dcaopen(dev_t dev, int flag, int mode, struct proc *p) 18149130Skarels #else 18249130Skarels dcaopen(dev, flag, mode, p) 18341480Smckusick dev_t dev; 18449130Skarels int flag, mode; 18549130Skarels struct proc *p; 18649130Skarels #endif 18741480Smckusick { 18841480Smckusick register struct tty *tp; 18941480Smckusick register int unit; 19044762Skarels int error = 0; 19141480Smckusick 19241480Smckusick unit = UNIT(dev); 19341480Smckusick if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 19441480Smckusick return (ENXIO); 19541480Smckusick tp = &dca_tty[unit]; 19641480Smckusick tp->t_oproc = dcastart; 19741480Smckusick tp->t_param = dcaparam; 19841480Smckusick tp->t_dev = dev; 19941480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 20042950Smarc tp->t_state |= TS_WOPEN; 20141480Smckusick ttychars(tp); 20249130Skarels if (tp->t_ispeed == 0) { 20349130Skarels tp->t_iflag = TTYDEF_IFLAG; 20449130Skarels tp->t_oflag = TTYDEF_OFLAG; 20549130Skarels tp->t_cflag = TTYDEF_CFLAG; 20649130Skarels tp->t_lflag = TTYDEF_LFLAG; 20749130Skarels tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 20849130Skarels } 20941480Smckusick dcaparam(tp, &tp->t_termios); 21041480Smckusick ttsetwater(tp); 21149130Skarels } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) 21241480Smckusick return (EBUSY); 21341480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 21441480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 21541480Smckusick tp->t_state |= TS_CARR_ON; 21641480Smckusick (void) spltty(); 21744295Shibler while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 && 21841480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 21941480Smckusick tp->t_state |= TS_WOPEN; 22044295Shibler if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 22144295Shibler ttopen, 0)) 22244295Shibler break; 22341480Smckusick } 22441480Smckusick (void) spl0(); 22544295Shibler if (error == 0) 22644295Shibler error = (*linesw[tp->t_line].l_open)(dev, tp); 22744295Shibler return (error); 22841480Smckusick } 22941480Smckusick 23041480Smckusick /*ARGSUSED*/ 23149750Smarc dcaclose(dev, flag, mode, p) 23241480Smckusick dev_t dev; 23349750Smarc int flag, mode; 23449750Smarc struct proc *p; 23541480Smckusick { 23641480Smckusick register struct tty *tp; 23741480Smckusick register struct dcadevice *dca; 23841480Smckusick register int unit; 23941480Smckusick 24041480Smckusick unit = UNIT(dev); 24141480Smckusick dca = dca_addr[unit]; 24241480Smckusick tp = &dca_tty[unit]; 24349750Smarc (*linesw[tp->t_line].l_close)(tp, flag); 24441480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 24541480Smckusick #ifdef KGDB 24641480Smckusick /* do not disable interrupts if debugging */ 24749130Skarels if (dev != kgdb_dev) 24841480Smckusick #endif 24941480Smckusick dca->dca_ier = 0; 25050219Skarels if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 25150219Skarels (tp->t_state&TS_ISOPEN) == 0) 25250219Skarels (void) dcamctl(dev, 0, DMSET); 25341480Smckusick ttyclose(tp); 25450219Skarels return (0); 25541480Smckusick } 25641480Smckusick 25741480Smckusick dcaread(dev, uio, flag) 25841480Smckusick dev_t dev; 25941480Smckusick struct uio *uio; 26041480Smckusick { 26141480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 26241480Smckusick 26341480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 26441480Smckusick } 26541480Smckusick 26641480Smckusick dcawrite(dev, uio, flag) 26741480Smckusick dev_t dev; 26841480Smckusick struct uio *uio; 26941480Smckusick { 27041480Smckusick int unit = UNIT(dev); 27141480Smckusick register struct tty *tp = &dca_tty[unit]; 272*53923Shibler extern struct tty *constty; 27341480Smckusick 27442353Smckusick /* 27542353Smckusick * (XXX) We disallow virtual consoles if the physical console is 27642353Smckusick * a serial port. This is in case there is a display attached that 27742353Smckusick * is not the console. In that situation we don't need/want the X 27842353Smckusick * server taking over the console. 27942353Smckusick */ 28042353Smckusick if (constty && unit == dcaconsole) 28142353Smckusick constty = NULL; 28241480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 28341480Smckusick } 28441480Smckusick 28541480Smckusick dcaintr(unit) 28641480Smckusick register int unit; 28741480Smckusick { 28841480Smckusick register struct dcadevice *dca; 28944318Shibler register u_char code; 29044318Shibler register struct tty *tp; 29141480Smckusick 29241480Smckusick dca = dca_addr[unit]; 293*53923Shibler #ifdef hp300 294*53923Shibler if ((dca->dca_ic & (IC_IR|IC_IE)) != (IC_IR|IC_IE)) 29550219Skarels return (0); 296*53923Shibler #endif 29744318Shibler while (1) { 29844318Shibler code = dca->dca_iir; 29949300Shibler #ifdef DEBUG 30049300Shibler dcaintrcount[code & IIR_IMASK]++; 30149300Shibler #endif 30249300Shibler switch (code & IIR_IMASK) { 30344318Shibler case IIR_NOPEND: 30444318Shibler return (1); 30549300Shibler case IIR_RXTOUT: 30644318Shibler case IIR_RXRDY: 30744318Shibler /* do time-critical read in-line */ 30844318Shibler tp = &dca_tty[unit]; 30949300Shibler /* 31049300Shibler * Process a received byte. Inline for speed... 31149300Shibler */ 31244318Shibler #ifdef KGDB 31349300Shibler #define RCVBYTE() \ 31449300Shibler code = dca->dca_data; \ 31549300Shibler if ((tp->t_state & TS_ISOPEN) == 0) { \ 31650219Skarels if (code == FRAME_END && \ 31750219Skarels kgdb_dev == makedev(dcamajor, unit)) \ 31849300Shibler kgdb_connect(0); /* trap into kgdb */ \ 31949300Shibler } else \ 32049300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 32149300Shibler #else 32249300Shibler #define RCVBYTE() \ 32349300Shibler code = dca->dca_data; \ 32449300Shibler if ((tp->t_state & TS_ISOPEN) != 0) \ 32549300Shibler (*linesw[tp->t_line].l_rint)(code, tp) 32644318Shibler #endif 32749300Shibler RCVBYTE(); 32849300Shibler if (dca_hasfifo & (1 << unit)) { 32949300Shibler #ifdef DEBUG 33049300Shibler register int fifocnt = 1; 33149300Shibler #endif 33249300Shibler while ((code = dca->dca_lsr) & LSR_RCV_MASK) { 33349300Shibler if (code == LSR_RXRDY) { 33449300Shibler RCVBYTE(); 33549300Shibler } else 33649300Shibler dcaeint(unit, code, dca); 33749300Shibler #ifdef DEBUG 33849300Shibler fifocnt++; 33949300Shibler #endif 34049300Shibler } 34149300Shibler #ifdef DEBUG 34249300Shibler if (fifocnt > 16) 34349300Shibler fifoin[0]++; 34449300Shibler else 34549300Shibler fifoin[fifocnt]++; 34649300Shibler #endif 34749300Shibler } 34844318Shibler break; 34944318Shibler case IIR_TXRDY: 35044318Shibler tp = &dca_tty[unit]; 35144318Shibler tp->t_state &=~ (TS_BUSY|TS_FLUSH); 35244318Shibler if (tp->t_line) 35344318Shibler (*linesw[tp->t_line].l_start)(tp); 35444318Shibler else 35544318Shibler dcastart(tp); 35644318Shibler break; 35744318Shibler case IIR_RLS: 35849300Shibler dcaeint(unit, dca->dca_lsr, dca); 35944318Shibler break; 36044318Shibler default: 36144318Shibler if (code & IIR_NOPEND) 36244318Shibler return (1); 36344318Shibler log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n", 36444318Shibler unit, code); 36544318Shibler /* fall through */ 36644318Shibler case IIR_MLSC: 36741480Smckusick dcamint(unit, dca); 36844318Shibler break; 36944318Shibler } 37041480Smckusick } 37141480Smckusick } 37241480Smckusick 37349300Shibler dcaeint(unit, stat, dca) 37449300Shibler register int unit, stat; 37541480Smckusick register struct dcadevice *dca; 37641480Smckusick { 37741480Smckusick register struct tty *tp; 37849300Shibler register int c; 37941480Smckusick 38041480Smckusick tp = &dca_tty[unit]; 38144318Shibler c = dca->dca_data; 38241480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 38341480Smckusick #ifdef KGDB 38441480Smckusick /* we don't care about parity errors */ 38541480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 38649130Skarels kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END) 38749130Skarels kgdb_connect(0); /* trap into kgdb */ 38841480Smckusick #endif 38941480Smckusick return; 39041480Smckusick } 39141480Smckusick if (stat & (LSR_BI | LSR_FE)) 39241480Smckusick c |= TTY_FE; 39341480Smckusick else if (stat & LSR_PE) 39441480Smckusick c |= TTY_PE; 39541480Smckusick else if (stat & LSR_OE) 39641480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 39741480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 39841480Smckusick } 39941480Smckusick 40041480Smckusick dcamint(unit, dca) 40141480Smckusick register int unit; 40241480Smckusick register struct dcadevice *dca; 40341480Smckusick { 40441480Smckusick register struct tty *tp; 405*53923Shibler register u_char stat; 40641480Smckusick 40741480Smckusick tp = &dca_tty[unit]; 40841480Smckusick stat = dca->dca_msr; 40949300Shibler #ifdef DEBUG 41049300Shibler dcamintcount[stat & 0xf]++; 41149300Shibler #endif 41244318Shibler if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) { 41341480Smckusick if (stat & MSR_DCD) 41444318Shibler (void)(*linesw[tp->t_line].l_modem)(tp, 1); 41541480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 41641480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 41744318Shibler } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) && 41844318Shibler (tp->t_flags & CRTSCTS)) { 41944318Shibler /* the line is up and we want to do rts/cts flow control */ 42044318Shibler if (stat & MSR_CTS) { 42144318Shibler tp->t_state &=~ TS_TTSTOP; 42244318Shibler ttstart(tp); 42344318Shibler } else 42444318Shibler tp->t_state |= TS_TTSTOP; 42541480Smckusick } 42641480Smckusick } 42741480Smckusick 42852421Smckusick dcaioctl(dev, cmd, data, flag, p) 42941480Smckusick dev_t dev; 43052421Smckusick int cmd; 43141480Smckusick caddr_t data; 43252421Smckusick int flag; 43352421Smckusick struct proc *p; 43441480Smckusick { 43541480Smckusick register struct tty *tp; 43641480Smckusick register int unit = UNIT(dev); 43741480Smckusick register struct dcadevice *dca; 43841480Smckusick register int error; 43941480Smckusick 44041480Smckusick tp = &dca_tty[unit]; 44152421Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 44241480Smckusick if (error >= 0) 44341480Smckusick return (error); 44441480Smckusick error = ttioctl(tp, cmd, data, flag); 44541480Smckusick if (error >= 0) 44641480Smckusick return (error); 44741480Smckusick 44841480Smckusick dca = dca_addr[unit]; 44941480Smckusick switch (cmd) { 45041480Smckusick 45141480Smckusick case TIOCSBRK: 45241480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 45341480Smckusick break; 45441480Smckusick 45541480Smckusick case TIOCCBRK: 45641480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 45741480Smckusick break; 45841480Smckusick 45941480Smckusick case TIOCSDTR: 46041480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 46141480Smckusick break; 46241480Smckusick 46341480Smckusick case TIOCCDTR: 46441480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 46541480Smckusick break; 46641480Smckusick 46741480Smckusick case TIOCMSET: 46841480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 46941480Smckusick break; 47041480Smckusick 47141480Smckusick case TIOCMBIS: 47241480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 47341480Smckusick break; 47441480Smckusick 47541480Smckusick case TIOCMBIC: 47641480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 47741480Smckusick break; 47841480Smckusick 47941480Smckusick case TIOCMGET: 48041480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 48141480Smckusick break; 48241480Smckusick 48341480Smckusick default: 48441480Smckusick return (ENOTTY); 48541480Smckusick } 48641480Smckusick return (0); 48741480Smckusick } 48841480Smckusick 48941480Smckusick dcaparam(tp, t) 49041480Smckusick register struct tty *tp; 49141480Smckusick register struct termios *t; 49241480Smckusick { 49341480Smckusick register struct dcadevice *dca; 49441480Smckusick register int cfcr, cflag = t->c_cflag; 49541480Smckusick int unit = UNIT(tp->t_dev); 49641480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 49741480Smckusick 49841480Smckusick /* check requested parameters */ 49941480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 50050219Skarels return (EINVAL); 50141480Smckusick /* and copy to tty */ 50241480Smckusick tp->t_ispeed = t->c_ispeed; 50341480Smckusick tp->t_ospeed = t->c_ospeed; 50441480Smckusick tp->t_cflag = cflag; 50541480Smckusick 50641480Smckusick dca = dca_addr[unit]; 50741480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 508*53923Shibler #ifdef hp700 509*53923Shibler dca->dca_mcr |= MCR_IEN; 510*53923Shibler #endif 51141480Smckusick if (ospeed == 0) { 51241480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 51350219Skarels return (0); 51441480Smckusick } 51541480Smckusick dca->dca_cfcr |= CFCR_DLAB; 51641480Smckusick dca->dca_data = ospeed & 0xFF; 51741480Smckusick dca->dca_ier = ospeed >> 8; 51841480Smckusick switch (cflag&CSIZE) { 51941480Smckusick case CS5: 52041480Smckusick cfcr = CFCR_5BITS; break; 52141480Smckusick case CS6: 52241480Smckusick cfcr = CFCR_6BITS; break; 52341480Smckusick case CS7: 52441480Smckusick cfcr = CFCR_7BITS; break; 52541480Smckusick case CS8: 52641480Smckusick cfcr = CFCR_8BITS; break; 52741480Smckusick } 52841480Smckusick if (cflag&PARENB) { 52941480Smckusick cfcr |= CFCR_PENAB; 53041480Smckusick if ((cflag&PARODD) == 0) 53141480Smckusick cfcr |= CFCR_PEVEN; 53241480Smckusick } 53341480Smckusick if (cflag&CSTOPB) 53441480Smckusick cfcr |= CFCR_STOPB; 53541480Smckusick dca->dca_cfcr = cfcr; 53649300Shibler if (dca_hasfifo & (1 << unit)) 53749300Shibler dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14; 53850219Skarels return (0); 53941480Smckusick } 54041480Smckusick 54152389Smckusick void 54241480Smckusick dcastart(tp) 54341480Smckusick register struct tty *tp; 54441480Smckusick { 54541480Smckusick register struct dcadevice *dca; 54641480Smckusick int s, unit, c; 54741480Smckusick 54841480Smckusick unit = UNIT(tp->t_dev); 54941480Smckusick dca = dca_addr[unit]; 55041480Smckusick s = spltty(); 55144318Shibler if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) 55241480Smckusick goto out; 55341480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 55441480Smckusick if (tp->t_state&TS_ASLEEP) { 55541480Smckusick tp->t_state &= ~TS_ASLEEP; 55641480Smckusick wakeup((caddr_t)&tp->t_outq); 55741480Smckusick } 55852529Storek selwakeup(&tp->t_wsel); 55941480Smckusick } 56041480Smckusick if (tp->t_outq.c_cc == 0) 56141480Smckusick goto out; 56244318Shibler if (dca->dca_lsr & LSR_TXRDY) { 56344318Shibler c = getc(&tp->t_outq); 56444318Shibler tp->t_state |= TS_BUSY; 56544318Shibler dca->dca_data = c; 56649300Shibler if (dca_hasfifo & (1 << unit)) { 56749300Shibler for (c = 1; c < 16 && tp->t_outq.c_cc; ++c) 56849300Shibler dca->dca_data = getc(&tp->t_outq); 56949300Shibler #ifdef DEBUG 57049300Shibler if (c > 16) 57149300Shibler fifoout[0]++; 57249300Shibler else 57349300Shibler fifoout[c]++; 57449300Shibler #endif 57549300Shibler } 57644318Shibler } 57741480Smckusick out: 57841480Smckusick splx(s); 57941480Smckusick } 58041480Smckusick 58141480Smckusick /* 58241480Smckusick * Stop output on a line. 58341480Smckusick */ 58441480Smckusick /*ARGSUSED*/ 58541480Smckusick dcastop(tp, flag) 58641480Smckusick register struct tty *tp; 58741480Smckusick { 58841480Smckusick register int s; 58941480Smckusick 59041480Smckusick s = spltty(); 59141480Smckusick if (tp->t_state & TS_BUSY) { 59241480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 59341480Smckusick tp->t_state |= TS_FLUSH; 59441480Smckusick } 59541480Smckusick splx(s); 59641480Smckusick } 59741480Smckusick 59841480Smckusick dcamctl(dev, bits, how) 59941480Smckusick dev_t dev; 60041480Smckusick int bits, how; 60141480Smckusick { 60241480Smckusick register struct dcadevice *dca; 60341480Smckusick register int unit; 60441480Smckusick int s; 60541480Smckusick 60641480Smckusick unit = UNIT(dev); 60741480Smckusick dca = dca_addr[unit]; 608*53923Shibler #ifdef hp700 609*53923Shibler /* 610*53923Shibler * Always make sure MCR_IEN is set (unless setting to 0) 611*53923Shibler */ 612*53923Shibler #ifdef KGDB 613*53923Shibler if (how == DMSET && kgdb_dev == makedev(dcamajor, unit)) 614*53923Shibler bits |= MCR_IEN; 615*53923Shibler else 616*53923Shibler #endif 617*53923Shibler if (how == DMBIS || (how == DMSET && bits)) 618*53923Shibler bits |= MCR_IEN; 619*53923Shibler else if (how == DMBIC) 620*53923Shibler bits &= ~MCR_IEN; 621*53923Shibler #endif 62241480Smckusick s = spltty(); 62341480Smckusick switch (how) { 62441480Smckusick 62541480Smckusick case DMSET: 62641480Smckusick dca->dca_mcr = bits; 62741480Smckusick break; 62841480Smckusick 62941480Smckusick case DMBIS: 63041480Smckusick dca->dca_mcr |= bits; 63141480Smckusick break; 63241480Smckusick 63341480Smckusick case DMBIC: 63441480Smckusick dca->dca_mcr &= ~bits; 63541480Smckusick break; 63641480Smckusick 63741480Smckusick case DMGET: 63841480Smckusick bits = dca->dca_msr; 63941480Smckusick break; 64041480Smckusick } 64141480Smckusick (void) splx(s); 64250219Skarels return (bits); 64341480Smckusick } 64441480Smckusick 64541480Smckusick /* 64641480Smckusick * Following are all routines needed for DCA to act as console 64741480Smckusick */ 648*53923Shibler #include "hp/dev/cons.h" 64941480Smckusick 65041480Smckusick dcacnprobe(cp) 65141480Smckusick struct consdev *cp; 65241480Smckusick { 65349300Shibler int unit; 65441480Smckusick 65549130Skarels /* locate the major number */ 65649130Skarels for (dcamajor = 0; dcamajor < nchrdev; dcamajor++) 65749130Skarels if (cdevsw[dcamajor].d_open == dcaopen) 65849130Skarels break; 65949130Skarels 66041480Smckusick /* XXX: ick */ 66141480Smckusick unit = CONUNIT; 662*53923Shibler #ifdef hp300 66349300Shibler dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE); 66441480Smckusick 66541480Smckusick /* make sure hardware exists */ 66641480Smckusick if (badaddr((short *)dca_addr[unit])) { 66741480Smckusick cp->cn_pri = CN_DEAD; 66841480Smckusick return; 66941480Smckusick } 670*53923Shibler #endif 671*53923Shibler #ifdef hp700 672*53923Shibler dca_addr[CONUNIT] = CONPORT; 673*53923Shibler #endif 67441480Smckusick 67541480Smckusick /* initialize required fields */ 67649130Skarels cp->cn_dev = makedev(dcamajor, unit); 67741480Smckusick cp->cn_tp = &dca_tty[unit]; 678*53923Shibler #ifdef hp300 679*53923Shibler switch (dca_addr[unit]->dca_id) { 68041480Smckusick case DCAID0: 68141480Smckusick case DCAID1: 68241480Smckusick cp->cn_pri = CN_NORMAL; 68341480Smckusick break; 68441480Smckusick case DCAREMID0: 68541480Smckusick case DCAREMID1: 68641480Smckusick cp->cn_pri = CN_REMOTE; 68741480Smckusick break; 68841480Smckusick default: 68941480Smckusick cp->cn_pri = CN_DEAD; 69041480Smckusick break; 69141480Smckusick } 692*53923Shibler #endif 693*53923Shibler #ifdef hp700 694*53923Shibler cp->cn_pri = CN_NORMAL; 695*53923Shibler #endif 69649130Skarels /* 69749300Shibler * If dcaconsole is initialized, raise our priority. 69849130Skarels */ 69949130Skarels if (dcaconsole == unit) 70049130Skarels cp->cn_pri = CN_REMOTE; 70149300Shibler #ifdef KGDB 70249130Skarels if (major(kgdb_dev) == 1) /* XXX */ 70349130Skarels kgdb_dev = makedev(dcamajor, minor(kgdb_dev)); 70449300Shibler #endif 70541480Smckusick } 70641480Smckusick 70741480Smckusick dcacninit(cp) 70841480Smckusick struct consdev *cp; 70941480Smckusick { 71041480Smckusick int unit = UNIT(cp->cn_dev); 71141480Smckusick 71249130Skarels dcainit(unit, dcadefaultrate); 71341480Smckusick dcaconsole = unit; 71449130Skarels dcaconsinit = 1; 71541480Smckusick } 71641480Smckusick 71749130Skarels dcainit(unit, rate) 71849130Skarels int unit, rate; 71941480Smckusick { 72041480Smckusick register struct dcadevice *dca; 72149130Skarels int s; 72241480Smckusick short stat; 72341480Smckusick 72441480Smckusick #ifdef lint 72541480Smckusick stat = unit; if (stat) return; 72641480Smckusick #endif 72741480Smckusick dca = dca_addr[unit]; 72841480Smckusick s = splhigh(); 729*53923Shibler #ifdef hp300 730*53923Shibler dca->dca_reset = 0xFF; 73141480Smckusick DELAY(100); 73241480Smckusick dca->dca_ic = IC_IE; 733*53923Shibler #endif 73441480Smckusick dca->dca_cfcr = CFCR_DLAB; 73549130Skarels rate = ttspeedtab(rate, dcaspeedtab); 73641480Smckusick dca->dca_data = rate & 0xFF; 73741480Smckusick dca->dca_ier = rate >> 8; 73841480Smckusick dca->dca_cfcr = CFCR_8BITS; 73941480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 740*53923Shibler #ifdef hp700 741*53923Shibler dca->dca_mcr |= MCR_IEN; 742*53923Shibler #endif 74349300Shibler dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14; 744*53923Shibler DELAY(100); 74541480Smckusick stat = dca->dca_iir; 74641480Smckusick splx(s); 74741480Smckusick } 74841480Smckusick 74941480Smckusick dcacngetc(dev) 75041480Smckusick { 75141480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 752*53923Shibler register u_char stat; 75341480Smckusick int c, s; 75441480Smckusick 75541480Smckusick #ifdef lint 75650219Skarels stat = dev; if (stat) return (0); 75741480Smckusick #endif 75841480Smckusick s = splhigh(); 75941480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 76041480Smckusick ; 76141480Smckusick c = dca->dca_data; 76241480Smckusick stat = dca->dca_iir; 76341480Smckusick splx(s); 76450219Skarels return (c); 76541480Smckusick } 76641480Smckusick 76741480Smckusick /* 76841480Smckusick * Console kernel output character routine. 76941480Smckusick */ 77041480Smckusick dcacnputc(dev, c) 77141480Smckusick dev_t dev; 77241480Smckusick register int c; 77341480Smckusick { 77441480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 77541480Smckusick register int timo; 776*53923Shibler register u_char stat; 77741480Smckusick int s = splhigh(); 77841480Smckusick 77941480Smckusick #ifdef lint 78041480Smckusick stat = dev; if (stat) return; 78141480Smckusick #endif 78249130Skarels if (dcaconsinit == 0) { 78349130Skarels (void) dcainit(UNIT(dev), dcadefaultrate); 78449130Skarels dcaconsinit = 1; 78541480Smckusick } 78641480Smckusick /* wait for any pending transmission to finish */ 78741480Smckusick timo = 50000; 78841480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 78941480Smckusick ; 79041480Smckusick dca->dca_data = c; 79141480Smckusick /* wait for this transmission to complete */ 79241480Smckusick timo = 1500000; 79341480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 79441480Smckusick ; 795*53923Shibler /* 796*53923Shibler * If the "normal" interface was busy transfering a character 797*53923Shibler * we must let our interrupt through to keep things moving. 798*53923Shibler * Otherwise, we clear the interrupt that we have caused. 799*53923Shibler */ 800*53923Shibler if ((dca_tty[UNIT(dev)].t_state & TS_BUSY) == 0) 801*53923Shibler stat = dca->dca_iir; 80241480Smckusick splx(s); 80341480Smckusick } 80441480Smckusick #endif 805