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