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*45804Sbostic * @(#)dmz.c 7.10 (Berkeley) 12/16/90 725224Smckusick */ 825224Smckusick 925224Smckusick /* 1025224Smckusick * DMZ-32 driver 1125224Smckusick */ 1225224Smckusick 1325224Smckusick #include "dmz.h" 1425224Smckusick #if NDMZ > 0 1525224Smckusick 16*45804Sbostic #include "../include/pte.h" 1725224Smckusick 18*45804Sbostic #include "sys/param.h" 1925224Smckusick #include "uba.h" 20*45804Sbostic #include "sys/conf.h" 21*45804Sbostic #include "sys/user.h" 22*45804Sbostic #include "sys/proc.h" 23*45804Sbostic #include "sys/ioctl.h" 24*45804Sbostic #include "sys/tty.h" 25*45804Sbostic #include "sys/map.h" 26*45804Sbostic #include "sys/buf.h" 27*45804Sbostic #include "sys/vm.h" 28*45804Sbostic #include "sys/bkmac.h" 29*45804Sbostic #include "sys/clist.h" 30*45804Sbostic #include "sys/file.h" 31*45804Sbostic #include "sys/uio.h" 32*45804Sbostic #include "sys/kernel.h" 33*45804Sbostic #include "sys/syslog.h" 3425224Smckusick 3530537Skarels #include "dmx.h" 3625224Smckusick #include "ubareg.h" 3725224Smckusick #include "ubavar.h" 3830537Skarels #include "dmxreg.h" 3925224Smckusick #include "dmzreg.h" 4025655Skarels #include "dmreg.h" 4125224Smckusick 4230537Skarels extern int dmx_timeout; /* silo timeout, in ms */ 4330537Skarels int dmzstart(); 4425224Smckusick 4525224Smckusick /* 4630322Skarels * The clist space is mapped by one terminal driver onto each UNIBUS. 4730322Skarels * The identity of the board which allocated resources is recorded, 4830322Skarels * so the process may be repeated after UNIBUS resets. 4930322Skarels * The UBACVT macro converts a clist space address for unibus uban 5030322Skarels * into an i/o space address for the DMA routine. 5130322Skarels */ 5230322Skarels int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ 5330322Skarels int cbase[NUBA]; /* base address of clists in unibus map */ 5425224Smckusick 5530537Skarels /* 5630537Skarels * Autoconfiguration and variables for DMZ32 5730537Skarels */ 5830537Skarels int dmzprobe(), dmzattach(); 5930537Skarels struct uba_device *dmzinfo[NDMZ]; 6030537Skarels u_short dmzstd[] = { 0 }; 6130537Skarels struct uba_driver dmzdriver = { 6230537Skarels dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 6330537Skarels }; 6425224Smckusick 6530537Skarels struct tty dmz_tty[NDMZ*24]; 6630537Skarels struct dmx_softc dmz_softc[3 * NDMZ]; 6730537Skarels #ifndef lint 6830537Skarels int ndmz = NDMZ*24; /* used by iostat */ 6930537Skarels #endif 7030537Skarels 7125224Smckusick dmzprobe(reg) 7225224Smckusick caddr_t reg; 7325224Smckusick { 7425224Smckusick register int br, cvec; 7525224Smckusick register struct dmzdevice *dmz_addr; 7625224Smckusick register unsigned int a; 7725224Smckusick 7825224Smckusick dmz_addr = (struct dmzdevice *)reg; 7925224Smckusick 8025224Smckusick #ifdef lint 8125224Smckusick br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 8225224Smckusick dmzrinta(0); dmzrintb(0); dmzrintc(0); 8325224Smckusick #endif 8425224Smckusick 8525224Smckusick br = 0x15; 8625224Smckusick 8725224Smckusick a = dmz_addr->dmz_config; 8825224Smckusick if (((a>>12) & ~DMZ_INTERFACE) != 0) { 8925224Smckusick printf(" Unknown interface type\n"); 9025224Smckusick return (0); 9125224Smckusick } 9225224Smckusick if (((a>>8) & DMZ_NOC_MASK) != 3) { 9325224Smckusick printf(" Not all octets are available\n"); 9425224Smckusick return (0); 9525224Smckusick } 9625224Smckusick 9725224Smckusick cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 9825224Smckusick dmz_addr->dmz_config = cvec >> 2; 9925224Smckusick 10025224Smckusick return (sizeof(struct dmzdevice)); 10125224Smckusick } 10225224Smckusick 10325224Smckusick dmzattach(ui) 10430537Skarels register struct uba_device *ui; 10525224Smckusick { 10630537Skarels register struct dmx_softc *sc; 10730537Skarels register int i; 10830537Skarels 10930537Skarels sc = &dmz_softc[3 * ui->ui_unit]; 11030537Skarels for (i = 0; i < 3; i++, sc++) { 11130537Skarels sc->dmx_type = 'z'; 11230537Skarels sc->dmx_unit = ui->ui_unit; 11330537Skarels sc->dmx_unit0 = 8 * i; 11430537Skarels sc->dmx_ubanum = ui->ui_ubanum; 11530537Skarels sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff; 11630537Skarels sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8]; 11730537Skarels sc->dmx_octet = (struct dmx_octet *) 11830537Skarels &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i]; 11930537Skarels } 12030537Skarels 12126218Skarels cbase[ui->ui_ubanum] = -1; 12236610Sbostic dmz_uballoc[ui->ui_ubanum] = -1; 12325224Smckusick } 12425224Smckusick 12530537Skarels /* 12630537Skarels * Open a DMF32 line, mapping the clist onto the uba if this 12730537Skarels * is the first dmf on this uba. Turn on this dmf if this is 12830537Skarels * the first use of it. 12930537Skarels */ 13030537Skarels /*ARGSUSED*/ 13130537Skarels dmzopen(dev, flag) 13230537Skarels dev_t dev; 13325224Smckusick { 13425224Smckusick register struct tty *tp; 13530537Skarels struct dmx_softc *sc; 13630537Skarels int unit, dmz; 13730537Skarels struct uba_device *ui; 13830537Skarels int s; 13939061Smarc int dmxparam(); 14025224Smckusick 14130537Skarels unit = minor(dev); 14230537Skarels dmz = DMZ(unit); 14330537Skarels if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0) 14425224Smckusick return (ENXIO); 14525224Smckusick 14625224Smckusick tp = &dmz_tty[unit]; 14730537Skarels sc = &dmz_softc[unit / 8]; 14830537Skarels tp->t_addr = (caddr_t)sc->dmx_octet; 14925224Smckusick tp->t_oproc = dmzstart; 15030537Skarels tp->t_dev = dev; /* needed before dmxopen */ 15139061Smarc tp->t_param = dmxparam; 15225224Smckusick 15325224Smckusick /* 15430537Skarels * While setting up state for this uba, 15530537Skarels * block uba resets which can clear the state. 15625224Smckusick */ 15730537Skarels s = spl6(); 15826218Skarels if (cbase[ui->ui_ubanum] == -1) { 15930537Skarels dmz_uballoc[ui->ui_ubanum] = dmz; 16030322Skarels cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 16130322Skarels (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 16225224Smckusick } 16330537Skarels splx(s); 16425224Smckusick 16539061Smarc return (dmxopen(tp, sc, flag)); 16625224Smckusick } 16725224Smckusick 16830537Skarels /* 16930537Skarels * Close a DMZ32 line. 17030537Skarels */ 17130537Skarels /*ARGSUSED*/ 17230537Skarels dmzclose(dev, flag) 17330537Skarels dev_t dev; 17425224Smckusick int flag; 17525224Smckusick { 17625224Smckusick 17740728Skarels return (dmxclose(&dmz_tty[minor(dev)])); 17825224Smckusick } 17925224Smckusick 18039061Smarc dmzread(dev, uio, flag) 18130537Skarels dev_t dev; 18230537Skarels struct uio *uio; 18325224Smckusick { 18425224Smckusick register struct tty *tp; 18525224Smckusick 18630537Skarels tp = &dmz_tty[minor(dev)]; 18739061Smarc return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 18825224Smckusick } 18925224Smckusick 19030537Skarels dmzwrite(dev, uio) 19130537Skarels dev_t dev; 19225224Smckusick struct uio *uio; 19325224Smckusick { 19425224Smckusick register struct tty *tp; 19525224Smckusick 19630537Skarels tp = &dmz_tty[minor(dev)]; 19730537Skarels return ((*linesw[tp->t_line].l_write)(tp, uio)); 19825224Smckusick } 19925224Smckusick 20030537Skarels /* 20130537Skarels * DMZ32 receiver interrupts. 20230537Skarels */ 20330537Skarels dmzrinta(dmz) 20430537Skarels int dmz; 20525224Smckusick { 20630537Skarels struct uba_device *ui; 20725224Smckusick 20830537Skarels ui = dmzinfo[dmz]; 20930537Skarels if (ui == 0 || ui->ui_alive == 0) 21030537Skarels return; 21130537Skarels dmxrint(&dmz_softc[3 * dmz + 0]); 21225224Smckusick } 21325224Smckusick 21430537Skarels dmzrintb(dmz) 21530537Skarels int dmz; 21625224Smckusick { 21730537Skarels struct uba_device *ui; 21825224Smckusick 21930537Skarels ui = dmzinfo[dmz]; 22030537Skarels if (ui == 0 || ui->ui_alive == 0) 22130537Skarels return; 22230537Skarels dmxrint(&dmz_softc[3 * dmz + 1]); 22325224Smckusick } 22425224Smckusick 22530537Skarels dmzrintc(dmz) 22630537Skarels int dmz; 22725224Smckusick { 22830537Skarels struct uba_device *ui; 22925224Smckusick 23030537Skarels ui = dmzinfo[dmz]; 23125224Smckusick if (ui == 0 || ui->ui_alive == 0) 23225224Smckusick return; 23330537Skarels dmxrint(&dmz_softc[3 * dmz + 2]); 23425224Smckusick } 23525224Smckusick 23630537Skarels /* 23730537Skarels * Ioctl for DMZ32. 23830537Skarels */ 23930537Skarels dmzioctl(dev, cmd, data, flag) 24030537Skarels dev_t dev; 24130537Skarels caddr_t data; 24225224Smckusick { 24330537Skarels int unit = minor(dev); 24430537Skarels 24530537Skarels return (dmxioctl(&dmz_tty[unit], cmd, data, flag)); 24625224Smckusick } 24725224Smckusick 24830537Skarels /* 24930537Skarels * DMZ32 transmitter interrupts. 25030537Skarels */ 25130537Skarels dmzxinta(dmz) 25230537Skarels int dmz; 25325224Smckusick { 25430537Skarels 25530537Skarels dmxxint(&dmz_softc[3 * dmz + 0]); 25625224Smckusick } 25725224Smckusick 25830537Skarels dmzxintb(dmz) 25930537Skarels int dmz; 26025224Smckusick { 26130537Skarels 26230537Skarels dmxxint(&dmz_softc[3 * dmz + 1]); 26325224Smckusick } 26425224Smckusick 26530537Skarels dmzxintc(dmz) 26630537Skarels int dmz; 26725224Smckusick { 26825224Smckusick 26930537Skarels dmxxint(&dmz_softc[3 * dmz + 2]); 27025224Smckusick } 27125224Smckusick 27230537Skarels /* 27330537Skarels * Start (restart) transmission on the given line. 27430537Skarels */ 27525224Smckusick dmzstart(tp) 27630537Skarels struct tty *tp; 27725224Smckusick { 27825224Smckusick 27930537Skarels dmxstart(tp, &dmz_softc[minor(tp->t_dev) >> 3]); 28025224Smckusick } 28125224Smckusick 28230537Skarels /* 28330537Skarels * Stop output on a line, e.g. for ^S/^Q or output flush. 28430537Skarels */ 28525224Smckusick dmzstop(tp, flag) 28630537Skarels struct tty *tp; 28725224Smckusick { 28825224Smckusick 28930537Skarels dmxstop(tp, &dmz_softc[minor(tp->t_dev) >> 3], flag); 29025224Smckusick } 29125224Smckusick 29230537Skarels /* 29330537Skarels * Reset state of driver if UBA reset was necessary. 29430537Skarels * Reset the csr, lpr, and lcr registers on open lines, and 29530537Skarels * restart transmitters. 29630537Skarels */ 29730537Skarels dmzreset(uban) 29830537Skarels int uban; 29925224Smckusick { 30030537Skarels register int dmz; 30125224Smckusick register struct tty *tp; 30230537Skarels register struct uba_device *ui; 30330537Skarels register struct dmzdevice *addr; 30430537Skarels int i; 30525224Smckusick 30630537Skarels for (dmz = 0; dmz < NDMZ; dmz++) { 30730537Skarels ui = dmzinfo[dmz]; 30830537Skarels if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 30930537Skarels continue; 31030537Skarels printf("dmz%d ", dmz); 31130537Skarels addr = (struct dmzdevice *)ui->ui_addr; 31225224Smckusick 31330537Skarels if (dmz_uballoc[uban] == dmz) { 31430537Skarels int info; 31525224Smckusick 31630537Skarels info = uballoc(uban, (caddr_t)cfree, 31730537Skarels nclist * sizeof(struct cblock), UBA_CANTWAIT); 31830537Skarels if (info) 31930537Skarels cbase[uban] = UBAI_ADDR(info); 32030537Skarels else { 32130537Skarels printf(" [can't get uba map]"); 32230537Skarels cbase[uban] = -1; 32330537Skarels } 32430537Skarels } 32525224Smckusick 32630537Skarels for (i = 0; i < 3; i++) 32730537Skarels if (dmz_softc[3 * dmz + i].dmx_flags & DMX_ACTIVE) { 32830537Skarels addr->dmz_octet[i].csr = DMF_IE; 32930537Skarels addr->dmz_octet[i].rsp = dmx_timeout; 33030537Skarels } 33125224Smckusick 33230537Skarels /* 33330537Skarels * If a unit is open or waiting for open to complete, 33430537Skarels * reset it. 33530537Skarels */ 33630537Skarels tp = &dmz_tty[dmz * 24]; 33730537Skarels for (i = 0; i < 24; i++, tp++) { 33830537Skarels if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 33939061Smarc dmxparam(tp, &tp->t_termios); 34030537Skarels (void) dmxmctl(tp, DMF_ON, DMSET); 34130537Skarels tp->t_state &= ~TS_BUSY; 34230537Skarels dmzstart(tp); 34330537Skarels } 34430537Skarels } 34525224Smckusick } 34625224Smckusick } 34725224Smckusick #endif 348