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.9 (Berkeley) 04/12/90 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 "uba.h" 19 #include "param.h" 20 #include "conf.h" 21 #include "user.h" 22 #include "proc.h" 23 #include "ioctl.h" 24 #include "tty.h" 25 #include "map.h" 26 #include "buf.h" 27 #include "vm.h" 28 #include "bkmac.h" 29 #include "clist.h" 30 #include "file.h" 31 #include "uio.h" 32 #include "kernel.h" 33 #include "syslog.h" 34 35 #include "dmx.h" 36 #include "ubareg.h" 37 #include "ubavar.h" 38 #include "dmxreg.h" 39 #include "dmzreg.h" 40 #include "dmreg.h" 41 42 extern int dmx_timeout; /* silo timeout, in ms */ 43 int dmzstart(); 44 45 /* 46 * The clist space is mapped by one terminal driver onto each UNIBUS. 47 * The identity of the board which allocated resources is recorded, 48 * so the process may be repeated after UNIBUS resets. 49 * The UBACVT macro converts a clist space address for unibus uban 50 * into an i/o space address for the DMA routine. 51 */ 52 int dmz_uballoc[NUBA]; /* which dmz (if any) allocated unibus map */ 53 int cbase[NUBA]; /* base address of clists in unibus map */ 54 55 /* 56 * Autoconfiguration and variables for DMZ32 57 */ 58 int dmzprobe(), dmzattach(); 59 struct uba_device *dmzinfo[NDMZ]; 60 u_short dmzstd[] = { 0 }; 61 struct uba_driver dmzdriver = { 62 dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo 63 }; 64 65 struct tty dmz_tty[NDMZ*24]; 66 struct dmx_softc dmz_softc[3 * NDMZ]; 67 #ifndef lint 68 int ndmz = NDMZ*24; /* used by iostat */ 69 #endif 70 71 dmzprobe(reg) 72 caddr_t reg; 73 { 74 register int br, cvec; 75 register struct dmzdevice *dmz_addr; 76 register unsigned int a; 77 78 dmz_addr = (struct dmzdevice *)reg; 79 80 #ifdef lint 81 br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0); 82 dmzrinta(0); dmzrintb(0); dmzrintc(0); 83 #endif 84 85 br = 0x15; 86 87 a = dmz_addr->dmz_config; 88 if (((a>>12) & ~DMZ_INTERFACE) != 0) { 89 printf(" Unknown interface type\n"); 90 return (0); 91 } 92 if (((a>>8) & DMZ_NOC_MASK) != 3) { 93 printf(" Not all octets are available\n"); 94 return (0); 95 } 96 97 cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6); 98 dmz_addr->dmz_config = cvec >> 2; 99 100 return (sizeof(struct dmzdevice)); 101 } 102 103 dmzattach(ui) 104 register struct uba_device *ui; 105 { 106 register struct dmx_softc *sc; 107 register int i; 108 109 sc = &dmz_softc[3 * ui->ui_unit]; 110 for (i = 0; i < 3; i++, sc++) { 111 sc->dmx_type = 'z'; 112 sc->dmx_unit = ui->ui_unit; 113 sc->dmx_unit0 = 8 * i; 114 sc->dmx_ubanum = ui->ui_ubanum; 115 sc->dmx_softCAR = (ui->ui_flags >> (8 * i)) & 0xff; 116 sc->dmx_tty = &dmz_tty[((ui->ui_unit * 3) + i) * 8]; 117 sc->dmx_octet = (struct dmx_octet *) 118 &((struct dmzdevice *)ui->ui_addr)->dmz_octet[i]; 119 } 120 121 cbase[ui->ui_ubanum] = -1; 122 dmz_uballoc[ui->ui_ubanum] = -1; 123 } 124 125 /* 126 * Open a DMF32 line, mapping the clist onto the uba if this 127 * is the first dmf on this uba. Turn on this dmf if this is 128 * the first use of it. 129 */ 130 /*ARGSUSED*/ 131 dmzopen(dev, flag) 132 dev_t dev; 133 { 134 register struct tty *tp; 135 struct dmx_softc *sc; 136 int unit, dmz; 137 struct uba_device *ui; 138 int s; 139 int dmxparam(); 140 141 unit = minor(dev); 142 dmz = DMZ(unit); 143 if (unit >= NDMZ*24 || (ui = dmzinfo[dmz])== 0 || ui->ui_alive == 0) 144 return (ENXIO); 145 146 tp = &dmz_tty[unit]; 147 sc = &dmz_softc[unit / 8]; 148 tp->t_addr = (caddr_t)sc->dmx_octet; 149 tp->t_oproc = dmzstart; 150 tp->t_dev = dev; /* needed before dmxopen */ 151 tp->t_param = dmxparam; 152 153 /* 154 * While setting up state for this uba, 155 * block uba resets which can clear the state. 156 */ 157 s = spl6(); 158 if (cbase[ui->ui_ubanum] == -1) { 159 dmz_uballoc[ui->ui_ubanum] = dmz; 160 cbase[ui->ui_ubanum] = UBAI_ADDR(uballoc(ui->ui_ubanum, 161 (caddr_t)cfree, nclist*sizeof(struct cblock), 0)); 162 } 163 splx(s); 164 165 return (dmxopen(tp, sc, flag)); 166 } 167 168 /* 169 * Close a DMZ32 line. 170 */ 171 /*ARGSUSED*/ 172 dmzclose(dev, flag) 173 dev_t dev; 174 int flag; 175 { 176 177 return (dmxclose(&dmz_tty[minor(dev)])); 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