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*42946Smarc * @(#)dca.c 7.3 (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) { 14541480Smckusick ttychars(tp); 14641480Smckusick tp->t_iflag = TTYDEF_IFLAG; 14741480Smckusick tp->t_oflag = TTYDEF_OFLAG; 14841480Smckusick tp->t_cflag = TTYDEF_CFLAG; 14941480Smckusick tp->t_lflag = TTYDEF_LFLAG; 15041480Smckusick tp->t_ispeed = tp->t_ospeed = dcadefaultrate; 15141480Smckusick dcaparam(tp, &tp->t_termios); 15241480Smckusick ttsetwater(tp); 15341480Smckusick } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 15441480Smckusick return (EBUSY); 15541480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET); 15641480Smckusick if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD)) 15741480Smckusick tp->t_state |= TS_CARR_ON; 15841480Smckusick (void) spltty(); 15941480Smckusick while (!(flag&O_NONBLOCK) && !(tp->t_cflag&CLOCAL) && 16041480Smckusick (tp->t_state & TS_CARR_ON) == 0) { 16141480Smckusick tp->t_state |= TS_WOPEN; 162*42946Smarc if ((error = tsleep((caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 163*42946Smarc ttopen, 0)) || 164*42946Smarc (error = ttclosed(tp))) { 16542353Smckusick tp->t_state &= ~TS_WOPEN; 16642353Smckusick (void) spl0(); 16742353Smckusick return (error); 16842353Smckusick } 16941480Smckusick } 17041480Smckusick (void) spl0(); 17141480Smckusick return ((*linesw[tp->t_line].l_open)(dev, tp)); 17241480Smckusick } 17341480Smckusick 17441480Smckusick /*ARGSUSED*/ 17541480Smckusick dcaclose(dev, flag) 17641480Smckusick dev_t dev; 17741480Smckusick { 17841480Smckusick register struct tty *tp; 17941480Smckusick register struct dcadevice *dca; 18041480Smckusick register int unit; 18141480Smckusick 18241480Smckusick unit = UNIT(dev); 18341480Smckusick dca = dca_addr[unit]; 18441480Smckusick tp = &dca_tty[unit]; 18541480Smckusick (*linesw[tp->t_line].l_close)(tp); 18641480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 18741480Smckusick #ifdef KGDB 18841480Smckusick /* do not disable interrupts if debugging */ 18941480Smckusick if (kgdb_dev != makedev(1, unit)) 19041480Smckusick #endif 19141480Smckusick dca->dca_ier = 0; 19241480Smckusick if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN || 19341480Smckusick (tp->t_state&TS_ISOPEN) == 0) 19441480Smckusick (void) dcamctl(dev, 0, DMSET); 19541480Smckusick ttyclose(tp); 19641480Smckusick return(0); 19741480Smckusick } 19841480Smckusick 19941480Smckusick dcaread(dev, uio, flag) 20041480Smckusick dev_t dev; 20141480Smckusick struct uio *uio; 20241480Smckusick { 20341480Smckusick register struct tty *tp = &dca_tty[UNIT(dev)]; 20441480Smckusick 20541480Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 20641480Smckusick } 20741480Smckusick 20841480Smckusick dcawrite(dev, uio, flag) 20941480Smckusick dev_t dev; 21041480Smckusick struct uio *uio; 21141480Smckusick { 21241480Smckusick int unit = UNIT(dev); 21341480Smckusick register struct tty *tp = &dca_tty[unit]; 21441480Smckusick 21542353Smckusick /* 21642353Smckusick * (XXX) We disallow virtual consoles if the physical console is 21742353Smckusick * a serial port. This is in case there is a display attached that 21842353Smckusick * is not the console. In that situation we don't need/want the X 21942353Smckusick * server taking over the console. 22042353Smckusick */ 22142353Smckusick if (constty && unit == dcaconsole) 22242353Smckusick constty = NULL; 22341480Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 22441480Smckusick } 22541480Smckusick 22641480Smckusick dcaintr(unit) 22741480Smckusick register int unit; 22841480Smckusick { 22941480Smckusick register struct dcadevice *dca; 23041480Smckusick register int code; 23141480Smckusick 23241480Smckusick dca = dca_addr[unit]; 23341480Smckusick if ((dca->dca_ic & IC_IR) == 0) 23441480Smckusick return(0); 23541480Smckusick while (((code = dca->dca_iir) & IIR_NOPEND) == 0) { 23641480Smckusick code &= IIR_IMASK; 23741480Smckusick if (code == IIR_RLS) 23841480Smckusick dcaeint(unit, dca); 23941480Smckusick else if (code == IIR_RXRDY) 24041480Smckusick dcarint(unit, dca); 24141480Smckusick else if (code == IIR_TXRDY) 24241480Smckusick dcaxint(unit, dca); 24341480Smckusick else 24441480Smckusick dcamint(unit, dca); 24541480Smckusick } 24641480Smckusick return(1); 24741480Smckusick } 24841480Smckusick 24941480Smckusick dcaeint(unit, dca) 25041480Smckusick register int unit; 25141480Smckusick register struct dcadevice *dca; 25241480Smckusick { 25341480Smckusick register struct tty *tp; 25441480Smckusick register int stat, c; 25541480Smckusick 25641480Smckusick tp = &dca_tty[unit]; 25741480Smckusick stat = dca->dca_lsr; 25841480Smckusick c = dca->dca_data & 0xff; 25941480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 26041480Smckusick #ifdef KGDB 26141480Smckusick /* we don't care about parity errors */ 26241480Smckusick if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) && 26341480Smckusick kgdb_dev == makedev(1, unit) && c == '!') { 26441480Smckusick printf("kgdb trap from dca%d\n", unit); 26541480Smckusick /* trap into kgdb */ 26641480Smckusick asm("trap #15;"); 26741480Smckusick } 26841480Smckusick #endif 26941480Smckusick return; 27041480Smckusick } 27141480Smckusick if (stat & (LSR_BI | LSR_FE)) 27241480Smckusick c |= TTY_FE; 27341480Smckusick else if (stat & LSR_PE) 27441480Smckusick c |= TTY_PE; 27541480Smckusick else if (stat & LSR_OE) 27641480Smckusick log(LOG_WARNING, "dca%d: silo overflow\n", unit); 27741480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 27841480Smckusick } 27941480Smckusick 28041480Smckusick dcarint(unit, dca) 28141480Smckusick int unit; 28241480Smckusick register struct dcadevice *dca; 28341480Smckusick { 28441480Smckusick register struct tty *tp; 28541480Smckusick register int c; 28641480Smckusick 28741480Smckusick tp = &dca_tty[unit]; 28841480Smckusick c = dca->dca_data; 28941480Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 29041480Smckusick #ifdef KGDB 29141480Smckusick if (kgdb_dev == makedev(1, unit) && c == '!') { 29241480Smckusick printf("kgdb trap from dca%d\n", unit); 29341480Smckusick /* trap into kgdb */ 29441480Smckusick asm("trap #15;"); 29541480Smckusick } 29641480Smckusick #endif 29741480Smckusick return; 29841480Smckusick } 29941480Smckusick (*linesw[tp->t_line].l_rint)(c, tp); 30041480Smckusick } 30141480Smckusick 30241480Smckusick /*ARGSUSED*/ 30341480Smckusick dcaxint(unit, dca) 30441480Smckusick int unit; 30541480Smckusick struct dcadevice *dca; 30641480Smckusick { 30741480Smckusick register struct tty *tp; 30841480Smckusick 30941480Smckusick tp = &dca_tty[unit]; 31041480Smckusick tp->t_state &= ~TS_BUSY; 31141480Smckusick if (tp->t_state & TS_FLUSH) 31241480Smckusick tp->t_state &= ~TS_FLUSH; 31341480Smckusick if (tp->t_line) 31441480Smckusick (*linesw[tp->t_line].l_start)(tp); 31541480Smckusick else 31641480Smckusick dcastart(tp); 31741480Smckusick } 31841480Smckusick 31941480Smckusick dcamint(unit, dca) 32041480Smckusick register int unit; 32141480Smckusick register struct dcadevice *dca; 32241480Smckusick { 32341480Smckusick register struct tty *tp; 32441480Smckusick register int stat; 32541480Smckusick 32641480Smckusick tp = &dca_tty[unit]; 32741480Smckusick stat = dca->dca_msr; 32841480Smckusick if ((stat & MSR_CCD) && (dcasoftCAR & (1 << unit)) == 0) { 32941480Smckusick if (stat & MSR_DCD) 33041480Smckusick (void) (*linesw[tp->t_line].l_modem)(tp, 1); 33141480Smckusick else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) 33241480Smckusick dca->dca_mcr &= ~(MCR_DTR | MCR_RTS); 33341480Smckusick } 33441480Smckusick } 33541480Smckusick 33641480Smckusick dcaioctl(dev, cmd, data, flag) 33741480Smckusick dev_t dev; 33841480Smckusick caddr_t data; 33941480Smckusick { 34041480Smckusick register struct tty *tp; 34141480Smckusick register int unit = UNIT(dev); 34241480Smckusick register struct dcadevice *dca; 34341480Smckusick register int error; 34441480Smckusick 34541480Smckusick tp = &dca_tty[unit]; 34641480Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 34741480Smckusick if (error >= 0) 34841480Smckusick return (error); 34941480Smckusick error = ttioctl(tp, cmd, data, flag); 35041480Smckusick if (error >= 0) 35141480Smckusick return (error); 35241480Smckusick 35341480Smckusick dca = dca_addr[unit]; 35441480Smckusick switch (cmd) { 35541480Smckusick 35641480Smckusick case TIOCSBRK: 35741480Smckusick dca->dca_cfcr |= CFCR_SBREAK; 35841480Smckusick break; 35941480Smckusick 36041480Smckusick case TIOCCBRK: 36141480Smckusick dca->dca_cfcr &= ~CFCR_SBREAK; 36241480Smckusick break; 36341480Smckusick 36441480Smckusick case TIOCSDTR: 36541480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS); 36641480Smckusick break; 36741480Smckusick 36841480Smckusick case TIOCCDTR: 36941480Smckusick (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC); 37041480Smckusick break; 37141480Smckusick 37241480Smckusick case TIOCMSET: 37341480Smckusick (void) dcamctl(dev, *(int *)data, DMSET); 37441480Smckusick break; 37541480Smckusick 37641480Smckusick case TIOCMBIS: 37741480Smckusick (void) dcamctl(dev, *(int *)data, DMBIS); 37841480Smckusick break; 37941480Smckusick 38041480Smckusick case TIOCMBIC: 38141480Smckusick (void) dcamctl(dev, *(int *)data, DMBIC); 38241480Smckusick break; 38341480Smckusick 38441480Smckusick case TIOCMGET: 38541480Smckusick *(int *)data = dcamctl(dev, 0, DMGET); 38641480Smckusick break; 38741480Smckusick 38841480Smckusick default: 38941480Smckusick return (ENOTTY); 39041480Smckusick } 39141480Smckusick return (0); 39241480Smckusick } 39341480Smckusick 39441480Smckusick dcaparam(tp, t) 39541480Smckusick register struct tty *tp; 39641480Smckusick register struct termios *t; 39741480Smckusick { 39841480Smckusick register struct dcadevice *dca; 39941480Smckusick register int cfcr, cflag = t->c_cflag; 40041480Smckusick int unit = UNIT(tp->t_dev); 40141480Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab); 40241480Smckusick 40341480Smckusick /* check requested parameters */ 40441480Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed)) 40541480Smckusick return(EINVAL); 40641480Smckusick /* and copy to tty */ 40741480Smckusick tp->t_ispeed = t->c_ispeed; 40841480Smckusick tp->t_ospeed = t->c_ospeed; 40941480Smckusick tp->t_cflag = cflag; 41041480Smckusick 41141480Smckusick dca = dca_addr[unit]; 41241480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC; 41341480Smckusick if (ospeed == 0) { 41441480Smckusick (void) dcamctl(unit, 0, DMSET); /* hang up line */ 41541480Smckusick return(0); 41641480Smckusick } 41741480Smckusick dca->dca_cfcr |= CFCR_DLAB; 41841480Smckusick dca->dca_data = ospeed & 0xFF; 41941480Smckusick dca->dca_ier = ospeed >> 8; 42041480Smckusick switch (cflag&CSIZE) { 42141480Smckusick case CS5: 42241480Smckusick cfcr = CFCR_5BITS; break; 42341480Smckusick case CS6: 42441480Smckusick cfcr = CFCR_6BITS; break; 42541480Smckusick case CS7: 42641480Smckusick cfcr = CFCR_7BITS; break; 42741480Smckusick case CS8: 42841480Smckusick cfcr = CFCR_8BITS; break; 42941480Smckusick } 43041480Smckusick if (cflag&PARENB) { 43141480Smckusick cfcr |= CFCR_PENAB; 43241480Smckusick if ((cflag&PARODD) == 0) 43341480Smckusick cfcr |= CFCR_PEVEN; 43441480Smckusick } 43541480Smckusick if (cflag&CSTOPB) 43641480Smckusick cfcr |= CFCR_STOPB; 43741480Smckusick dca->dca_cfcr = cfcr; 43841480Smckusick return(0); 43941480Smckusick } 44041480Smckusick 44141480Smckusick dcastart(tp) 44241480Smckusick register struct tty *tp; 44341480Smckusick { 44441480Smckusick register struct dcadevice *dca; 44541480Smckusick int s, unit, c; 44641480Smckusick 44741480Smckusick unit = UNIT(tp->t_dev); 44841480Smckusick dca = dca_addr[unit]; 44941480Smckusick s = spltty(); 45041480Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 45141480Smckusick goto out; 45241480Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 45341480Smckusick if (tp->t_state&TS_ASLEEP) { 45441480Smckusick tp->t_state &= ~TS_ASLEEP; 45541480Smckusick wakeup((caddr_t)&tp->t_outq); 45641480Smckusick } 45741480Smckusick if (tp->t_wsel) { 45841480Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 45941480Smckusick tp->t_wsel = 0; 46041480Smckusick tp->t_state &= ~TS_WCOLL; 46141480Smckusick } 46241480Smckusick } 46341480Smckusick if (tp->t_outq.c_cc == 0) 46441480Smckusick goto out; 46541480Smckusick c = getc(&tp->t_outq); 46641480Smckusick tp->t_state |= TS_BUSY; 46741480Smckusick dca->dca_data = c; 46841480Smckusick out: 46941480Smckusick splx(s); 47041480Smckusick } 47141480Smckusick 47241480Smckusick /* 47341480Smckusick * Stop output on a line. 47441480Smckusick */ 47541480Smckusick /*ARGSUSED*/ 47641480Smckusick dcastop(tp, flag) 47741480Smckusick register struct tty *tp; 47841480Smckusick { 47941480Smckusick register int s; 48041480Smckusick 48141480Smckusick s = spltty(); 48241480Smckusick if (tp->t_state & TS_BUSY) { 48341480Smckusick if ((tp->t_state&TS_TTSTOP)==0) 48441480Smckusick tp->t_state |= TS_FLUSH; 48541480Smckusick } 48641480Smckusick splx(s); 48741480Smckusick } 48841480Smckusick 48941480Smckusick dcamctl(dev, bits, how) 49041480Smckusick dev_t dev; 49141480Smckusick int bits, how; 49241480Smckusick { 49341480Smckusick register struct dcadevice *dca; 49441480Smckusick register int unit; 49541480Smckusick int s; 49641480Smckusick 49741480Smckusick unit = UNIT(dev); 49841480Smckusick dca = dca_addr[unit]; 49941480Smckusick s = spltty(); 50041480Smckusick switch (how) { 50141480Smckusick 50241480Smckusick case DMSET: 50341480Smckusick dca->dca_mcr = bits; 50441480Smckusick break; 50541480Smckusick 50641480Smckusick case DMBIS: 50741480Smckusick dca->dca_mcr |= bits; 50841480Smckusick break; 50941480Smckusick 51041480Smckusick case DMBIC: 51141480Smckusick dca->dca_mcr &= ~bits; 51241480Smckusick break; 51341480Smckusick 51441480Smckusick case DMGET: 51541480Smckusick bits = dca->dca_msr; 51641480Smckusick break; 51741480Smckusick } 51841480Smckusick (void) splx(s); 51941480Smckusick return(bits); 52041480Smckusick } 52141480Smckusick 52241480Smckusick /* 52341480Smckusick * Following are all routines needed for DCA to act as console 52441480Smckusick */ 52541480Smckusick #include "machine/cons.h" 52641480Smckusick 52741480Smckusick dcacnprobe(cp) 52841480Smckusick struct consdev *cp; 52941480Smckusick { 53041480Smckusick int unit, i; 53141480Smckusick extern int dcaopen(); 53241480Smckusick 53341480Smckusick /* XXX: ick */ 53441480Smckusick unit = CONUNIT; 53541480Smckusick dca_addr[CONUNIT] = CONADDR; 53641480Smckusick 53741480Smckusick /* make sure hardware exists */ 53841480Smckusick if (badaddr((short *)dca_addr[unit])) { 53941480Smckusick cp->cn_pri = CN_DEAD; 54041480Smckusick return; 54141480Smckusick } 54241480Smckusick 54341480Smckusick /* locate the major number */ 54441480Smckusick for (i = 0; i < nchrdev; i++) 54541480Smckusick if (cdevsw[i].d_open == dcaopen) 54641480Smckusick break; 54741480Smckusick 54841480Smckusick /* initialize required fields */ 54941480Smckusick cp->cn_dev = makedev(i, unit); 55041480Smckusick cp->cn_tp = &dca_tty[unit]; 55141480Smckusick switch (dca_addr[unit]->dca_irid) { 55241480Smckusick case DCAID0: 55341480Smckusick case DCAID1: 55441480Smckusick cp->cn_pri = CN_NORMAL; 55541480Smckusick break; 55641480Smckusick case DCAREMID0: 55741480Smckusick case DCAREMID1: 55841480Smckusick cp->cn_pri = CN_REMOTE; 55941480Smckusick break; 56041480Smckusick default: 56141480Smckusick cp->cn_pri = CN_DEAD; 56241480Smckusick break; 56341480Smckusick } 56441480Smckusick } 56541480Smckusick 56641480Smckusick dcacninit(cp) 56741480Smckusick struct consdev *cp; 56841480Smckusick { 56941480Smckusick int unit = UNIT(cp->cn_dev); 57041480Smckusick 57141480Smckusick dcainit(unit); 57241480Smckusick dcaconsole = unit; 57341480Smckusick } 57441480Smckusick 57541480Smckusick dcainit(unit) 57641480Smckusick int unit; 57741480Smckusick { 57841480Smckusick register struct dcadevice *dca; 57941480Smckusick int s, rate; 58041480Smckusick short stat; 58141480Smckusick 58241480Smckusick #ifdef lint 58341480Smckusick stat = unit; if (stat) return; 58441480Smckusick #endif 58541480Smckusick dca = dca_addr[unit]; 58641480Smckusick s = splhigh(); 58741480Smckusick dca->dca_irid = 0xFF; 58841480Smckusick DELAY(100); 58941480Smckusick dca->dca_ic = IC_IE; 59041480Smckusick dca->dca_cfcr = CFCR_DLAB; 59141480Smckusick rate = ttspeedtab(dcadefaultrate, dcaspeedtab); 59241480Smckusick dca->dca_data = rate & 0xFF; 59341480Smckusick dca->dca_ier = rate >> 8; 59441480Smckusick dca->dca_cfcr = CFCR_8BITS; 59541480Smckusick dca->dca_ier = IER_ERXRDY | IER_ETXRDY; 59641480Smckusick stat = dca->dca_iir; 59741480Smckusick splx(s); 59841480Smckusick } 59941480Smckusick 60041480Smckusick dcacngetc(dev) 60141480Smckusick { 60241480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 60341480Smckusick short stat; 60441480Smckusick int c, s; 60541480Smckusick 60641480Smckusick #ifdef lint 60741480Smckusick stat = dev; if (stat) return(0); 60841480Smckusick #endif 60941480Smckusick s = splhigh(); 61041480Smckusick while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0) 61141480Smckusick ; 61241480Smckusick c = dca->dca_data; 61341480Smckusick stat = dca->dca_iir; 61441480Smckusick splx(s); 61541480Smckusick return(c); 61641480Smckusick } 61741480Smckusick 61841480Smckusick /* 61941480Smckusick * Console kernel output character routine. 62041480Smckusick */ 62141480Smckusick dcacnputc(dev, c) 62241480Smckusick dev_t dev; 62341480Smckusick register int c; 62441480Smckusick { 62541480Smckusick register struct dcadevice *dca = dca_addr[UNIT(dev)]; 62641480Smckusick register int timo; 62741480Smckusick short stat; 62841480Smckusick int s = splhigh(); 62941480Smckusick 63041480Smckusick #ifdef lint 63141480Smckusick stat = dev; if (stat) return; 63241480Smckusick #endif 63341480Smckusick if (dcaconsole == -1) { 63441480Smckusick (void) dcainit(UNIT(dev)); 63541480Smckusick dcaconsole = UNIT(dev); 63641480Smckusick } 63741480Smckusick /* wait for any pending transmission to finish */ 63841480Smckusick timo = 50000; 63941480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 64041480Smckusick ; 64141480Smckusick dca->dca_data = c; 64241480Smckusick /* wait for this transmission to complete */ 64341480Smckusick timo = 1500000; 64441480Smckusick while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo) 64541480Smckusick ; 64641480Smckusick /* clear any interrupts generated by this transmission */ 64741480Smckusick stat = dca->dca_iir; 64841480Smckusick splx(s); 64941480Smckusick } 65041480Smckusick #endif 651