125224Smckusick /* 229216Smckusick * Copyright (c) 1985, 1986 Regents of the University of California. 325224Smckusick * All rights reserved. The Berkeley software License Agreement 425224Smckusick * specifies the terms and conditions for redistribution. 525224Smckusick * 6*30322Skarels * @(#)dmz.c 7.2 (Berkeley) 12/19/86 725224Smckusick */ 825224Smckusick 925224Smckusick /* 1025224Smckusick * DMZ-32 driver 1125224Smckusick * HISTORY 1225224Smckusick * 23-Apr-85 Joe Camaratta (jcc) at Siemens RTL 1325224Smckusick * Driver for DEC's DMZ32 24-line asynchronous multiplexor. 1425224Smckusick * Based on Chris Maloney's driver for DEC's DMF32 1525224Smckusick * 1625224Smckusick * 9-Aug-85 Mike Meyer (mwm) at ucb 1725224Smckusick * Mangled into shape for 4.3. 1825224Smckusick */ 1925224Smckusick 2025224Smckusick #include "dmz.h" 2125224Smckusick #if NDMZ > 0 2225224Smckusick 2325224Smckusick 2425224Smckusick #include "../machine/pte.h" 2525224Smckusick 2625224Smckusick 2725224Smckusick #include "bk.h" 2825224Smckusick #include "uba.h" 2925224Smckusick #include "param.h" 3025224Smckusick #include "conf.h" 3125224Smckusick #include "dir.h" 3225224Smckusick #include "user.h" 3326837Skarels #include "proc.h" 3425224Smckusick #include "ioctl.h" 3525224Smckusick #include "tty.h" 3625224Smckusick #include "map.h" 3725224Smckusick #include "buf.h" 3825224Smckusick #include "vm.h" 3925224Smckusick #include "bkmac.h" 4025224Smckusick #include "clist.h" 4125224Smckusick #include "file.h" 4225224Smckusick #include "uio.h" 4325224Smckusick #include "kernel.h" 4425435Skarels #include "syslog.h" 4525224Smckusick 4625224Smckusick #include "ubareg.h" 4725224Smckusick #include "ubavar.h" 4825224Smckusick #include "dmzreg.h" 4925655Skarels #include "dmreg.h" 5025224Smckusick 5125224Smckusick int dmzprobe(), dmzattach(), dmzrint(), dmzxint(); 5225224Smckusick struct uba_device *dmzinfo[NDMZ]; 5325224Smckusick u_short dmzstd[] = {0, 0}; 5425224Smckusick struct uba_driver dmzdriver = { 5525224Smckusick dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 5625224Smckusick }; 5725224Smckusick 5825224Smckusick #define NDMZLINES (NDMZ*24) 5925224Smckusick 6025224Smckusick int ttrstrt(); 6125224Smckusick struct tty dmz_tty[NDMZLINES]; 6225224Smckusick 6325224Smckusick int dmzsoftCAR[NDMZ]; 6425224Smckusick 6525224Smckusick struct { 6625224Smckusick char dmz_state; /* dmz state */ 6725224Smckusick int dmz_count; /* dmz dma count */ 6825224Smckusick } dmz_softc[NDMZ*24]; 6925224Smckusick 7025224Smckusick #define ST_TXOFF (0x01) /* transmission turned off (^S) */ 7125224Smckusick #define ST_DMA (0x02) /* dma inprogress */ 7225224Smckusick #define ST_INBUSY (0x04) /* stop transmission in busy */ 7325224Smckusick 7425224Smckusick char dmz_speeds[] = { 7525224Smckusick 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 7625224Smckusick }; 7725224Smckusick 7825396Skarels #ifndef PORTSELECTOR 7925396Skarels #define ISPEED B9600 8025396Skarels #define IFLAGS (EVENP|ODDP|ECHO) 8125396Skarels #else 8225396Skarels #define ISPEED B4800 8325396Skarels #define IFLAGS (EVENP|ODDP) 8425396Skarels #endif 8525396Skarels 8625224Smckusick #ifndef lint 8725224Smckusick int ndmz = NDMZLINES; /* Used by pstat/iostat */ 8825224Smckusick #endif 8925224Smckusick 9025224Smckusick short dmzact[NDMZ]; /* Mask of active octets on the dmz */ 9125224Smckusick int dmzstart(); 9225224Smckusick 9325224Smckusick /* 9425224Smckusick * SILO_TIMEOUT represents the number of milliseconds characters can sit 9525224Smckusick * in the input silo without causing an interrupt. If data overruns or 9625224Smckusick * slow XON/XOFF occur, set it lower but AT LEAST equal to 1. 9725224Smckusick */ 9825224Smckusick #define SILO_TIMEOUT (3) 9925224Smckusick 10025224Smckusick /* 10125224Smckusick * DO_DMA_COUNT represents the threshold of the number of output 10225224Smckusick * characters beyond which the driver uses DMA mode. 10325224Smckusick */ 10425224Smckusick #define DO_DMA_COUNT (10) 10525224Smckusick 10625224Smckusick #define TRUE (1) 10725224Smckusick #define FALSE (0) 10825224Smckusick 109*30322Skarels /* 110*30322Skarels * The clist space is mapped by one terminal driver onto each UNIBUS. 111*30322Skarels * The identity of the board which allocated resources is recorded, 112*30322Skarels * so the process may be repeated after UNIBUS resets. 113*30322Skarels * The UBACVT macro converts a clist space address for unibus uban 114*30322Skarels * into an i/o space address for the DMA routine. 115*30322Skarels */ 116*30322Skarels int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ 117*30322Skarels int cbase[NUBA]; /* base address of clists in unibus map */ 11825224Smckusick #define UBACVT(x, uban) (cbase[uban] + ((x) - (char *)cfree)) 11925224Smckusick 12025224Smckusick /* These flags are for debugging purposes only */ 12125224Smckusick int dmz_dma_on = 1; 12225224Smckusick 12325224Smckusick dmzprobe(reg) 12425224Smckusick caddr_t reg; 12525224Smckusick { 12625224Smckusick register int br, cvec; 12725224Smckusick register struct dmzdevice *dmz_addr; 12825224Smckusick register unsigned int a; 12925224Smckusick 13025224Smckusick dmz_addr = (struct dmzdevice *)reg; 13125224Smckusick 13225224Smckusick #ifdef lint 13325224Smckusick br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 13425224Smckusick dmzrinta(0); dmzrintb(0); dmzrintc(0); 13525224Smckusick #endif 13625224Smckusick 13725224Smckusick br = 0x15; 13825224Smckusick 13925224Smckusick a = dmz_addr->dmz_config; 14025224Smckusick if (((a>>12) & ~DMZ_INTERFACE) != 0) { 14125224Smckusick printf(" Unknown interface type\n"); 14225224Smckusick return (0); 14325224Smckusick } 14425224Smckusick if (((a>>8) & DMZ_NOC_MASK) != 3) { 14525224Smckusick printf(" Not all octets are available\n"); 14625224Smckusick return (0); 14725224Smckusick } 14825224Smckusick 14925224Smckusick cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 15025224Smckusick dmz_addr->dmz_config = cvec >> 2; 15125224Smckusick 15225224Smckusick return (sizeof(struct dmzdevice)); 15325224Smckusick } 15425224Smckusick 15525224Smckusick dmzattach(ui) 15625224Smckusick struct uba_device *ui; 15725224Smckusick { 15825224Smckusick dmzsoftCAR[ui->ui_unit] = ui->ui_flags; 15926218Skarels cbase[ui->ui_ubanum] = -1; 160*30322Skarels dmz_uballoc[ui->ui_unit] = -1; 16125224Smckusick } 16225224Smckusick 16325224Smckusick /* ARGSUSED */ 16425224Smckusick dmzopen(device, flag) 16525224Smckusick dev_t device; 16625224Smckusick int flag; 16725224Smckusick { 16825224Smckusick register struct tty *tp; 16925224Smckusick register int unit, controller; 17025224Smckusick register struct dmzdevice *dmz_addr; 17125224Smckusick register struct uba_device *ui; 17225224Smckusick int priority; 17325224Smckusick int octet; 17425224Smckusick 17525224Smckusick unit = minor(device); 17625224Smckusick controller = DMZ(unit); 17725224Smckusick octet = OCTET(unit); 17825224Smckusick 17925224Smckusick if (unit >= NDMZLINES || 18025224Smckusick (ui = dmzinfo[controller]) == 0 || 18125224Smckusick ui->ui_alive == 0) 18225224Smckusick return (ENXIO); 18325224Smckusick 18425224Smckusick tp = &dmz_tty[unit]; 18525224Smckusick 18625224Smckusick if ((tp->t_state & TS_XCLUDE) && u.u_uid != 0) 18725224Smckusick return (EBUSY); 18825224Smckusick 18925224Smckusick dmz_addr = (struct dmzdevice *)ui->ui_addr; 19025224Smckusick tp->t_addr = (caddr_t)dmz_addr; 19125224Smckusick tp->t_oproc = dmzstart; 19225224Smckusick 19325224Smckusick /* 19425224Smckusick * Set up Unibus map registers. Block uba resets, which can 19525224Smckusick * clear the state. 19625224Smckusick */ 19725224Smckusick priority = spl5(); 19826218Skarels if (cbase[ui->ui_ubanum] == -1) { 199*30322Skarels dmz_uballoc[ui->ui_ubanum] = controller; 200*30322Skarels cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 201*30322Skarels (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 20225224Smckusick } 20325224Smckusick 20425224Smckusick if ((dmzact[controller] & (1 << octet)) == 0) { 20525224Smckusick dmz_addr->octet[octet].octet_csr |= DMZ_IE; 20625224Smckusick dmzact[controller] |= 1 << octet; 20725224Smckusick dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT; 20825224Smckusick } 20925224Smckusick 21025224Smckusick splx(priority); 21125224Smckusick 21225224Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 21325224Smckusick ttychars(tp); 21427051Skarels #ifndef PORTSELECTOR 21527051Skarels if (tp->t_ispeed == 0) { 21627051Skarels #else 21727051Skarels tp->t_state |= TS_HUPCLS; 21827051Skarels #endif PORTSELECTOR 21927051Skarels tp->t_ispeed = ISPEED; 22027051Skarels tp->t_ospeed = ISPEED; 22127051Skarels tp->t_flags = IFLAGS; 22227051Skarels #ifndef PORTSELECTOR 22327051Skarels } 22427051Skarels #endif PORTSELECTOR 22525224Smckusick dmz_softc[unit].dmz_state = 0; 22625224Smckusick } 22725655Skarels dmzparam(unit); 22825224Smckusick 22925224Smckusick /* 23025224Smckusick * Wait for carrier, then process line discipline specific open. 23125224Smckusick */ 23225655Skarels if ((dmzmctl(unit, DMZ_ON, DMSET) & DMZ_CAR) || 23325224Smckusick (dmzsoftCAR[controller] & (1 << (unit % 24)))) 23425224Smckusick tp->t_state |= TS_CARR_ON; 23525224Smckusick priority = spl5(); 23625224Smckusick while ((tp->t_state & TS_CARR_ON) == 0) { 23725224Smckusick tp->t_state |= TS_WOPEN; 23825224Smckusick sleep((caddr_t) &tp->t_rawq, TTIPRI); 23925224Smckusick } 24025224Smckusick splx(priority); 24125224Smckusick 24225435Skarels return ((*linesw[tp->t_line].l_open)(device, tp)); 24325224Smckusick } 24425224Smckusick 24525224Smckusick dmzparam(unit) 24625224Smckusick register int unit; 24725224Smckusick { 24825224Smckusick register struct tty *tp; 24925224Smckusick register struct dmzdevice *dmz_addr; 25025655Skarels register int line_parameters; 25125224Smckusick register int octet; 25225224Smckusick int priority; 25325224Smckusick 25425224Smckusick octet = OCTET(unit); 25525224Smckusick 25625224Smckusick tp = &dmz_tty[unit]; 25725224Smckusick dmz_addr = (struct dmzdevice *)tp->t_addr; 25825224Smckusick 25925224Smckusick priority = spl5(); 26025224Smckusick if ((tp->t_ispeed) == 0) { 26125224Smckusick tp->t_state |= TS_HUPCLS; 26225224Smckusick (void) dmzmctl(unit, DMZ_OFF, DMSET); 26325224Smckusick splx(priority); 26425224Smckusick return; 26525224Smckusick } 26625224Smckusick 26725224Smckusick line_parameters = (dmz_speeds[tp->t_ospeed] << 12) | (dmz_speeds[tp->t_ispeed] << 8); 26825224Smckusick 26925224Smckusick if ((tp->t_ispeed) == B134) 27025224Smckusick line_parameters |= DMZ_6BT | DMZ_PEN; 27125655Skarels else if (tp->t_flags & (RAW | LITOUT | PASS8)) 27225224Smckusick line_parameters |= DMZ_8BT; 27325224Smckusick else 27425224Smckusick line_parameters |= DMZ_7BT | DMZ_PEN; 27525224Smckusick 27625224Smckusick if (tp->t_flags & EVENP) 27725224Smckusick line_parameters |= DMZ_EPR; 27825224Smckusick if ((tp->t_ospeed) == B110) 27925224Smckusick line_parameters |= DMZ_SCD; 28025224Smckusick 28125224Smckusick line_parameters |= (unit & 07); 28225224Smckusick 28325224Smckusick dmz_addr->octet[octet].octet_lprm = line_parameters; 28425224Smckusick splx(priority); 28525224Smckusick } 28625224Smckusick 28725224Smckusick /* ARGSUSED */ 28825224Smckusick dmzclose(device, flag) 28925224Smckusick dev_t device; 29025224Smckusick int flag; 29125224Smckusick { 29225224Smckusick register struct tty *tp; 29325224Smckusick register int unit; 29425224Smckusick 29525224Smckusick unit = minor(device); 29625224Smckusick tp = &dmz_tty[unit]; 29725655Skarels (*linesw[tp->t_line].l_close)(tp); 29825224Smckusick 29925224Smckusick /* 30025655Skarels * Clear break, hang-up and close the modem. 30125224Smckusick */ 30225224Smckusick (void) dmzmctl(unit, DMZ_BRK, DMBIC); 30325224Smckusick if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0) 30425224Smckusick (void) dmzmctl(unit, DMZ_OFF, DMSET); 30525224Smckusick ttyclose(tp); 30625224Smckusick return; 30725224Smckusick } 30825224Smckusick 30925224Smckusick dmzreset(uban) 31025224Smckusick int uban; 31125224Smckusick { 31225224Smckusick register int controller, unit; 31325224Smckusick register struct tty *tp; 31425224Smckusick register struct uba_device *ui; 31525224Smckusick register struct dmzdevice *dmz_addr; 31625224Smckusick int i; 31725224Smckusick int octet; 31825224Smckusick 31925224Smckusick for (controller = 0; controller < NDMZ; controller++) { 32025224Smckusick ui = dmzinfo[controller]; 32125224Smckusick if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 32225224Smckusick continue; 32325224Smckusick printf("dmz%d ", controller); 32425224Smckusick dmz_addr = (struct dmzdevice *) ui->ui_addr; 32525224Smckusick 326*30322Skarels if (dmz_uballoc[uban] == controller) { 327*30322Skarels int info; 328*30322Skarels 329*30322Skarels info = uballoc(uban, (caddr_t)cfree, 330*30322Skarels nclist * sizeof(struct cblock), UBA_CANTWAIT); 331*30322Skarels if (info) 332*30322Skarels cbase[uban] = UBAI_ADDR(info); 333*30322Skarels else { 334*30322Skarels printf(" [can't get uba map]"); 335*30322Skarels cbase[uban] = -1; 336*30322Skarels } 33725435Skarels } 33825435Skarels 33925224Smckusick for (octet = 0; octet < 3; octet++) 34025224Smckusick if ((dmzact[controller] & (1 << octet)) != 0) { 34125224Smckusick dmz_addr->octet[octet].octet_csr |= DMZ_IE; 34225224Smckusick dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT; 34325224Smckusick } 34425224Smckusick 34525224Smckusick unit = controller * 24; 34625224Smckusick 34725224Smckusick /* 34825224Smckusick * If a unit is open or waiting for open to complete, 34925224Smckusick * reset it. 35025224Smckusick */ 35125224Smckusick for (i = 0; i < 24; i++) { 35225224Smckusick dmz_softc[unit].dmz_state = 0; 35325224Smckusick tp = &dmz_tty[unit]; 35425224Smckusick if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 35525224Smckusick dmzparam(unit); 35625224Smckusick (void) dmzmctl(unit, DMZ_ON, DMSET); 35725224Smckusick tp->t_state &= ~TS_BUSY; 35825224Smckusick dmzstart(tp); 35925224Smckusick } 36025224Smckusick unit++; 36125224Smckusick } 36225224Smckusick } 36325224Smckusick return; 36425224Smckusick } 36525224Smckusick 36625224Smckusick dmzread(device, uio) 36725224Smckusick dev_t device; 36825224Smckusick struct uio *uio; 36925224Smckusick { 37025224Smckusick register struct tty *tp; 37125224Smckusick int xstatus; 37225224Smckusick 37325224Smckusick tp = &dmz_tty[minor(device)]; 37425224Smckusick xstatus = (*linesw[tp->t_line].l_read)(tp, uio); 37525224Smckusick return (xstatus); 37625224Smckusick } 37725224Smckusick 37825224Smckusick dmzwrite(device, uio) 37925224Smckusick dev_t device; 38025224Smckusick struct uio *uio; 38125224Smckusick { 38225224Smckusick register struct tty *tp; 38325224Smckusick int xstatus; 38425224Smckusick 38525224Smckusick tp = &dmz_tty[minor(device)]; 38625224Smckusick xstatus = (*linesw[tp->t_line].l_write)(tp, uio); 38725224Smckusick return (xstatus); 38825224Smckusick } 38925224Smckusick 39025224Smckusick dmzrinta(controller) 39125224Smckusick int controller; 39225224Smckusick { 39325224Smckusick dmzrint(controller, 0); 39425224Smckusick } 39525224Smckusick 39625224Smckusick dmzrintb(controller) 39725224Smckusick int controller; 39825224Smckusick { 39925224Smckusick dmzrint(controller, 1); 40025224Smckusick } 40125224Smckusick 40225224Smckusick dmzrintc(controller) 40325224Smckusick int controller; 40425224Smckusick { 40525224Smckusick dmzrint(controller, 2); 40625224Smckusick } 40725224Smckusick 40825224Smckusick dmzrint(controller, octet) 40925224Smckusick int controller; 41025224Smckusick register int octet; 41125224Smckusick { 41225224Smckusick register struct tty *tp; 41325224Smckusick register int character; 41425224Smckusick register struct dmzdevice *dmz_addr; 41525224Smckusick register struct tty *tp0; 41625224Smckusick register int unit; 41725224Smckusick register struct uba_device *ui; 41825396Skarels int overrun; 41925224Smckusick 42025224Smckusick overrun = 0; 42125224Smckusick ui = dmzinfo[controller]; 42225224Smckusick if (ui == 0 || ui->ui_alive == 0) 42325224Smckusick return; 42425224Smckusick dmz_addr = (struct dmzdevice *) ui->ui_addr; 42525224Smckusick tp0 = &dmz_tty[controller * 24]; 42625224Smckusick 42725224Smckusick while ((character = dmz_addr->octet[octet].octet_receive.octet_rb) < 0) { 42825224Smckusick unit = (character >> 8) & 07; /* unit is bits 8-10 of rb */ 42925224Smckusick tp = tp0 + (octet * 8 + unit); 43025224Smckusick 43126218Skarels if (character & DMZ_DSC) { 43225655Skarels dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | unit; 43325655Skarels if (dmz_addr->octet[octet].octet_rmstsc & DMZ_CAR) 43425396Skarels (void)(*linesw[tp->t_line].l_modem)(tp, 1); 43527051Skarels else if ((dmzsoftCAR[controller] & 43627051Skarels (1 << (octet * 8 + unit))) == 0 && 43726218Skarels (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 43825655Skarels (void)dmzmctl(tp - dmz_tty, DMZ_OFF, DMSET); 43925224Smckusick continue; 44025224Smckusick } 44125224Smckusick 44225396Skarels if ((tp->t_state&TS_ISOPEN)==0) { 44325396Skarels wakeup((caddr_t)&tp->t_rawq); 44425396Skarels #ifdef PORTSELECTOR 44525396Skarels if ((tp->t_state&TS_WOPEN) == 0) 44625396Skarels #endif 44725396Skarels continue; 44825224Smckusick } 44925224Smckusick 45025224Smckusick if (character & DMZ_PE) { 45125224Smckusick if ((tp->t_flags & (EVENP | ODDP)) == EVENP || 45225224Smckusick (tp->t_flags & (EVENP | ODDP)) == ODDP) 45325224Smckusick continue; 45425224Smckusick } 45525224Smckusick 45625224Smckusick if ((character & DMZ_DO) && overrun == 0) { 45725435Skarels log(LOG_WARNING, "dmz%d: silo overflow\n", controller); 45825224Smckusick overrun = 1; 45925224Smckusick } 46025224Smckusick 46125224Smckusick if (character & DMZ_FE) { 46225224Smckusick if (tp->t_flags & RAW) 46325224Smckusick character = 0; 46425224Smckusick else 46525224Smckusick character = tp->t_intrc; 46625224Smckusick } 46725224Smckusick 46825224Smckusick (*linesw[tp->t_line].l_rint)(character, tp); 46925224Smckusick } 47025224Smckusick 47125224Smckusick return; 47225224Smckusick } 47325224Smckusick 47425224Smckusick dmzxinta(controller) 47525224Smckusick int controller; 47625224Smckusick { 47725224Smckusick dmzxint(controller, 0); 47825224Smckusick } 47925224Smckusick 48025224Smckusick dmzxintb(controller) 48125224Smckusick int controller; 48225224Smckusick { 48325224Smckusick dmzxint(controller, 1); 48425224Smckusick } 48525224Smckusick 48625224Smckusick dmzxintc(controller) 48725224Smckusick int controller; 48825224Smckusick { 48925224Smckusick dmzxint(controller, 2); 49025224Smckusick } 49125224Smckusick 49225224Smckusick dmzxint(controller, octet) 49325224Smckusick int controller; 49425224Smckusick register int octet; 49525224Smckusick { 49625224Smckusick register struct tty *tp; 49725224Smckusick register struct dmzdevice *dmz_addr; 49825224Smckusick register struct uba_device *ui; 49925224Smckusick register int unit, t; 50025224Smckusick int priority; 50125224Smckusick 50225224Smckusick ui = dmzinfo[controller]; 50325224Smckusick dmz_addr = (struct dmzdevice *)ui->ui_addr; 50425224Smckusick 50525224Smckusick priority = spl5(); 50625224Smckusick 50725224Smckusick while ((t = dmz_addr->octet[octet].octet_csr) & DMZ_TRDY) { 50825224Smckusick unit = controller * 24 + (octet * 8 + ((t>>8) & 07)); 50925224Smckusick tp = &dmz_tty[unit]; 51025224Smckusick tp->t_state &= ~TS_BUSY; 51125224Smckusick 51225224Smckusick if (t & DMZ_NXM) 51325224Smckusick printf("dmz%d: NXM line %d\n", controller, 51425224Smckusick octet * 8 + (unit & 07)); 51525224Smckusick 51625224Smckusick if (tp->t_state & TS_FLUSH) { 51725224Smckusick tp->t_state &= ~TS_FLUSH; 51825224Smckusick dmz_addr->octet[octet].octet_csr = 51925224Smckusick DMZ_IE | IR_LCTMR | (unit & 07); 52025224Smckusick dmz_addr->octet[octet].octet_lctmr = 52125224Smckusick (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 52225224Smckusick } else 52325224Smckusick if (dmz_softc[unit].dmz_state & ST_DMA) 52425224Smckusick ndflush(&tp->t_outq, dmz_softc[unit].dmz_count); 52525224Smckusick dmz_softc[unit].dmz_state = 0; 52625224Smckusick 52725224Smckusick if (tp->t_line) 52825224Smckusick (*linesw[tp->t_line].l_start)(tp); 52925224Smckusick else 53025224Smckusick dmzstart(tp); 53125224Smckusick } 53225224Smckusick 53325224Smckusick splx(priority); 53425224Smckusick return; 53525224Smckusick } 53625224Smckusick 53725224Smckusick dmzstart(tp) 53825224Smckusick register struct tty *tp; 53925224Smckusick { 54025224Smckusick register struct dmzdevice *dmz_addr; 54125224Smckusick register int unit, nch, room; 54225224Smckusick int controller, octet; 54325224Smckusick int priority, car, use_dma; 54425224Smckusick register int i; 54525224Smckusick register char *cp; 54625224Smckusick 54725224Smckusick unit = minor(tp->t_dev); 54825224Smckusick controller = DMZ(unit); 54925224Smckusick octet = OCTET(unit); 55025224Smckusick dmz_addr = (struct dmzdevice *)tp->t_addr; 55125224Smckusick 55225224Smckusick priority = spl5(); 55325224Smckusick 55425224Smckusick if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) 55525224Smckusick goto out; 55625224Smckusick 55725224Smckusick /* 55825224Smckusick * If the transmitter has been disabled, reenable it. 55925224Smckusick * If the transmitter was disabled before the xint (the 56025224Smckusick * ST_INBUSY was still on), then reset the BUSY state and 56125224Smckusick * we will wait for the interrupt. If !TS_BUSY, we already 56225224Smckusick * saw the interrupt so we can start another transmission. 56325224Smckusick */ 56425224Smckusick if (dmz_softc[unit].dmz_state & ST_TXOFF) { 56525224Smckusick dmz_addr->octet[octet].octet_csr = 56625224Smckusick DMZ_IE | IR_LCTMR | (unit & 07); 56725224Smckusick dmz_addr->octet[octet].octet_lctmr = 56825224Smckusick (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 56925224Smckusick dmz_softc[unit].dmz_state &= ~ST_TXOFF; 57025224Smckusick if (dmz_softc[unit].dmz_state & ST_INBUSY) { 57125224Smckusick dmz_softc[unit].dmz_state &= ~ST_INBUSY; 57225224Smckusick tp->t_state |= TS_BUSY; 57325224Smckusick goto out; 57425224Smckusick } 57525224Smckusick } 57625224Smckusick 57725224Smckusick if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 57825224Smckusick if (tp->t_state & TS_ASLEEP) { 57925224Smckusick tp->t_state &= ~TS_ASLEEP; 58025224Smckusick wakeup((caddr_t)&tp->t_outq); 58125224Smckusick } 58225224Smckusick if (tp->t_wsel) { 58325224Smckusick selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 58425224Smckusick tp->t_wsel = 0; 58525224Smckusick tp->t_state &= ~TS_WCOLL; 58625224Smckusick } 58725224Smckusick } 58825224Smckusick 58925224Smckusick if (tp->t_outq.c_cc == 0) 59025224Smckusick goto out; 59127443Slepreau if (tp->t_flags & (RAW | LITOUT)) 59225224Smckusick nch = ndqb(&tp->t_outq, 0); 59325224Smckusick else { 59425224Smckusick nch = ndqb(&tp->t_outq, 0200); 59525224Smckusick if (nch == 0) { 59625224Smckusick nch = getc(&tp->t_outq); 59725224Smckusick timeout(ttrstrt, (caddr_t)tp, (nch & 0x7f)+6); 59825224Smckusick tp->t_state |= TS_TIMEOUT; 59925224Smckusick goto out; 60025224Smckusick } 60125224Smckusick } 60225224Smckusick 60325224Smckusick /* 60425224Smckusick * Should we use DMA or SILO mode? 60525224Smckusick * If nch is greater than DO_DMA_COUNT then DMA. 60625224Smckusick */ 60725224Smckusick if (nch) { 60825224Smckusick dmz_addr->octet[octet].octet_csr = 60925224Smckusick DMZ_IE | IR_LCTMR | (unit & 07); 61025224Smckusick dmz_addr->octet[octet].octet_lctmr = 61125224Smckusick (dmz_addr->octet[octet].octet_lctmr | DMZ_TE); 61225224Smckusick tp->t_state |= TS_BUSY; 61325224Smckusick 61425224Smckusick use_dma = FALSE; 61525224Smckusick room = DMZ_SIZ; 61625224Smckusick 61725224Smckusick if (nch > DO_DMA_COUNT) 61825224Smckusick use_dma = TRUE; 61925224Smckusick 62025224Smckusick if (use_dma && dmz_dma_on) { 62125224Smckusick car = UBACVT(tp->t_outq.c_cf, 62225224Smckusick dmzinfo[controller]->ui_ubanum); 62325224Smckusick dmz_softc[unit].dmz_count = nch; 62425224Smckusick dmz_softc[unit].dmz_state |= ST_DMA; 62525224Smckusick dmz_addr->octet[octet].octet_csr = 62625224Smckusick DMZ_IE | IR_TBA | (unit & 07); 62725224Smckusick dmz_addr->octet[octet].octet_tba = car; 62825224Smckusick dmz_addr->octet[octet].octet_tcc = 62925224Smckusick ((car >> 2) & 0xc000) | nch; 63025224Smckusick } else { 63125224Smckusick dmz_softc[unit].dmz_state &= ~ST_DMA; 63225224Smckusick cp = tp->t_outq.c_cf; 63325224Smckusick nch = MIN(nch, room); 63425224Smckusick dmz_addr->octet[octet].octet_csr = 63525224Smckusick DMZ_IE | IR_TBUF | (unit & 07); 63625224Smckusick for (i = 0; i < nch; i++) 63725224Smckusick dmz_addr->octet[octet].octet_tbf = *cp++ ; 63825224Smckusick ndflush(&tp->t_outq, nch); 63925224Smckusick } 64025224Smckusick } 64125224Smckusick 64225224Smckusick out: 64325224Smckusick splx(priority); 64425224Smckusick return; 64525224Smckusick } 64625224Smckusick 64725224Smckusick /* ARGSUSED */ 64825224Smckusick dmzstop(tp, flag) 64925224Smckusick register struct tty *tp; 65025224Smckusick { 65125224Smckusick register struct dmzdevice *dmz_addr; 65225224Smckusick register int unit, priority, octet; 65325224Smckusick 65425224Smckusick priority = spl5(); 65525224Smckusick dmz_addr = (struct dmzdevice *) tp->t_addr; 65625224Smckusick unit = minor(tp->t_dev); 65725224Smckusick octet = OCTET(unit); 65825224Smckusick 65925224Smckusick dmz_addr->octet[octet].octet_csr = IR_LCTMR | (unit & 07) | DMZ_IE; 66025224Smckusick dmz_addr->octet[octet].octet_lctmr = 66125224Smckusick (dmz_addr->octet[octet].octet_lctmr & ~DMZ_TE); 66225224Smckusick dmz_softc[unit].dmz_state |= ST_TXOFF; 66325224Smckusick if ((tp->t_state & TS_TTSTOP) == 0) { 66425224Smckusick tp->t_state |= (TS_FLUSH | TS_BUSY); 66525224Smckusick dmz_addr->octet[octet].octet_lctmr = 66625224Smckusick (dmz_addr->octet[octet].octet_lctmr | DMZ_FLS); 66725224Smckusick } else if (tp->t_state & TS_BUSY) { 66825224Smckusick dmz_softc[unit].dmz_state |= ST_INBUSY; 66925224Smckusick tp->t_state &= ~TS_BUSY; 67025224Smckusick } 67125224Smckusick 67225224Smckusick splx(priority); 67325224Smckusick return; 67425224Smckusick } 67525224Smckusick 67625224Smckusick /* ARGSUSED */ 67725224Smckusick dmzioctl(device, command, data, flag) 67825224Smckusick dev_t device; 67925224Smckusick caddr_t data; 68025224Smckusick { 68125224Smckusick register struct tty *tp; 68225224Smckusick register int unit; 68325224Smckusick int error; 68425224Smckusick 68525224Smckusick unit = minor(device); 68625224Smckusick tp = &dmz_tty[unit]; 68725224Smckusick 68825224Smckusick error = (*linesw[tp->t_line].l_ioctl)(tp, command, data, flag); 68925224Smckusick if (error >= 0) 69025224Smckusick return (error); 69125224Smckusick error = ttioctl(tp, command, data, flag); 69225224Smckusick if (error >= 0) { 69325655Skarels if (command == TIOCSETP || command == TIOCSETN || 69425655Skarels command == TIOCLSET || command == TIOCLBIS || 69525655Skarels command == TIOCLBIC) 69625224Smckusick dmzparam(unit); 69725224Smckusick return (error); 69825224Smckusick } 69925224Smckusick 70025224Smckusick switch (command) { 70125224Smckusick case TIOCSBRK: 70225655Skarels (void) dmzmctl(unit, DMZ_BRK, DMBIS); 70325224Smckusick break; 70425224Smckusick case TIOCCBRK: 70525655Skarels (void) dmzmctl(unit, DMZ_BRK, DMBIC); 70625224Smckusick break; 70725224Smckusick case TIOCSDTR: 70825655Skarels (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIS); 70925224Smckusick break; 71025224Smckusick case TIOCCDTR: 71125655Skarels (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIC); 71225224Smckusick break; 71325224Smckusick case TIOCMSET: 71425655Skarels (void) dmzmctl(unit, dmtodmz(*(int *)data), DMSET); 71525224Smckusick break; 71625224Smckusick case TIOCMBIS: 71725655Skarels (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIS); 71825224Smckusick break; 71925224Smckusick case TIOCMBIC: 72025655Skarels (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIC); 72125224Smckusick break; 72225224Smckusick case TIOCMGET: 72325655Skarels *(int *)data = dmzmctl(unit, 0, DMGET); 72425224Smckusick break; 72525224Smckusick default: 72625224Smckusick return (ENOTTY); 72725224Smckusick } 72825224Smckusick return (0); 72925224Smckusick } 73025224Smckusick 73125655Skarels dmzmctl(unit, bits, how) 73225655Skarels register int unit; 73325224Smckusick int bits, how; 73425224Smckusick { 73525224Smckusick register struct dmzdevice *dmz_addr; 73625655Skarels register int modem_status, line_control; 73725224Smckusick int priority; 73825224Smckusick int octet; 73925224Smckusick 74025224Smckusick octet = OCTET(unit); 74125655Skarels dmz_addr = (struct dmzdevice *) dmzinfo[DMZ(unit)]->ui_addr; 74225224Smckusick 74325224Smckusick priority = spl5(); 74425655Skarels dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | (unit & 07); 74525655Skarels modem_status = dmz_addr->octet[octet].octet_rmstsc & 0xff00; 74625224Smckusick 74725224Smckusick dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07); 74825655Skarels line_control = dmz_addr->octet[octet].octet_lctmr; 74925224Smckusick 75025224Smckusick 75125224Smckusick switch (how) { 75225224Smckusick case DMSET: 75325655Skarels line_control = bits; 75425224Smckusick break; 75525224Smckusick case DMBIS: 75625655Skarels line_control |= bits; 75725224Smckusick break; 75825224Smckusick case DMBIC: 75925655Skarels line_control &= ~bits; 76025224Smckusick break; 76125224Smckusick case DMGET: 76225224Smckusick (void) splx(priority); 76325655Skarels return (dmztodm(modem_status, line_control)); 76425224Smckusick } 76525224Smckusick 76625224Smckusick dmz_addr->octet[octet].octet_csr = 76725224Smckusick DMZ_IE | IR_LCTMR | (unit & 07); 76825655Skarels dmz_addr->octet[octet].octet_lctmr = line_control; 76925224Smckusick 77025655Skarels splx(priority); 77125224Smckusick return (modem_status); 77225224Smckusick } 77325224Smckusick 77425224Smckusick /* 77525655Skarels * Routine to convert modem status from dm to dmz lctmr format. 77625224Smckusick */ 77725224Smckusick dmtodmz(bits) 77825224Smckusick register int bits; 77925224Smckusick { 78025655Skarels register int lcr = DMZ_LCE; 78125224Smckusick 78225655Skarels if (bits & DML_DTR) 78325655Skarels lcr |= DMZ_DTR; 78425655Skarels if (bits & DML_RTS) 78525655Skarels lcr |= DMZ_RTS; 78625655Skarels if (bits & DML_ST) 78725655Skarels lcr |= DMF_ST; 78825655Skarels if (bits & DML_USR) 78925655Skarels lcr |= DMZ_USRW; 79025655Skarels return (lcr); 79125224Smckusick } 79225224Smckusick 79325224Smckusick /* 79425655Skarels * Routine to convert modem status from dmz receive modem status 79525655Skarels * and line control register to dm format. 79625655Skarels * If dmz user modem read bit set, set DML_USR. 79725224Smckusick */ 79825655Skarels dmztodm(rms, lcr) 79925655Skarels register int rms, lcr; 80025224Smckusick { 80125224Smckusick 80225655Skarels rms = ((rms & (DMZ_DSR|DMZ_RNG|DMZ_CAR|DMZ_CTS|DMF_SR)) >> 7) | 80325655Skarels ((rms & DMZ_USRR) >> 1) | DML_LE; 80425655Skarels if (lcr & DMZ_DTR) 80525655Skarels rms |= DML_DTR; 80625655Skarels if (lcr & DMF_ST) 80725655Skarels rms |= DML_ST; 80825655Skarels if (lcr & DMZ_RTS) 80925655Skarels rms |= DML_RTS; 81025655Skarels return (rms); 81125224Smckusick } 81225224Smckusick #endif 813