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*37511Smckusick * @(#)dmz.c 7.5 (Berkeley) 04/25/89 725224Smckusick */ 825224Smckusick 925224Smckusick /* 1025224Smckusick * DMZ-32 driver 1125224Smckusick */ 1225224Smckusick 1325224Smckusick #include "dmz.h" 1425224Smckusick #if NDMZ > 0 1525224Smckusick 16*37511Smckusick #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 extern char dmx_speeds[]; 4630537Skarels int dmzstart(); 4725224Smckusick 4825224Smckusick /* 4930322Skarels * The clist space is mapped by one terminal driver onto each UNIBUS. 5030322Skarels * The identity of the board which allocated resources is recorded, 5130322Skarels * so the process may be repeated after UNIBUS resets. 5230322Skarels * The UBACVT macro converts a clist space address for unibus uban 5330322Skarels * into an i/o space address for the DMA routine. 5430322Skarels */ 5530322Skarels int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ 5630322Skarels int cbase[NUBA]; /* base address of clists in unibus map */ 5725224Smckusick 5830537Skarels /* 5930537Skarels * Autoconfiguration and variables for DMZ32 6030537Skarels */ 6130537Skarels int dmzprobe(), dmzattach(); 6230537Skarels struct uba_device *dmzinfo[NDMZ]; 6330537Skarels u_short dmzstd[] = { 0 }; 6430537Skarels struct uba_driver dmzdriver = { 6530537Skarels dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 6630537Skarels }; 6725224Smckusick 6830537Skarels struct tty dmz_tty[NDMZ*24]; 6930537Skarels struct dmx_softc dmz_softc[3 * NDMZ]; 7030537Skarels #ifndef lint 7130537Skarels int ndmz = NDMZ*24; /* used by iostat */ 7230537Skarels #endif 7330537Skarels 7425224Smckusick dmzprobe(reg) 7525224Smckusick caddr_t reg; 7625224Smckusick { 7725224Smckusick register int br, cvec; 7825224Smckusick register struct dmzdevice *dmz_addr; 7925224Smckusick register unsigned int a; 8025224Smckusick 8125224Smckusick dmz_addr = (struct dmzdevice *)reg; 8225224Smckusick 8325224Smckusick #ifdef lint 8425224Smckusick br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 8525224Smckusick dmzrinta(0); dmzrintb(0); dmzrintc(0); 8625224Smckusick #endif 8725224Smckusick 8825224Smckusick br = 0x15; 8925224Smckusick 9025224Smckusick a = dmz_addr->dmz_config; 9125224Smckusick if (((a>>12) & ~DMZ_INTERFACE) != 0) { 9225224Smckusick printf(" Unknown interface type\n"); 9325224Smckusick return (0); 9425224Smckusick } 9525224Smckusick if (((a>>8) & DMZ_NOC_MASK) != 3) { 9625224Smckusick printf(" Not all octets are available\n"); 9725224Smckusick return (0); 9825224Smckusick } 9925224Smckusick 10025224Smckusick cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 10125224Smckusick dmz_addr->dmz_config = cvec >> 2; 10225224Smckusick 10325224Smckusick return (sizeof(struct dmzdevice)); 10425224Smckusick } 10525224Smckusick 10625224Smckusick dmzattach(ui) 10730537Skarels register struct uba_device *ui; 10825224Smckusick { 10930537Skarels register struct dmx_softc *sc; 11030537Skarels register int i; 11130537Skarels 11230537Skarels sc = &dmz_softc[3 * ui->ui_unit]; 11330537Skarels for (i = 0; i < 3; i++, sc++) { 11430537Skarels sc->dmx_type = 'z'; 11530537Skarels sc->dmx_unit = ui->ui_unit; 11630537Skarels sc->dmx_unit0 = 8 * i; 11730537Skarels sc->dmx_ubanum = ui->ui_ubanum; 11830537Skarels sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff; 11930537Skarels sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8]; 12030537Skarels sc->dmx_octet = (struct dmx_octet *) 12130537Skarels &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i]; 12230537Skarels } 12330537Skarels 12426218Skarels cbase[ui->ui_ubanum] = -1; 12536610Sbostic dmz_uballoc[ui->ui_ubanum] = -1; 12625224Smckusick } 12725224Smckusick 12830537Skarels /* 12930537Skarels * Open a DMF32 line, mapping the clist onto the uba if this 13030537Skarels * is the first dmf on this uba. Turn on this dmf if this is 13130537Skarels * the first use of it. 13230537Skarels */ 13330537Skarels /*ARGSUSED*/ 13430537Skarels dmzopen(dev, flag) 13530537Skarels dev_t dev; 13625224Smckusick { 13725224Smckusick register struct tty *tp; 13830537Skarels struct dmx_softc *sc; 13930537Skarels int unit, dmz; 14030537Skarels struct uba_device *ui; 14130537Skarels int s; 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 */ 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 16630537Skarels return (dmxopen(tp, sc)); 16725224Smckusick } 16825224Smckusick 16930537Skarels /* 17030537Skarels * Close a DMZ32 line. 17130537Skarels */ 17230537Skarels /*ARGSUSED*/ 17330537Skarels dmzclose(dev, flag) 17430537Skarels dev_t dev; 17525224Smckusick int flag; 17625224Smckusick { 17725224Smckusick 17830537Skarels dmxclose(&dmz_tty[minor(dev)]); 17925224Smckusick } 18025224Smckusick 18130537Skarels dmzread(dev, uio) 18230537Skarels dev_t dev; 18330537Skarels struct uio *uio; 18425224Smckusick { 18525224Smckusick register struct tty *tp; 18625224Smckusick 18730537Skarels tp = &dmz_tty[minor(dev)]; 18830537Skarels return ((*linesw[tp->t_line].l_read)(tp, uio)); 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)) { 34030537Skarels dmxparam(tp); 34130537Skarels (void) dmxmctl(tp, DMF_ON, DMSET); 34230537Skarels tp->t_state &= ~TS_BUSY; 34330537Skarels dmzstart(tp); 34430537Skarels } 34530537Skarels } 34625224Smckusick } 34725224Smckusick } 34825224Smckusick #endif 349