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*40728Skarels * @(#)dmz.c 7.8 (Berkeley) 04/03/90 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 "user.h" 2326837Skarels #include "proc.h" 2425224Smckusick #include "ioctl.h" 2525224Smckusick #include "tty.h" 2625224Smckusick #include "map.h" 2725224Smckusick #include "buf.h" 2825224Smckusick #include "vm.h" 2925224Smckusick #include "bkmac.h" 3025224Smckusick #include "clist.h" 3125224Smckusick #include "file.h" 3225224Smckusick #include "uio.h" 3325224Smckusick #include "kernel.h" 3425435Skarels #include "syslog.h" 3525224Smckusick 3630537Skarels #include "dmx.h" 3725224Smckusick #include "ubareg.h" 3825224Smckusick #include "ubavar.h" 3930537Skarels #include "dmxreg.h" 4025224Smckusick #include "dmzreg.h" 4125655Skarels #include "dmreg.h" 4225224Smckusick 4330537Skarels extern int dmx_timeout; /* silo timeout, in ms */ 4430537Skarels int dmzstart(); 4525224Smckusick 4625224Smckusick /* 4730322Skarels * The clist space is mapped by one terminal driver onto each UNIBUS. 4830322Skarels * The identity of the board which allocated resources is recorded, 4930322Skarels * so the process may be repeated after UNIBUS resets. 5030322Skarels * The UBACVT macro converts a clist space address for unibus uban 5130322Skarels * into an i/o space address for the DMA routine. 5230322Skarels */ 5330322Skarels int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ 5430322Skarels int cbase[NUBA]; /* base address of clists in unibus map */ 5525224Smckusick 5630537Skarels /* 5730537Skarels * Autoconfiguration and variables for DMZ32 5830537Skarels */ 5930537Skarels int dmzprobe(), dmzattach(); 6030537Skarels struct uba_device *dmzinfo[NDMZ]; 6130537Skarels u_short dmzstd[] = { 0 }; 6230537Skarels struct uba_driver dmzdriver = { 6330537Skarels dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 6430537Skarels }; 6525224Smckusick 6630537Skarels struct tty dmz_tty[NDMZ*24]; 6730537Skarels struct dmx_softc dmz_softc[3 * NDMZ]; 6830537Skarels #ifndef lint 6930537Skarels int ndmz = NDMZ*24; /* used by iostat */ 7030537Skarels #endif 7130537Skarels 7225224Smckusick dmzprobe(reg) 7325224Smckusick caddr_t reg; 7425224Smckusick { 7525224Smckusick register int br, cvec; 7625224Smckusick register struct dmzdevice *dmz_addr; 7725224Smckusick register unsigned int a; 7825224Smckusick 7925224Smckusick dmz_addr = (struct dmzdevice *)reg; 8025224Smckusick 8125224Smckusick #ifdef lint 8225224Smckusick br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 8325224Smckusick dmzrinta(0); dmzrintb(0); dmzrintc(0); 8425224Smckusick #endif 8525224Smckusick 8625224Smckusick br = 0x15; 8725224Smckusick 8825224Smckusick a = dmz_addr->dmz_config; 8925224Smckusick if (((a>>12) & ~DMZ_INTERFACE) != 0) { 9025224Smckusick printf(" Unknown interface type\n"); 9125224Smckusick return (0); 9225224Smckusick } 9325224Smckusick if (((a>>8) & DMZ_NOC_MASK) != 3) { 9425224Smckusick printf(" Not all octets are available\n"); 9525224Smckusick return (0); 9625224Smckusick } 9725224Smckusick 9825224Smckusick cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 9925224Smckusick dmz_addr->dmz_config = cvec >> 2; 10025224Smckusick 10125224Smckusick return (sizeof(struct dmzdevice)); 10225224Smckusick } 10325224Smckusick 10425224Smckusick dmzattach(ui) 10530537Skarels register struct uba_device *ui; 10625224Smckusick { 10730537Skarels register struct dmx_softc *sc; 10830537Skarels register int i; 10930537Skarels 11030537Skarels sc = &dmz_softc[3 * ui->ui_unit]; 11130537Skarels for (i = 0; i < 3; i++, sc++) { 11230537Skarels sc->dmx_type = 'z'; 11330537Skarels sc->dmx_unit = ui->ui_unit; 11430537Skarels sc->dmx_unit0 = 8 * i; 11530537Skarels sc->dmx_ubanum = ui->ui_ubanum; 11630537Skarels sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff; 11730537Skarels sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8]; 11830537Skarels sc->dmx_octet = (struct dmx_octet *) 11930537Skarels &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i]; 12030537Skarels } 12130537Skarels 12226218Skarels cbase[ui->ui_ubanum] = -1; 12336610Sbostic dmz_uballoc[ui->ui_ubanum] = -1; 12425224Smckusick } 12525224Smckusick 12630537Skarels /* 12730537Skarels * Open a DMF32 line, mapping the clist onto the uba if this 12830537Skarels * is the first dmf on this uba. Turn on this dmf if this is 12930537Skarels * the first use of it. 13030537Skarels */ 13130537Skarels /*ARGSUSED*/ 13230537Skarels dmzopen(dev, flag) 13330537Skarels dev_t dev; 13425224Smckusick { 13525224Smckusick register struct tty *tp; 13630537Skarels struct dmx_softc *sc; 13730537Skarels int unit, dmz; 13830537Skarels struct uba_device *ui; 13930537Skarels int s; 14039061Smarc int dmxparam(); 14125224Smckusick 14230537Skarels unit = minor(dev); 14330537Skarels dmz = DMZ(unit); 14430537Skarels if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0) 14525224Smckusick return (ENXIO); 14625224Smckusick 14725224Smckusick tp = &dmz_tty[unit]; 14830537Skarels sc = &dmz_softc[unit / 8]; 14930537Skarels tp->t_addr = (caddr_t)sc->dmx_octet; 15025224Smckusick tp->t_oproc = dmzstart; 15130537Skarels tp->t_dev = dev; /* needed before dmxopen */ 15239061Smarc tp->t_param = dmxparam; 15325224Smckusick 15425224Smckusick /* 15530537Skarels * While setting up state for this uba, 15630537Skarels * block uba resets which can clear the state. 15725224Smckusick */ 15830537Skarels s = spl6(); 15926218Skarels if (cbase[ui->ui_ubanum] == -1) { 16030537Skarels dmz_uballoc[ui->ui_ubanum] = dmz; 16130322Skarels cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 16230322Skarels (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 16325224Smckusick } 16430537Skarels splx(s); 16525224Smckusick 16639061Smarc return (dmxopen(tp, sc, flag)); 16725224Smckusick } 16825224Smckusick 16930537Skarels /* 17030537Skarels * Close a DMZ32 line. 17130537Skarels */ 17230537Skarels /*ARGSUSED*/ 17330537Skarels dmzclose(dev, flag) 17430537Skarels dev_t dev; 17525224Smckusick int flag; 17625224Smckusick { 17725224Smckusick 178*40728Skarels return (dmxclose(&dmz_tty[minor(dev)])); 17925224Smckusick } 18025224Smckusick 18139061Smarc dmzread(dev, uio, flag) 18230537Skarels dev_t dev; 18330537Skarels struct uio *uio; 18425224Smckusick { 18525224Smckusick register struct tty *tp; 18625224Smckusick 18730537Skarels tp = &dmz_tty[minor(dev)]; 18839061Smarc return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 18925224Smckusick } 19025224Smckusick 19130537Skarels dmzwrite(dev, uio) 19230537Skarels dev_t dev; 19325224Smckusick struct uio *uio; 19425224Smckusick { 19525224Smckusick register struct tty *tp; 19625224Smckusick 19730537Skarels tp = &dmz_tty[minor(dev)]; 19830537Skarels return ((*linesw[tp->t_line].l_write)(tp, uio)); 19925224Smckusick } 20025224Smckusick 20130537Skarels /* 20230537Skarels * DMZ32 receiver interrupts. 20330537Skarels */ 20430537Skarels dmzrinta(dmz) 20530537Skarels int dmz; 20625224Smckusick { 20730537Skarels struct uba_device *ui; 20825224Smckusick 20930537Skarels ui = dmzinfo[dmz]; 21030537Skarels if (ui == 0 || ui->ui_alive == 0) 21130537Skarels return; 21230537Skarels dmxrint(&dmz_softc[3 * dmz + 0]); 21325224Smckusick } 21425224Smckusick 21530537Skarels dmzrintb(dmz) 21630537Skarels int dmz; 21725224Smckusick { 21830537Skarels struct uba_device *ui; 21925224Smckusick 22030537Skarels ui = dmzinfo[dmz]; 22130537Skarels if (ui == 0 || ui->ui_alive == 0) 22230537Skarels return; 22330537Skarels dmxrint(&dmz_softc[3 * dmz + 1]); 22425224Smckusick } 22525224Smckusick 22630537Skarels dmzrintc(dmz) 22730537Skarels int dmz; 22825224Smckusick { 22930537Skarels struct uba_device *ui; 23025224Smckusick 23130537Skarels ui = dmzinfo[dmz]; 23225224Smckusick if (ui == 0 || ui->ui_alive == 0) 23325224Smckusick return; 23430537Skarels dmxrint(&dmz_softc[3 * dmz + 2]); 23525224Smckusick } 23625224Smckusick 23730537Skarels /* 23830537Skarels * Ioctl for DMZ32. 23930537Skarels */ 24030537Skarels dmzioctl(dev, cmd, data, flag) 24130537Skarels dev_t dev; 24230537Skarels caddr_t data; 24325224Smckusick { 24430537Skarels int unit = minor(dev); 24530537Skarels 24630537Skarels return (dmxioctl(&dmz_tty[unit], cmd, data, flag)); 24725224Smckusick } 24825224Smckusick 24930537Skarels /* 25030537Skarels * DMZ32 transmitter interrupts. 25130537Skarels */ 25230537Skarels dmzxinta(dmz) 25330537Skarels int dmz; 25425224Smckusick { 25530537Skarels 25630537Skarels dmxxint(&dmz_softc[3 * dmz + 0]); 25725224Smckusick } 25825224Smckusick 25930537Skarels dmzxintb(dmz) 26030537Skarels int dmz; 26125224Smckusick { 26230537Skarels 26330537Skarels dmxxint(&dmz_softc[3 * dmz + 1]); 26425224Smckusick } 26525224Smckusick 26630537Skarels dmzxintc(dmz) 26730537Skarels int dmz; 26825224Smckusick { 26925224Smckusick 27030537Skarels dmxxint(&dmz_softc[3 * dmz + 2]); 27125224Smckusick } 27225224Smckusick 27330537Skarels /* 27430537Skarels * Start (restart) transmission on the given line. 27530537Skarels */ 27625224Smckusick dmzstart(tp) 27730537Skarels struct tty *tp; 27825224Smckusick { 27925224Smckusick 28030537Skarels dmxstart(tp, &dmz_softc[minor(tp->t_dev) >> 3]); 28125224Smckusick } 28225224Smckusick 28330537Skarels /* 28430537Skarels * Stop output on a line, e.g. for ^S/^Q or output flush. 28530537Skarels */ 28625224Smckusick dmzstop(tp, flag) 28730537Skarels struct tty *tp; 28825224Smckusick { 28925224Smckusick 29030537Skarels dmxstop(tp, &dmz_softc[minor(tp->t_dev) >> 3], flag); 29125224Smckusick } 29225224Smckusick 29330537Skarels /* 29430537Skarels * Reset state of driver if UBA reset was necessary. 29530537Skarels * Reset the csr, lpr, and lcr registers on open lines, and 29630537Skarels * restart transmitters. 29730537Skarels */ 29830537Skarels dmzreset(uban) 29930537Skarels int uban; 30025224Smckusick { 30130537Skarels register int dmz; 30225224Smckusick register struct tty *tp; 30330537Skarels register struct uba_device *ui; 30430537Skarels register struct dmzdevice *addr; 30530537Skarels int i; 30625224Smckusick 30730537Skarels for (dmz = 0; dmz < NDMZ; dmz++) { 30830537Skarels ui = dmzinfo[dmz]; 30930537Skarels if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 31030537Skarels continue; 31130537Skarels printf("dmz%d ", dmz); 31230537Skarels addr = (struct dmzdevice *)ui->ui_addr; 31325224Smckusick 31430537Skarels if (dmz_uballoc[uban] == dmz) { 31530537Skarels int info; 31625224Smckusick 31730537Skarels info = uballoc(uban, (caddr_t)cfree, 31830537Skarels nclist * sizeof(struct cblock), UBA_CANTWAIT); 31930537Skarels if (info) 32030537Skarels cbase[uban] = UBAI_ADDR(info); 32130537Skarels else { 32230537Skarels printf(" [can't get uba map]"); 32330537Skarels cbase[uban] = -1; 32430537Skarels } 32530537Skarels } 32625224Smckusick 32730537Skarels for (i = 0; i < 3; i++) 32830537Skarels if (dmz_softc[3 * dmz + i].dmx_flags & DMX_ACTIVE) { 32930537Skarels addr->dmz_octet[i].csr = DMF_IE; 33030537Skarels addr->dmz_octet[i].rsp = dmx_timeout; 33130537Skarels } 33225224Smckusick 33330537Skarels /* 33430537Skarels * If a unit is open or waiting for open to complete, 33530537Skarels * reset it. 33630537Skarels */ 33730537Skarels tp = &dmz_tty[dmz * 24]; 33830537Skarels for (i = 0; i < 24; i++, tp++) { 33930537Skarels if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 34039061Smarc dmxparam(tp, &tp->t_termios); 34130537Skarels (void) dmxmctl(tp, DMF_ON, DMSET); 34230537Skarels tp->t_state &= ~TS_BUSY; 34330537Skarels dmzstart(tp); 34430537Skarels } 34530537Skarels } 34625224Smckusick } 34725224Smckusick } 34825224Smckusick #endif 349