1 /* 2 * Copyright (c) 1985, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)dmz.c 7.12 (Berkeley) 05/16/91 7 */ 8 9 /* 10 * DMZ-32 driver 11 */ 12 13 #include "dmz.h" 14 #if NDMZ > 0 15 16 #include "../include/pte.h" 17 18 #include "sys/param.h" 19 #include "uba.h" 20 #include "sys/conf.h" 21 #include "sys/user.h" 22 #include "sys/proc.h" 23 #include "sys/ioctl.h" 24 #include "sys/tty.h" 25 #include "sys/map.h" 26 #include "sys/buf.h" 27 #include "sys/vm.h" 28 #include "sys/clist.h" 29 #include "sys/file.h" 30 #include "sys/uio.h" 31 #include "sys/kernel.h" 32 #include "sys/syslog.h" 33 34 #include "dmx.h" 35 #include "ubareg.h" 36 #include "ubavar.h" 37 #include "dmxreg.h" 38 #include "dmzreg.h" 39 #include "dmreg.h" 40 41 extern int dmx_timeout; /* silo timeout, in ms */ 42 int dmzstart(); 43 44 /* 45 * The clist space is mapped by one terminal driver onto each UNIBUS. 46 * The identity of the board which allocated resources is recorded, 47 * so the process may be repeated after UNIBUS resets. 48 * The UBACVT macro converts a clist space address for unibus uban 49 * into an i/o space address for the DMA routine. 50 */ 51 int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ 52 int cbase[NUBA]; /* base address of clists in unibus map */ 53 54 /* 55 * Autoconfiguration and variables for DMZ32 56 */ 57 int dmzprobe(), dmzattach(); 58 struct uba_device *dmzinfo[NDMZ]; 59 u_short dmzstd[] = { 0 }; 60 struct uba_driver dmzdriver = { 61 dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 62 }; 63 64 struct tty dmz_tty[NDMZ*24]; 65 struct dmx_softc dmz_softc[3 * NDMZ]; 66 #ifndef lint 67 int ndmz = NDMZ*24; /* used by iostat */ 68 #endif 69 70 dmzprobe(reg) 71 caddr_t reg; 72 { 73 register int br, cvec; 74 register struct dmzdevice *dmz_addr; 75 register unsigned int a; 76 77 dmz_addr = (struct dmzdevice *)reg; 78 79 #ifdef lint 80 br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 81 dmzrinta(0); dmzrintb(0); dmzrintc(0); 82 #endif 83 84 br = 0x15; 85 86 a = dmz_addr->dmz_config; 87 if (((a>>12) & ~DMZ_INTERFACE) != 0) { 88 printf(" Unknown interface type\n"); 89 return (0); 90 } 91 if (((a>>8) & DMZ_NOC_MASK) != 3) { 92 printf(" Not all octets are available\n"); 93 return (0); 94 } 95 96 cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 97 dmz_addr->dmz_config = cvec >> 2; 98 99 return (sizeof(struct dmzdevice)); 100 } 101 102 dmzattach(ui) 103 register struct uba_device *ui; 104 { 105 register struct dmx_softc *sc; 106 register int i; 107 108 sc = &dmz_softc[3 * ui->ui_unit]; 109 for (i = 0; i < 3; i++, sc++) { 110 sc->dmx_type = 'z'; 111 sc->dmx_unit = ui->ui_unit; 112 sc->dmx_unit0 = 8 * i; 113 sc->dmx_ubanum = ui->ui_ubanum; 114 sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff; 115 sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8]; 116 sc->dmx_octet = (struct dmx_octet *) 117 &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i]; 118 } 119 120 cbase[ui->ui_ubanum] = -1; 121 dmz_uballoc[ui->ui_ubanum] = -1; 122 } 123 124 /* 125 * Open a DMF32 line, mapping the clist onto the uba if this 126 * is the first dmf on this uba. Turn on this dmf if this is 127 * the first use of it. 128 */ 129 /*ARGSUSED*/ 130 dmzopen(dev, flag) 131 dev_t dev; 132 { 133 register struct tty *tp; 134 struct dmx_softc *sc; 135 int unit, dmz; 136 struct uba_device *ui; 137 int s; 138 int dmxparam(); 139 140 unit = minor(dev); 141 dmz = DMZ(unit); 142 if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0) 143 return (ENXIO); 144 145 tp = &dmz_tty[unit]; 146 sc = &dmz_softc[unit / 8]; 147 tp->t_addr = (caddr_t)sc->dmx_octet; 148 tp->t_oproc = dmzstart; 149 tp->t_dev = dev; /* needed before dmxopen */ 150 tp->t_param = dmxparam; 151 152 /* 153 * While setting up state for this uba, 154 * block uba resets which can clear the state. 155 */ 156 s = spl6(); 157 if (cbase[ui->ui_ubanum] == -1) { 158 dmz_uballoc[ui->ui_ubanum] = dmz; 159 cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 160 (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 161 } 162 splx(s); 163 164 return (dmxopen(tp, sc, flag)); 165 } 166 167 /* 168 * Close a DMZ32 line. 169 */ 170 /*ARGSUSED*/ 171 dmzclose(dev, flag, mode, p) 172 dev_t dev; 173 int flag, mode; 174 struct proc *p; 175 { 176 177 return (dmxclose(&dmz_tty[minor(dev)]), flag); 178 } 179 180 dmzread(dev, uio, flag) 181 dev_t dev; 182 struct uio *uio; 183 { 184 register struct tty *tp; 185 186 tp = &dmz_tty[minor(dev)]; 187 return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 188 } 189 190 dmzwrite(dev, uio) 191 dev_t dev; 192 struct uio *uio; 193 { 194 register struct tty *tp; 195 196 tp = &dmz_tty[minor(dev)]; 197 return ((*linesw[tp->t_line].l_write)(tp, uio)); 198 } 199 200 /* 201 * DMZ32 receiver interrupts. 202 */ 203 dmzrinta(dmz) 204 int dmz; 205 { 206 struct uba_device *ui; 207 208 ui = dmzinfo[dmz]; 209 if (ui == 0 || ui->ui_alive == 0) 210 return; 211 dmxrint(&dmz_softc[3 * dmz + 0]); 212 } 213 214 dmzrintb(dmz) 215 int dmz; 216 { 217 struct uba_device *ui; 218 219 ui = dmzinfo[dmz]; 220 if (ui == 0 || ui->ui_alive == 0) 221 return; 222 dmxrint(&dmz_softc[3 * dmz + 1]); 223 } 224 225 dmzrintc(dmz) 226 int dmz; 227 { 228 struct uba_device *ui; 229 230 ui = dmzinfo[dmz]; 231 if (ui == 0 || ui->ui_alive == 0) 232 return; 233 dmxrint(&dmz_softc[3 * dmz + 2]); 234 } 235 236 /* 237 * Ioctl for DMZ32. 238 */ 239 dmzioctl(dev, cmd, data, flag) 240 dev_t dev; 241 caddr_t data; 242 { 243 int unit = minor(dev); 244 245 return (dmxioctl(&dmz_tty[unit], cmd, data, flag)); 246 } 247 248 /* 249 * DMZ32 transmitter interrupts. 250 */ 251 dmzxinta(dmz) 252 int dmz; 253 { 254 255 dmxxint(&dmz_softc[3 * dmz + 0]); 256 } 257 258 dmzxintb(dmz) 259 int dmz; 260 { 261 262 dmxxint(&dmz_softc[3 * dmz + 1]); 263 } 264 265 dmzxintc(dmz) 266 int dmz; 267 { 268 269 dmxxint(&dmz_softc[3 * dmz + 2]); 270 } 271 272 /* 273 * Start (restart) transmission on the given line. 274 */ 275 dmzstart(tp) 276 struct tty *tp; 277 { 278 279 dmxstart(tp, &dmz_softc[minor(tp->t_dev) >> 3]); 280 } 281 282 /* 283 * Stop output on a line, e.g. for ^S/^Q or output flush. 284 */ 285 dmzstop(tp, flag) 286 struct tty *tp; 287 { 288 289 dmxstop(tp, &dmz_softc[minor(tp->t_dev) >> 3], flag); 290 } 291 292 /* 293 * Reset state of driver if UBA reset was necessary. 294 * Reset the csr, lpr, and lcr registers on open lines, and 295 * restart transmitters. 296 */ 297 dmzreset(uban) 298 int uban; 299 { 300 register int dmz; 301 register struct tty *tp; 302 register struct uba_device *ui; 303 register struct dmzdevice *addr; 304 int i; 305 306 for (dmz = 0; dmz < NDMZ; dmz++) { 307 ui = dmzinfo[dmz]; 308 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 309 continue; 310 printf("dmz%d ", dmz); 311 addr = (struct dmzdevice *)ui->ui_addr; 312 313 if (dmz_uballoc[uban] == dmz) { 314 int info; 315 316 info = uballoc(uban, (caddr_t)cfree, 317 nclist * sizeof(struct cblock), UBA_CANTWAIT); 318 if (info) 319 cbase[uban] = UBAI_ADDR(info); 320 else { 321 printf(" [can't get uba map]"); 322 cbase[uban] = -1; 323 } 324 } 325 326 for (i = 0; i < 3; i++) 327 if (dmz_softc[3 * dmz + i].dmx_flags & DMX_ACTIVE) { 328 addr->dmz_octet[i].csr = DMF_IE; 329 addr->dmz_octet[i].rsp = dmx_timeout; 330 } 331 332 /* 333 * If a unit is open or waiting for open to complete, 334 * reset it. 335 */ 336 tp = &dmz_tty[dmz * 24]; 337 for (i = 0; i < 24; i++, tp++) { 338 if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) { 339 dmxparam(tp, &tp->t_termios); 340 (void) dmxmctl(tp, DMF_ON, DMSET); 341 tp->t_state &= ~TS_BUSY; 342 dmzstart(tp); 343 } 344 } 345 } 346 } 347 #endif 348