/* * Copyright (c) 1985, 1986 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)dmz.c 7.9 (Berkeley) 04/12/90 */ /* * DMZ-32 driver */ #include "dmz.h" #if NDMZ > 0 #include "machine/pte.h" #include "uba.h" #include "param.h" #include "conf.h" #include "user.h" #include "proc.h" #include "ioctl.h" #include "tty.h" #include "map.h" #include "buf.h" #include "vm.h" #include "bkmac.h" #include "clist.h" #include "file.h" #include "uio.h" #include "kernel.h" #include "syslog.h" #include "dmx.h" #include "ubareg.h" #include "ubavar.h" #include "dmxreg.h" #include "dmzreg.h" #include "dmreg.h" extern int dmx_timeout; /* silo timeout, in ms */ int dmzstart(); /* * The clist space is mapped by one terminal driver onto each UNIBUS. * The identity of the board which allocated resources is recorded, * so the process may be repeated after UNIBUS resets. * The UBACVT macro converts a clist space address for unibus uban * into an i/o space address for the DMA routine. */ int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ int cbase[NUBA]; /* base address of clists in unibus map */ /* * Autoconfiguration and variables for DMZ32 */ int dmzprobe(), dmzattach(); struct uba_device *dmzinfo[NDMZ]; u_short dmzstd[] = { 0 }; struct uba_driver dmzdriver = { dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo }; struct tty dmz_tty[NDMZ*24]; struct dmx_softc dmz_softc[3 * NDMZ]; #ifndef lint int ndmz = NDMZ*24; /* used by iostat */ #endif dmzprobe(reg) caddr_t reg; { register int br, cvec; register struct dmzdevice *dmz_addr; register unsigned int a; dmz_addr = (struct dmzdevice *)reg; #ifdef lint br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); dmzrinta(0); dmzrintb(0); dmzrintc(0); #endif br = 0x15; a = dmz_addr->dmz_config; if (((a>>12) & ~DMZ_INTERFACE) != 0) { printf(" Unknown interface type\n"); return (0); } if (((a>>8) & DMZ_NOC_MASK) != 3) { printf(" Not all octets are available\n"); return (0); } cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); dmz_addr->dmz_config = cvec >> 2; return (sizeof(struct dmzdevice)); } dmzattach(ui) register struct uba_device *ui; { register struct dmx_softc *sc; register int i; sc = &dmz_softc[3 * ui->ui_unit]; for (i = 0; i < 3; i++, sc++) { sc->dmx_type = 'z'; sc->dmx_unit = ui->ui_unit; sc->dmx_unit0 = 8 * i; sc->dmx_ubanum = ui->ui_ubanum; sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff; sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8]; sc->dmx_octet = (struct dmx_octet *) &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i]; } cbase[ui->ui_ubanum] = -1; dmz_uballoc[ui->ui_ubanum] = -1; } /* * Open a DMF32 line, mapping the clist onto the uba if this * is the first dmf on this uba. Turn on this dmf if this is * the first use of it. */ /*ARGSUSED*/ dmzopen(dev, flag) dev_t dev; { register struct tty *tp; struct dmx_softc *sc; int unit, dmz; struct uba_device *ui; int s; int dmxparam(); unit = minor(dev); dmz = DMZ(unit); if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0) return (ENXIO); tp = &dmz_tty[unit]; sc = &dmz_softc[unit / 8]; tp->t_addr = (caddr_t)sc->dmx_octet; tp->t_oproc = dmzstart; tp->t_dev = dev; /* needed before dmxopen */ tp->t_param = dmxparam; /* * While setting up state for this uba, * block uba resets which can clear the state. */ s = spl6(); if (cbase[ui->ui_ubanum] == -1) { dmz_uballoc[ui->ui_ubanum] = dmz; cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); } splx(s); return (dmxopen(tp, sc, flag)); } /* * Close a DMZ32 line. */ /*ARGSUSED*/ dmzclose(dev, flag) dev_t dev; int flag; { return (dmxclose(&dmz_tty[minor(dev)])); } dmzread(dev, uio, flag) dev_t dev; struct uio *uio; { register struct tty *tp; tp = &dmz_tty[minor(dev)]; return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); } dmzwrite(dev, uio) dev_t dev; struct uio *uio; { register struct tty *tp; tp = &dmz_tty[minor(dev)]; return ((*linesw[tp->t_line].l_write)(tp, uio)); } /* * DMZ32 receiver interrupts. */ dmzrinta(dmz) int dmz; { struct uba_device *ui; ui = dmzinfo[dmz]; if (ui == 0 || ui->ui_alive == 0) return; dmxrint(&dmz_softc[3 * dmz + 0]); } dmzrintb(dmz) int dmz; { struct uba_device *ui; ui = dmzinfo[dmz]; if (ui == 0 || ui->ui_alive == 0) return; dmxrint(&dmz_softc[3 * dmz + 1]); } dmzrintc(dmz) int dmz; { struct uba_device *ui; ui = dmzinfo[dmz]; if (ui == 0 || ui->ui_alive == 0) return; dmxrint(&dmz_softc[3 * dmz + 2]); } /* * Ioctl for DMZ32. */ dmzioctl(dev, cmd, data, flag) dev_t dev; caddr_t data; { int unit = minor(dev); return (dmxioctl(&dmz_tty[unit], cmd, data, flag)); } /* * DMZ32 transmitter interrupts. */ dmzxinta(dmz) int dmz; { dmxxint(&dmz_softc[3 * dmz + 0]); } dmzxintb(dmz) int dmz; { dmxxint(&dmz_softc[3 * dmz + 1]); } dmzxintc(dmz) int dmz; { dmxxint(&dmz_softc[3 * dmz + 2]); } /* * Start (restart) transmission on the given line. */ dmzstart(tp) struct tty *tp; { dmxstart(tp, &dmz_softc[minor(tp->t_dev) >> 3]); } /* * Stop output on a line, e.g. for ^S/^Q or output flush. */ dmzstop(tp, flag) struct tty *tp; { dmxstop(tp, &dmz_softc[minor(tp->t_dev) >> 3], flag); } /* * Reset state of driver if UBA reset was necessary. * Reset the csr, lpr, and lcr registers on open lines, and * restart transmitters. */ dmzreset(uban) int uban; { register int dmz; register struct tty *tp; register struct uba_device *ui; register struct dmzdevice *addr; int i; for (dmz = 0; dmz < NDMZ; dmz++) { ui = dmzinfo[dmz]; if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) continue; printf("dmz%d ", dmz); addr = (struct dmzdevice *)ui->ui_addr; if (dmz_uballoc[uban] == dmz) { int info; info = uballoc(uban, (caddr_t)cfree, nclist * sizeof(struct cblock), UBA_CANTWAIT); if (info) cbase[uban] = UBAI_ADDR(info); else { printf(" [can't get uba map]"); cbase[uban] = -1; } } for (i = 0; i < 3; i++) if (dmz_softc[3 * dmz + i].dmx_flags & DMX_ACTIVE) { addr->dmz_octet[i].csr = DMF_IE; addr->dmz_octet[i].rsp = dmx_timeout; } /* * If a unit is open or waiting for open to complete, * reset it. */ tp = &dmz_tty[dmz * 24]; for (i = 0; i < 24; i++, tp++) { if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { dmxparam(tp, &tp->t_termios); (void) dmxmctl(tp, DMF_ON, DMSET); tp->t_state &= ~TS_BUSY; dmzstart(tp); } } } } #endif