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*42950Smarc * @(#)dca.c 7.4 (Berkeley) 06/06/90 841480Smckusick */ 941480Smckusick 1041480Smckusick #include "dca.h" 1141480Smckusick #if NDCA > 0 1241480Smckusick /* 1341480Smckusick * 98626/98644/internal serial interface 1441480Smckusick */ 1541480Smckusick #include "param.h" 1641480Smckusick #include "systm.h" 1741480Smckusick #include "ioctl.h" 1841480Smckusick #include "tty.h" 1941480Smckusick #include "user.h" 2041480Smckusick #include "conf.h" 2141480Smckusick #include "file.h" 2241480Smckusick #include "uio.h" 2341480Smckusick #include "kernel.h" 2441480Smckusick #include "syslog.h" 2541480Smckusick 2641480Smckusick #include "device.h" 2741480Smckusick #include "dcareg.h" 2841480Smckusick #include "machine/cpu.h" 2941480Smckusick #include "machine/isr.h" 3041480Smckusick 3141480Smckusick int dcaprobe(); 3241480Smckusick struct driver dcadriver = { 3341480Smckusick dcaprobe, "dca", 3441480Smckusick }; 3541480Smckusick 3641480Smckusick int dcastart(), dcaparam(), dcaintr(); 3741480Smckusick int dcasoftCAR; 3841480Smckusick int dca_active; 3941480Smckusick int ndca = NDCA; 4041480Smckusick int dcaconsole = -1; 4141480Smckusick int dcadefaultrate = TTYDEF_SPEED; 4241480Smckusick struct dcadevice *dca_addr[NDCA]; 4341480Smckusick struct tty dca_tty[NDCA]; 4441480Smckusick struct isr dcaisr[NDCA]; 4541480Smckusick 4641480Smckusick struct speedtab dcaspeedtab[] = { 4741480Smckusick 0, 0, 4841480Smckusick 50, DCABRD(50), 4941480Smckusick 75, DCABRD(75), 5041480Smckusick 110, DCABRD(110), 5141480Smckusick 134, DCABRD(134), 5241480Smckusick 150, DCABRD(150), 5341480Smckusick 200, DCABRD(200), 5441480Smckusick 300, DCABRD(300), 5541480Smckusick 600, DCABRD(600), 5641480Smckusick 1200, DCABRD(1200), 5741480Smckusick 1800, DCABRD(1800), 5841480Smckusick 2400, DCABRD(2400), 5941480Smckusick 4800, DCABRD(4800), 6041480Smckusick 9600, DCABRD(9600), 6141480Smckusick 19200, DCABRD(19200), 6241480Smckusick 38400, DCABRD(38400), 6341480Smckusick -1, -1 6441480Smckusick }; 6541480Smckusick 6641480Smckusick extern struct tty *constty; 6741480Smckusick #ifdef KGDB 6841480Smckusick extern int kgdb_dev; 6941480Smckusick extern int kgdb_rate; 7041480Smckusick extern int kgdb_debug_init; 7141480Smckusick #endif 7241480Smckusick 7341480Smckusick #define UNIT(x) minor(x) 7441480Smckusick 7541480Smckusick dcaprobe(hd) 7641480Smckusick register struct hp_device *hd; 7741480Smckusick { 7841480Smckusick register struct dcadevice *dca; 7941480Smckusick register int unit; 8041480Smckusick 8141480Smckusick dca = (struct dcadevice *)hd->hp_addr; 8241480Smckusick if (dca->dca_irid != DCAID0 && 8341480Smckusick dca->dca_irid != DCAREMID0 && 8441480Smckusick dca->dca_irid != DCAID1 && 8541480Smckusick dca->dca_irid != DCAREMID1) 8641480Smckusick return (0); 8741480Smckusick unit = hd->hp_unit; 8841480Smckusick if (unit == dcaconsole) 8941480Smckusick DELAY(100000); 9041480Smckusick dca->dca_irid = 0xFF; 9141480Smckusick DELAY(100); 9241480Smckusick 9341480Smckusick hd->hp_ipl = DCAIPL(dca->dca_ic); 9441480Smckusick dcaisr[unit].isr_ipl = hd->hp_ipl; 9541480Smckusick dcaisr[unit].isr_arg = unit; 9641480Smckusick dcaisr[unit].isr_intr = dcaintr; 9741480Smckusick dca_addr[unit] = dca; 9841480Smckusick dca_active |= 1 << unit; 9941480Smckusick dcasoftCAR = hd->hp_flags; 10041480Smckusick isrlink(&dcaisr[unit]); 10141480Smckusick #ifdef KGDB 10241480Smckusick if (kgdb_dev == makedev(1, unit)) { 10341480Smckusick if (dcaconsole == unit) 10441480Smckusick kgdb_dev = -1; /* can't debug over console port */ 10541480Smckusick else { 10641480Smckusick (void) dcainit(unit); 10741480Smckusick dcaconsole = -2; /* XXX */ 10841480Smckusick if (kgdb_debug_init) { 10941480Smckusick printf("dca%d: kgdb waiting...", unit); 11041480Smckusick /* trap into kgdb */ 11141480Smckusick asm("trap #15;"); 11241480Smckusick printf("connected.\n"); 11341480Smckusick } else 11441480Smckusick printf("dca%d: kgdb enabled\n", unit); 11541480Smckusick } 11641480Smckusick } 11741480Smckusick #endif 11841480Smckusick dca->dca_ic = IC_IE; 11941480Smckusick /* 12041480Smckusick * Need to reset baud rate, etc. of next print so reset dcaconsole. 12141480Smckusick * Also make sure console is always "hardwired" 12241480Smckusick */ 12341480Smckusick if (unit == dcaconsole) { 12441480Smckusick dcaconsole = -1; 12541480Smckusick dcasoftCAR |= (1 << unit); 12641480Smckusick } 12741480Smckusick return (1); 12841480Smckusick } 12941480Smckusick 13041480Smckusick dcaopen(dev, flag) 13141480Smckusick dev_t dev; 13241480Smckusick { 13341480Smckusick register struct tty *tp; 13441480Smckusick register int unit; 13542353Smckusick int error; 13641480Smckusick 13741480Smckusick unit = UNIT(dev); 13841480Smckusick if (unit >= NDCA || (dca_active & (1 << unit)) == 0) 13941480Smckusick return (ENXIO); 14041480Smckusick tp = &dca_tty[unit]; 14141480Smckusick tp->t_oproc = dcastart; 14241480Smckusick tp->t_param = dcaparam; 14341480Smckusick tp->t_dev = dev; 14441480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 145*42950Smarc tp->t_state |= TS_WOPEN; 14641480Smckusick ttychars(tp); 14741480Smckusick tp->t_iflag = TTYDEF_IFLAG; 14841480Smckusick tp->t_oflag = TTYDEF_OFLAG; 14941480Smckusick tp->t_cflag = TTYDEF_CFLAG; 15041480Smckusick tp->t_lflag = TTYDEF_LFLAG; 15141480Smckusick tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 15241480Smckusick dcaparam(tp, &tp->t_termios); 15341480Smckusick ttsetwater(tp); 15441480Smckusick } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 15541480Smckusick return (EBUSY); 15641480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 15741480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 15841480Smckusick tp->t_state |= TS_CARR_ON; 15941480Smckusick (void) spltty(); 16041480Smckusick while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 16141480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 16241480Smckusick tp->t_state |= TS_WOPEN; 16342946Smarc if ((error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 16442946Smarc ttopen, 0)) || 16542946Smarc (error = ttclosed(tp))) { 16642353Smckusick tp->t_state &= ~TS_WOPEN; 16742353Smckusick (void) spl0(); 16842353Smckusick return (error); 16942353Smckusick } 17041480Smckusick } 17141480Smckusick (void) spl0(); 17241480Smckusick return ((*linesw[tp->t_line].l_open)(dev, tp)); 17341480Smckusick } 17441480Smckusick 17541480Smckusick /*ARGSUSED*/ 17641480Smckusick dcaclose(dev, flag) 17741480Smckusick dev_t dev; 17841480Smckusick { 17941480Smckusick register struct tty *tp; 18041480Smckusick register struct dcadevice *dca; 18141480Smckusick register int unit; 18241480Smckusick 18341480Smckusick unit = UNIT(dev); 18441480Smckusick dca = dca_addr[unit]; 18541480Smckusick tp = &dca_tty[unit]; 18641480Smckusick (*linesw[tp->t_line].l_close)(tp); 18741480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 18841480Smckusick #ifdef KGDB 18941480Smckusick /* do not disable interrupts if debugging */ 19041480Smckusick if (kgdb_dev != makedev(1, unit)) 19141480Smckusick #endif 19241480Smckusick dca->dca_ier = 0; 19341480Smckusick if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 19441480Smckusick (tp->t_state&TS_ISOPEN) == 0) 19541480Smckusick (void) dcamctl(dev, 0, DMSET); 19641480Smckusick ttyclose(tp); 19741480Smckusick return(0); 19841480Smckusick } 19941480Smckusick 20041480Smckusick dcaread(dev, uio, flag) 20141480Smckusick dev_t dev; 20241480Smckusick struct uio *uio; 20341480Smckusick { 20441480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 20541480Smckusick 20641480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 20741480Smckusick } 20841480Smckusick 20941480Smckusick dcawrite(dev, uio, flag) 21041480Smckusick dev_t dev; 21141480Smckusick struct uio *uio; 21241480Smckusick { 21341480Smckusick int unit = UNIT(dev); 21441480Smckusick register struct tty *tp = &dca_tty[unit]; 21541480Smckusick 21642353Smckusick /* 21742353Smckusick * (XXX) We disallow virtual consoles if the physical console is 21842353Smckusick * a serial port. This is in case there is a display attached that 21942353Smckusick * is not the console. In that situation we don't need/want the X 22042353Smckusick * server taking over the console. 22142353Smckusick */ 22242353Smckusick if (constty && unit == dcaconsole) 22342353Smckusick constty = NULL; 22441480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 22541480Smckusick } 22641480Smckusick 22741480Smckusick dcaintr(unit) 22841480Smckusick register int unit; 22941480Smckusick { 23041480Smckusick register struct dcadevice *dca; 23141480Smckusick register int code; 23241480Smckusick 23341480Smckusick dca = dca_addr[unit]; 23441480Smckusick if ((dca->dca_ic & IC_IR) == 0) 23541480Smckusick return(0); 23641480Smckusick while (((code = dca->dca_iir) & IIR_NOPEND) == 0) { 23741480Smckusick code &= IIR_IMASK; 23841480Smckusick if (code == IIR_RLS) 23941480Smckusick dcaeint(unit, dca); 24041480Smckusick else if (code == IIR_RXRDY) 24141480Smckusick dcarint(unit, dca); 24241480Smckusick else if (code == IIR_TXRDY) 24341480Smckusick dcaxint(unit, dca); 24441480Smckusick else 24541480Smckusick dcamint(unit, dca); 24641480Smckusick } 24741480Smckusick return(1); 24841480Smckusick } 24941480Smckusick 25041480Smckusick dcaeint(unit, dca) 25141480Smckusick register int unit; 25241480Smckusick register struct dcadevice *dca; 25341480Smckusick { 25441480Smckusick register struct tty *tp; 25541480Smckusick register int stat, c; 25641480Smckusick 25741480Smckusick tp = &dca_tty[unit]; 25841480Smckusick stat = dca->dca_lsr; 25941480Smckusick c = dca->dca_data & 0xff; 26041480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 26141480Smckusick #ifdef KGDB 26241480Smckusick /* we don't care about parity errors */ 26341480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 26441480Smckusick kgdb_dev == makedev(1, unit) && c == '!') { 26541480Smckusick printf("kgdb trap from dca%d\n", unit); 26641480Smckusick /* trap into kgdb */ 26741480Smckusick asm("trap #15;"); 26841480Smckusick } 26941480Smckusick #endif 27041480Smckusick return; 27141480Smckusick } 27241480Smckusick if (stat & (LSR_BI | LSR_FE)) 27341480Smckusick c |= TTY_FE; 27441480Smckusick else if (stat & LSR_PE) 27541480Smckusick c |= TTY_PE; 27641480Smckusick else if (stat & LSR_OE) 27741480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 27841480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 27941480Smckusick } 28041480Smckusick 28141480Smckusick dcarint(unit, dca) 28241480Smckusick int unit; 28341480Smckusick register struct dcadevice *dca; 28441480Smckusick { 28541480Smckusick register struct tty *tp; 28641480Smckusick register int c; 28741480Smckusick 28841480Smckusick tp = &dca_tty[unit]; 28941480Smckusick c = dca->dca_data; 29041480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 29141480Smckusick #ifdef KGDB 29241480Smckusick if (kgdb_dev == makedev(1, unit) && c == '!') { 29341480Smckusick printf("kgdb trap from dca%d\n", unit); 29441480Smckusick /* trap into kgdb */ 29541480Smckusick asm("trap #15;"); 29641480Smckusick } 29741480Smckusick #endif 29841480Smckusick return; 29941480Smckusick } 30041480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 30141480Smckusick } 30241480Smckusick 30341480Smckusick /*ARGSUSED*/ 30441480Smckusick dcaxint(unit, dca) 30541480Smckusick int unit; 30641480Smckusick struct dcadevice *dca; 30741480Smckusick { 30841480Smckusick register struct tty *tp; 30941480Smckusick 31041480Smckusick tp = &dca_tty[unit]; 31141480Smckusick tp->t_state &= ~TS_BUSY; 31241480Smckusick if (tp->t_state & TS_FLUSH) 31341480Smckusick tp->t_state &= ~TS_FLUSH; 31441480Smckusick if (tp->t_line) 31541480Smckusick (*linesw[tp->t_line].l_start)(tp); 31641480Smckusick else 31741480Smckusick dcastart(tp); 31841480Smckusick } 31941480Smckusick 32041480Smckusick dcamint(unit, dca) 32141480Smckusick register int unit; 32241480Smckusick register struct dcadevice *dca; 32341480Smckusick { 32441480Smckusick register struct tty *tp; 32541480Smckusick register int stat; 32641480Smckusick 32741480Smckusick tp = &dca_tty[unit]; 32841480Smckusick stat = dca->dca_msr; 32941480Smckusick if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) { 33041480Smckusick if (stat & MSR_DCD) 33141480Smckusick (void) (*linesw[tp->t_line].l_modem)(tp, 1); 33241480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 33341480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 33441480Smckusick } 33541480Smckusick } 33641480Smckusick 33741480Smckusick dcaioctl(dev, cmd, data, flag) 33841480Smckusick dev_t dev; 33941480Smckusick caddr_t data; 34041480Smckusick { 34141480Smckusick register struct tty *tp; 34241480Smckusick register int unit = UNIT(dev); 34341480Smckusick register struct dcadevice *dca; 34441480Smckusick register int error; 34541480Smckusick 34641480Smckusick tp = &dca_tty[unit]; 34741480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 34841480Smckusick if (error >= 0) 34941480Smckusick return (error); 35041480Smckusick error = ttioctl(tp, cmd, data, flag); 35141480Smckusick if (error >= 0) 35241480Smckusick return (error); 35341480Smckusick 35441480Smckusick dca = dca_addr[unit]; 35541480Smckusick switch (cmd) { 35641480Smckusick 35741480Smckusick case TIOCSBRK: 35841480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 35941480Smckusick break; 36041480Smckusick 36141480Smckusick case TIOCCBRK: 36241480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 36341480Smckusick break; 36441480Smckusick 36541480Smckusick case TIOCSDTR: 36641480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 36741480Smckusick break; 36841480Smckusick 36941480Smckusick case TIOCCDTR: 37041480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 37141480Smckusick break; 37241480Smckusick 37341480Smckusick case TIOCMSET: 37441480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 37541480Smckusick break; 37641480Smckusick 37741480Smckusick case TIOCMBIS: 37841480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 37941480Smckusick break; 38041480Smckusick 38141480Smckusick case TIOCMBIC: 38241480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 38341480Smckusick break; 38441480Smckusick 38541480Smckusick case TIOCMGET: 38641480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 38741480Smckusick break; 38841480Smckusick 38941480Smckusick default: 39041480Smckusick return (ENOTTY); 39141480Smckusick } 39241480Smckusick return (0); 39341480Smckusick } 39441480Smckusick 39541480Smckusick dcaparam(tp, t) 39641480Smckusick register struct tty *tp; 39741480Smckusick register struct termios *t; 39841480Smckusick { 39941480Smckusick register struct dcadevice *dca; 40041480Smckusick register int cfcr, cflag = t->c_cflag; 40141480Smckusick int unit = UNIT(tp->t_dev); 40241480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 40341480Smckusick 40441480Smckusick /* check requested parameters */ 40541480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 40641480Smckusick return(EINVAL); 40741480Smckusick /* and copy to tty */ 40841480Smckusick tp->t_ispeed = t->c_ispeed; 40941480Smckusick tp->t_ospeed = t->c_ospeed; 41041480Smckusick tp->t_cflag = cflag; 41141480Smckusick 41241480Smckusick dca = dca_addr[unit]; 41341480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 41441480Smckusick if (ospeed == 0) { 41541480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 41641480Smckusick return(0); 41741480Smckusick } 41841480Smckusick dca->dca_cfcr |= CFCR_DLAB; 41941480Smckusick dca->dca_data = ospeed & 0xFF; 42041480Smckusick dca->dca_ier = ospeed >> 8; 42141480Smckusick switch (cflag&CSIZE) { 42241480Smckusick case CS5: 42341480Smckusick cfcr = CFCR_5BITS; break; 42441480Smckusick case CS6: 42541480Smckusick cfcr = CFCR_6BITS; break; 42641480Smckusick case CS7: 42741480Smckusick cfcr = CFCR_7BITS; break; 42841480Smckusick case CS8: 42941480Smckusick cfcr = CFCR_8BITS; break; 43041480Smckusick } 43141480Smckusick if (cflag&PARENB) { 43241480Smckusick cfcr |= CFCR_PENAB; 43341480Smckusick if ((cflag&PARODD) == 0) 43441480Smckusick cfcr |= CFCR_PEVEN; 43541480Smckusick } 43641480Smckusick if (cflag&CSTOPB) 43741480Smckusick cfcr |= CFCR_STOPB; 43841480Smckusick dca->dca_cfcr = cfcr; 43941480Smckusick return(0); 44041480Smckusick } 44141480Smckusick 44241480Smckusick dcastart(tp) 44341480Smckusick register struct tty *tp; 44441480Smckusick { 44541480Smckusick register struct dcadevice *dca; 44641480Smckusick int s, unit, c; 44741480Smckusick 44841480Smckusick unit = UNIT(tp->t_dev); 44941480Smckusick dca = dca_addr[unit]; 45041480Smckusick s = spltty(); 45141480Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 45241480Smckusick goto out; 45341480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 45441480Smckusick if (tp->t_state&TS_ASLEEP) { 45541480Smckusick tp->t_state &= ~TS_ASLEEP; 45641480Smckusick wakeup((caddr_t)&tp->t_outq); 45741480Smckusick } 45841480Smckusick if (tp->t_wsel) { 45941480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 46041480Smckusick tp->t_wsel = 0; 46141480Smckusick tp->t_state &= ~TS_WCOLL; 46241480Smckusick } 46341480Smckusick } 46441480Smckusick if (tp->t_outq.c_cc == 0) 46541480Smckusick goto out; 46641480Smckusick c = getc(&tp->t_outq); 46741480Smckusick tp->t_state |= TS_BUSY; 46841480Smckusick dca->dca_data = c; 46941480Smckusick out: 47041480Smckusick splx(s); 47141480Smckusick } 47241480Smckusick 47341480Smckusick /* 47441480Smckusick * Stop output on a line. 47541480Smckusick */ 47641480Smckusick /*ARGSUSED*/ 47741480Smckusick dcastop(tp, flag) 47841480Smckusick register struct tty *tp; 47941480Smckusick { 48041480Smckusick register int s; 48141480Smckusick 48241480Smckusick s = spltty(); 48341480Smckusick if (tp->t_state & TS_BUSY) { 48441480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 48541480Smckusick tp->t_state |= TS_FLUSH; 48641480Smckusick } 48741480Smckusick splx(s); 48841480Smckusick } 48941480Smckusick 49041480Smckusick dcamctl(dev, bits, how) 49141480Smckusick dev_t dev; 49241480Smckusick int bits, how; 49341480Smckusick { 49441480Smckusick register struct dcadevice *dca; 49541480Smckusick register int unit; 49641480Smckusick int s; 49741480Smckusick 49841480Smckusick unit = UNIT(dev); 49941480Smckusick dca = dca_addr[unit]; 50041480Smckusick s = spltty(); 50141480Smckusick switch (how) { 50241480Smckusick 50341480Smckusick case DMSET: 50441480Smckusick dca->dca_mcr = bits; 50541480Smckusick break; 50641480Smckusick 50741480Smckusick case DMBIS: 50841480Smckusick dca->dca_mcr |= bits; 50941480Smckusick break; 51041480Smckusick 51141480Smckusick case DMBIC: 51241480Smckusick dca->dca_mcr &= ~bits; 51341480Smckusick break; 51441480Smckusick 51541480Smckusick case DMGET: 51641480Smckusick bits = dca->dca_msr; 51741480Smckusick break; 51841480Smckusick } 51941480Smckusick (void) splx(s); 52041480Smckusick return(bits); 52141480Smckusick } 52241480Smckusick 52341480Smckusick /* 52441480Smckusick * Following are all routines needed for DCA to act as console 52541480Smckusick */ 52641480Smckusick #include "machine/cons.h" 52741480Smckusick 52841480Smckusick dcacnprobe(cp) 52941480Smckusick struct consdev *cp; 53041480Smckusick { 53141480Smckusick int unit, i; 53241480Smckusick extern int dcaopen(); 53341480Smckusick 53441480Smckusick /* XXX: ick */ 53541480Smckusick unit = CONUNIT; 53641480Smckusick dca_addr[CONUNIT] = CONADDR; 53741480Smckusick 53841480Smckusick /* make sure hardware exists */ 53941480Smckusick if (badaddr((short *)dca_addr[unit])) { 54041480Smckusick cp->cn_pri = CN_DEAD; 54141480Smckusick return; 54241480Smckusick } 54341480Smckusick 54441480Smckusick /* locate the major number */ 54541480Smckusick for (i = 0; i < nchrdev; i++) 54641480Smckusick if (cdevsw[i].d_open == dcaopen) 54741480Smckusick break; 54841480Smckusick 54941480Smckusick /* initialize required fields */ 55041480Smckusick cp->cn_dev = makedev(i, unit); 55141480Smckusick cp->cn_tp = &dca_tty[unit]; 55241480Smckusick switch (dca_addr[unit]->dca_irid) { 55341480Smckusick case DCAID0: 55441480Smckusick case DCAID1: 55541480Smckusick cp->cn_pri = CN_NORMAL; 55641480Smckusick break; 55741480Smckusick case DCAREMID0: 55841480Smckusick case DCAREMID1: 55941480Smckusick cp->cn_pri = CN_REMOTE; 56041480Smckusick break; 56141480Smckusick default: 56241480Smckusick cp->cn_pri = CN_DEAD; 56341480Smckusick break; 56441480Smckusick } 56541480Smckusick } 56641480Smckusick 56741480Smckusick dcacninit(cp) 56841480Smckusick struct consdev *cp; 56941480Smckusick { 57041480Smckusick int unit = UNIT(cp->cn_dev); 57141480Smckusick 57241480Smckusick dcainit(unit); 57341480Smckusick dcaconsole = unit; 57441480Smckusick } 57541480Smckusick 57641480Smckusick dcainit(unit) 57741480Smckusick int unit; 57841480Smckusick { 57941480Smckusick register struct dcadevice *dca; 58041480Smckusick int s, rate; 58141480Smckusick short stat; 58241480Smckusick 58341480Smckusick #ifdef lint 58441480Smckusick stat = unit; if (stat) return; 58541480Smckusick #endif 58641480Smckusick dca = dca_addr[unit]; 58741480Smckusick s = splhigh(); 58841480Smckusick dca->dca_irid = 0xFF; 58941480Smckusick DELAY(100); 59041480Smckusick dca->dca_ic = IC_IE; 59141480Smckusick dca->dca_cfcr = CFCR_DLAB; 59241480Smckusick rate = ttspeedtab(dcadefaultrate, dcaspeedtab); 59341480Smckusick dca->dca_data = rate & 0xFF; 59441480Smckusick dca->dca_ier = rate >> 8; 59541480Smckusick dca->dca_cfcr = CFCR_8BITS; 59641480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 59741480Smckusick stat = dca->dca_iir; 59841480Smckusick splx(s); 59941480Smckusick } 60041480Smckusick 60141480Smckusick dcacngetc(dev) 60241480Smckusick { 60341480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 60441480Smckusick short stat; 60541480Smckusick int c, s; 60641480Smckusick 60741480Smckusick #ifdef lint 60841480Smckusick stat = dev; if (stat) return(0); 60941480Smckusick #endif 61041480Smckusick s = splhigh(); 61141480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 61241480Smckusick ; 61341480Smckusick c = dca->dca_data; 61441480Smckusick stat = dca->dca_iir; 61541480Smckusick splx(s); 61641480Smckusick return(c); 61741480Smckusick } 61841480Smckusick 61941480Smckusick /* 62041480Smckusick * Console kernel output character routine. 62141480Smckusick */ 62241480Smckusick dcacnputc(dev, c) 62341480Smckusick dev_t dev; 62441480Smckusick register int c; 62541480Smckusick { 62641480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 62741480Smckusick register int timo; 62841480Smckusick short stat; 62941480Smckusick int s = splhigh(); 63041480Smckusick 63141480Smckusick #ifdef lint 63241480Smckusick stat = dev; if (stat) return; 63341480Smckusick #endif 63441480Smckusick if (dcaconsole == -1) { 63541480Smckusick (void) dcainit(UNIT(dev)); 63641480Smckusick dcaconsole = UNIT(dev); 63741480Smckusick } 63841480Smckusick /* wait for any pending transmission to finish */ 63941480Smckusick timo = 50000; 64041480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 64141480Smckusick ; 64241480Smckusick dca->dca_data = c; 64341480Smckusick /* wait for this transmission to complete */ 64441480Smckusick timo = 1500000; 64541480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 64641480Smckusick ; 64741480Smckusick /* clear any interrupts generated by this transmission */ 64841480Smckusick stat = dca->dca_iir; 64941480Smckusick splx(s); 65041480Smckusick } 65141480Smckusick #endif 652