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*39061Smarc * @(#)dmz.c 7.6 (Berkeley) 09/06/89 725224Smckusick */ 825224Smckusick 925224Smckusick /* 1025224Smckusick * DMZ-32 driver 1125224Smckusick */ 1225224Smckusick 1325224Smckusick #include "dmz.h" 1425224Smckusick #if NDMZ > 0 1525224Smckusick 1637511Smckusick #include "machine/pte.h" 1725224Smckusick 1825224Smckusick #include "bk.h" 1925224Smckusick #include "uba.h" 2025224Smckusick #include "param.h" 2125224Smckusick #include "conf.h" 2225224Smckusick #include "dir.h" 2325224Smckusick #include "user.h" 2426837Skarels #include "proc.h" 2525224Smckusick #include "ioctl.h" 2625224Smckusick #include "tty.h" 2725224Smckusick #include "map.h" 2825224Smckusick #include "buf.h" 2925224Smckusick #include "vm.h" 3025224Smckusick #include "bkmac.h" 3125224Smckusick #include "clist.h" 3225224Smckusick #include "file.h" 3325224Smckusick #include "uio.h" 3425224Smckusick #include "kernel.h" 3525435Skarels #include "syslog.h" 3625224Smckusick 3730537Skarels #include "dmx.h" 3825224Smckusick #include "ubareg.h" 3925224Smckusick #include "ubavar.h" 4030537Skarels #include "dmxreg.h" 4125224Smckusick #include "dmzreg.h" 4225655Skarels #include "dmreg.h" 4325224Smckusick 4430537Skarels extern int dmx_timeout; /* silo timeout, in ms */ 4530537Skarels int dmzstart(); 4625224Smckusick 4725224Smckusick /* 4830322Skarels * The clist space is mapped by one terminal driver onto each UNIBUS. 4930322Skarels * The identity of the board which allocated resources is recorded, 5030322Skarels * so the process may be repeated after UNIBUS resets. 5130322Skarels * The UBACVT macro converts a clist space address for unibus uban 5230322Skarels * into an i/o space address for the DMA routine. 5330322Skarels */ 5430322Skarels int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ 5530322Skarels int cbase[NUBA]; /* base address of clists in unibus map */ 5625224Smckusick 5730537Skarels /* 5830537Skarels * Autoconfiguration and variables for DMZ32 5930537Skarels */ 6030537Skarels int dmzprobe(), dmzattach(); 6130537Skarels struct uba_device *dmzinfo[NDMZ]; 6230537Skarels u_short dmzstd[] = { 0 }; 6330537Skarels struct uba_driver dmzdriver = { 6430537Skarels dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 6530537Skarels }; 6625224Smckusick 6730537Skarels struct tty dmz_tty[NDMZ*24]; 6830537Skarels struct dmx_softc dmz_softc[3 * NDMZ]; 6930537Skarels #ifndef lint 7030537Skarels int ndmz = NDMZ*24; /* used by iostat */ 7130537Skarels #endif 7230537Skarels 7325224Smckusick dmzprobe(reg) 7425224Smckusick caddr_t reg; 7525224Smckusick { 7625224Smckusick register int br, cvec; 7725224Smckusick register struct dmzdevice *dmz_addr; 7825224Smckusick register unsigned int a; 7925224Smckusick 8025224Smckusick dmz_addr = (struct dmzdevice *)reg; 8125224Smckusick 8225224Smckusick #ifdef lint 8325224Smckusick br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 8425224Smckusick dmzrinta(0); dmzrintb(0); dmzrintc(0); 8525224Smckusick #endif 8625224Smckusick 8725224Smckusick br = 0x15; 8825224Smckusick 8925224Smckusick a = dmz_addr->dmz_config; 9025224Smckusick if (((a>>12) & ~DMZ_INTERFACE) != 0) { 9125224Smckusick printf(" Unknown interface type\n"); 9225224Smckusick return (0); 9325224Smckusick } 9425224Smckusick if (((a>>8) & DMZ_NOC_MASK) != 3) { 9525224Smckusick printf(" Not all octets are available\n"); 9625224Smckusick return (0); 9725224Smckusick } 9825224Smckusick 9925224Smckusick cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 10025224Smckusick dmz_addr->dmz_config = cvec >> 2; 10125224Smckusick 10225224Smckusick return (sizeof(struct dmzdevice)); 10325224Smckusick } 10425224Smckusick 10525224Smckusick dmzattach(ui) 10630537Skarels register struct uba_device *ui; 10725224Smckusick { 10830537Skarels register struct dmx_softc *sc; 10930537Skarels register int i; 11030537Skarels 11130537Skarels sc = &dmz_softc[3 * ui->ui_unit]; 11230537Skarels for (i = 0; i < 3; i++, sc++) { 11330537Skarels sc->dmx_type = 'z'; 11430537Skarels sc->dmx_unit = ui->ui_unit; 11530537Skarels sc->dmx_unit0 = 8 * i; 11630537Skarels sc->dmx_ubanum = ui->ui_ubanum; 11730537Skarels sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff; 11830537Skarels sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8]; 11930537Skarels sc->dmx_octet = (struct dmx_octet *) 12030537Skarels &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i]; 12130537Skarels } 12230537Skarels 12326218Skarels cbase[ui->ui_ubanum] = -1; 12436610Sbostic dmz_uballoc[ui->ui_ubanum] = -1; 12525224Smckusick } 12625224Smckusick 12730537Skarels /* 12830537Skarels * Open a DMF32 line, mapping the clist onto the uba if this 12930537Skarels * is the first dmf on this uba. Turn on this dmf if this is 13030537Skarels * the first use of it. 13130537Skarels */ 13230537Skarels /*ARGSUSED*/ 13330537Skarels dmzopen(dev, flag) 13430537Skarels dev_t dev; 13525224Smckusick { 13625224Smckusick register struct tty *tp; 13730537Skarels struct dmx_softc *sc; 13830537Skarels int unit, dmz; 13930537Skarels struct uba_device *ui; 14030537Skarels int s; 141*39061Smarc int dmxparam(); 14225224Smckusick 14330537Skarels unit = minor(dev); 14430537Skarels dmz = DMZ(unit); 14530537Skarels if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0) 14625224Smckusick return (ENXIO); 14725224Smckusick 14825224Smckusick tp = &dmz_tty[unit]; 14930537Skarels sc = &dmz_softc[unit / 8]; 15030537Skarels tp->t_addr = (caddr_t)sc->dmx_octet; 15125224Smckusick tp->t_oproc = dmzstart; 15230537Skarels tp->t_dev = dev; /* needed before dmxopen */ 153*39061Smarc tp->t_param = dmxparam; 15425224Smckusick 15525224Smckusick /* 15630537Skarels * While setting up state for this uba, 15730537Skarels * block uba resets which can clear the state. 15825224Smckusick */ 15930537Skarels s = spl6(); 16026218Skarels if (cbase[ui->ui_ubanum] == -1) { 16130537Skarels dmz_uballoc[ui->ui_ubanum] = dmz; 16230322Skarels cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 16330322Skarels (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 16425224Smckusick } 16530537Skarels splx(s); 16625224Smckusick 167*39061Smarc return (dmxopen(tp, sc, flag)); 16825224Smckusick } 16925224Smckusick 17030537Skarels /* 17130537Skarels * Close a DMZ32 line. 17230537Skarels */ 17330537Skarels /*ARGSUSED*/ 17430537Skarels dmzclose(dev, flag) 17530537Skarels dev_t dev; 17625224Smckusick int flag; 17725224Smckusick { 17825224Smckusick 17930537Skarels dmxclose(&dmz_tty[minor(dev)]); 18025224Smckusick } 18125224Smckusick 182*39061Smarc dmzread(dev, uio, flag) 18330537Skarels dev_t dev; 18430537Skarels struct uio *uio; 18525224Smckusick { 18625224Smckusick register struct tty *tp; 18725224Smckusick 18830537Skarels tp = &dmz_tty[minor(dev)]; 189*39061Smarc return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 19025224Smckusick } 19125224Smckusick 19230537Skarels dmzwrite(dev, uio) 19330537Skarels dev_t dev; 19425224Smckusick struct uio *uio; 19525224Smckusick { 19625224Smckusick register struct tty *tp; 19725224Smckusick 19830537Skarels tp = &dmz_tty[minor(dev)]; 19930537Skarels return ((*linesw[tp->t_line].l_write)(tp, uio)); 20025224Smckusick } 20125224Smckusick 20230537Skarels /* 20330537Skarels * DMZ32 receiver interrupts. 20430537Skarels */ 20530537Skarels dmzrinta(dmz) 20630537Skarels int dmz; 20725224Smckusick { 20830537Skarels struct uba_device *ui; 20925224Smckusick 21030537Skarels ui = dmzinfo[dmz]; 21130537Skarels if (ui == 0 || ui->ui_alive == 0) 21230537Skarels return; 21330537Skarels dmxrint(&dmz_softc[3 * dmz + 0]); 21425224Smckusick } 21525224Smckusick 21630537Skarels dmzrintb(dmz) 21730537Skarels int dmz; 21825224Smckusick { 21930537Skarels struct uba_device *ui; 22025224Smckusick 22130537Skarels ui = dmzinfo[dmz]; 22230537Skarels if (ui == 0 || ui->ui_alive == 0) 22330537Skarels return; 22430537Skarels dmxrint(&dmz_softc[3 * dmz + 1]); 22525224Smckusick } 22625224Smckusick 22730537Skarels dmzrintc(dmz) 22830537Skarels int dmz; 22925224Smckusick { 23030537Skarels struct uba_device *ui; 23125224Smckusick 23230537Skarels ui = dmzinfo[dmz]; 23325224Smckusick if (ui == 0 || ui->ui_alive == 0) 23425224Smckusick return; 23530537Skarels dmxrint(&dmz_softc[3 * dmz + 2]); 23625224Smckusick } 23725224Smckusick 23830537Skarels /* 23930537Skarels * Ioctl for DMZ32. 24030537Skarels */ 24130537Skarels dmzioctl(dev, cmd, data, flag) 24230537Skarels dev_t dev; 24330537Skarels caddr_t data; 24425224Smckusick { 24530537Skarels int unit = minor(dev); 24630537Skarels 24730537Skarels return (dmxioctl(&dmz_tty[unit], cmd, data, flag)); 24825224Smckusick } 24925224Smckusick 25030537Skarels /* 25130537Skarels * DMZ32 transmitter interrupts. 25230537Skarels */ 25330537Skarels dmzxinta(dmz) 25430537Skarels int dmz; 25525224Smckusick { 25630537Skarels 25730537Skarels dmxxint(&dmz_softc[3 * dmz + 0]); 25825224Smckusick } 25925224Smckusick 26030537Skarels dmzxintb(dmz) 26130537Skarels int dmz; 26225224Smckusick { 26330537Skarels 26430537Skarels dmxxint(&dmz_softc[3 * dmz + 1]); 26525224Smckusick } 26625224Smckusick 26730537Skarels dmzxintc(dmz) 26830537Skarels int dmz; 26925224Smckusick { 27025224Smckusick 27130537Skarels dmxxint(&dmz_softc[3 * dmz + 2]); 27225224Smckusick } 27325224Smckusick 27430537Skarels /* 27530537Skarels * Start (restart) transmission on the given line. 27630537Skarels */ 27725224Smckusick dmzstart(tp) 27830537Skarels struct tty *tp; 27925224Smckusick { 28025224Smckusick 28130537Skarels dmxstart(tp, &dmz_softc[minor(tp->t_dev) >> 3]); 28225224Smckusick } 28325224Smckusick 28430537Skarels /* 28530537Skarels * Stop output on a line, e.g. for ^S/^Q or output flush. 28630537Skarels */ 28725224Smckusick dmzstop(tp, flag) 28830537Skarels struct tty *tp; 28925224Smckusick { 29025224Smckusick 29130537Skarels dmxstop(tp, &dmz_softc[minor(tp->t_dev) >> 3], flag); 29225224Smckusick } 29325224Smckusick 29430537Skarels /* 29530537Skarels * Reset state of driver if UBA reset was necessary. 29630537Skarels * Reset the csr, lpr, and lcr registers on open lines, and 29730537Skarels * restart transmitters. 29830537Skarels */ 29930537Skarels dmzreset(uban) 30030537Skarels int uban; 30125224Smckusick { 30230537Skarels register int dmz; 30325224Smckusick register struct tty *tp; 30430537Skarels register struct uba_device *ui; 30530537Skarels register struct dmzdevice *addr; 30630537Skarels int i; 30725224Smckusick 30830537Skarels for (dmz = 0; dmz < NDMZ; dmz++) { 30930537Skarels ui = dmzinfo[dmz]; 31030537Skarels if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 31130537Skarels continue; 31230537Skarels printf("dmz%d ", dmz); 31330537Skarels addr = (struct dmzdevice *)ui->ui_addr; 31425224Smckusick 31530537Skarels if (dmz_uballoc[uban] == dmz) { 31630537Skarels int info; 31725224Smckusick 31830537Skarels info = uballoc(uban, (caddr_t)cfree, 31930537Skarels nclist * sizeof(struct cblock), UBA_CANTWAIT); 32030537Skarels if (info) 32130537Skarels cbase[uban] = UBAI_ADDR(info); 32230537Skarels else { 32330537Skarels printf(" [can't get uba map]"); 32430537Skarels cbase[uban] = -1; 32530537Skarels } 32630537Skarels } 32725224Smckusick 32830537Skarels for (i = 0; i < 3; i++) 32930537Skarels if (dmz_softc[3 * dmz + i].dmx_flags & DMX_ACTIVE) { 33030537Skarels addr->dmz_octet[i].csr = DMF_IE; 33130537Skarels addr->dmz_octet[i].rsp = dmx_timeout; 33230537Skarels } 33325224Smckusick 33430537Skarels /* 33530537Skarels * If a unit is open or waiting for open to complete, 33630537Skarels * reset it. 33730537Skarels */ 33830537Skarels tp = &dmz_tty[dmz * 24]; 33930537Skarels for (i = 0; i < 24; i++, tp++) { 34030537Skarels if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 341*39061Smarc dmxparam(tp, &tp->t_termios); 34230537Skarels (void) dmxmctl(tp, DMF_ON, DMSET); 34330537Skarels tp->t_state &= ~TS_BUSY; 34430537Skarels dmzstart(tp); 34530537Skarels } 34630537Skarels } 34725224Smckusick } 34825224Smckusick } 34925224Smckusick #endif 350