1 /* dz.c 4.10 02/10/81 */ 2 3 #include "dz.h" 4 #if NDZ11 > 0 5 /* 6 * DZ-11 Driver 7 */ 8 #include "../h/param.h" 9 #include "../h/systm.h" 10 #include "../h/tty.h" 11 #include "../h/dir.h" 12 #include "../h/user.h" 13 #include "../h/map.h" 14 #include "../h/pte.h" 15 #include "../h/buf.h" 16 #include "../h/uba.h" 17 #include "../h/conf.h" 18 #include "../h/pdma.h" 19 #include "../h/bk.h" 20 #include "../h/file.h" 21 #include "../h/mx.h" 22 23 /* 24 * When running dz's using only SAE (silo alarm) on input 25 * it is necessary to call dzrint() at clock interrupt time. 26 * This is unsafe unless spl5()s in tty code are changed to 27 * spl6()s to block clock interrupts. Note that the dh driver 28 * currently in use works the same way as the dz, even though 29 * we could try to more intelligently manage its silo. 30 * Thus don't take this out if you have no dz's unless you 31 * change clock.c and dhtimer(). 32 * 33 * SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME. 34 */ 35 #define spl5 spl6 36 37 int dzcntrlr(), dzslave(), dzrint(); 38 struct uba_dinfo *dzinfo[NDZ11]; 39 u_short dzstd[] = { 0 }; 40 int (*dzivec[])() = { dzrint, 0 }; /* omit dzxint so we can do it here */ 41 struct uba_driver dzdriver = 42 { dzcntrlr, dzslave, (int (*)())0, 0, 0, dzstd, dzinfo, dzivec }; 43 44 #define NDZ (NDZ11*8) 45 46 #define BITS7 020 47 #define BITS8 030 48 #define TWOSB 040 49 #define PENABLE 0100 50 #define OPAR 0200 51 #define MSE 040 /* Master Scan Enable */ 52 #define RIE 0100 /* Receiver Interrupt Enable */ 53 #define SAE 010000 /* Silo Alarm Enable */ 54 #define TIE 040000 /* Transmit Interrupt Enable */ 55 #define DZ_IEN (MSE+RIE+TIE+SAE) 56 #define PERROR 010000 57 #define FRERROR 020000 58 #define OVERRUN 040000 59 #define SSPEED 7 /* std speed = 300 baud */ 60 61 #define dzlpr dzrbuf 62 #define dzmsr dzbrk 63 #define ON 1 64 #define OFF 0 65 66 int dzstart(); 67 int dzxint(); 68 int dzdma(); 69 int ttrstrt(); 70 struct tty dz_tty[NDZ]; 71 int dz_cnt = { NDZ }; 72 int dzact; 73 74 struct device { 75 short dzcsr; 76 short dzrbuf; 77 char dztcr; 78 char dzdtr; 79 char dztbuf; 80 char dzbrk; 81 }; 82 83 struct pdma dzpdma[NDZ]; 84 char dz_timer; 85 char dz_speeds[] = 86 { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 87 char dz_brk[NDZ11]; 88 89 dzcntrlr(ui, reg) 90 struct uba_dinfo *ui; 91 caddr_t reg; 92 { 93 94 ((struct device *)reg)->dzcsr |= IENABLE; 95 /* get it to interrupt */ 96 } 97 98 dzslave(ui, reg, slaveno, uban) 99 register struct uba_dinfo *ui; 100 caddr_t reg; 101 { 102 register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 103 register struct tty *tp = &dz_tty[ui->ui_unit*8]; 104 register int cnt; 105 register int *urk = (int *)(® - 24); /* white magic */ 106 caddr_t cp; 107 int urk2; 108 109 for (cnt = 0; cnt < 8; cnt++) { 110 pdp->p_addr = (struct device *)reg; 111 pdp->p_arg = (int)tp; 112 pdp->p_fcn = dzxint; 113 pdp++, tp++; 114 } 115 if ((cp = calloc(12)) == 0) 116 panic("dz iv nm\n"); 117 uba_hd[uban].uh_vec[*urk] = (int (*)())cp; /* more white magic */ 118 *cp++ = 0xbb; *cp++ = 0xff; *cp++ = 0xd0; /* black magic */ 119 *cp++ = ui->ui_unit&0x3f; *cp++ = 0x50; 120 *cp++ = 0x17; *cp++ = 0x9f; 121 urk2 = (int)dzdma; 122 for (cnt = 0; cnt < 4; cnt++) 123 *cp++ = urk2, urk2 >>= 4; /* the spell ends */ 124 return (1); 125 } 126 127 /*ARGSUSED*/ 128 dzopen(dev, flag) 129 dev_t dev; 130 { 131 register struct tty *tp; 132 register int unit; 133 extern dzscan(); 134 135 unit = minor(dev); 136 if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 137 u.u_error = ENXIO; 138 return; 139 } 140 if (dz_timer == 0) { 141 dz_timer++; 142 timeout(dzscan, (caddr_t)0, 60); 143 } 144 tp = &dz_tty[unit]; 145 tp->t_addr = (caddr_t)&dzpdma[unit]; 146 tp->t_oproc = dzstart; 147 tp->t_iproc = NULL; 148 tp->t_state |= WOPEN; 149 if ((tp->t_state & ISOPEN) == 0) { 150 ttychars(tp); 151 tp->t_ospeed = tp->t_ispeed = SSPEED; 152 tp->t_flags = ODDP|EVENP|ECHO; 153 /*tp->t_state |= HUPCLS;*/ 154 dzparam(unit); 155 } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 156 u.u_error = EBUSY; 157 return; 158 } 159 dzmodem(unit, ON); 160 (void) spl5(); 161 while ((tp->t_state & CARR_ON) == 0) { 162 tp->t_state |= WOPEN; 163 sleep((caddr_t)&tp->t_rawq, TTIPRI); 164 } 165 (void) spl0(); 166 (*linesw[tp->t_line].l_open)(dev, tp); 167 } 168 169 /*ARGSUSED*/ 170 dzclose(dev, flag) 171 dev_t dev; 172 { 173 register struct tty *tp; 174 register int unit; 175 int dz; 176 177 unit = minor(dev); 178 dz = unit >> 3; 179 tp = &dz_tty[unit]; 180 (*linesw[tp->t_line].l_close)(tp); 181 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 182 (dz_brk[dz] &= ~(1 << (unit&07))); 183 if (tp->t_state & HUPCLS) 184 dzmodem(unit, OFF); 185 ttyclose(tp); 186 } 187 188 dzread(dev) 189 dev_t dev; 190 { 191 register struct tty *tp; 192 193 tp = &dz_tty[minor(dev)]; 194 (*linesw[tp->t_line].l_read)(tp); 195 } 196 197 dzwrite(dev) 198 dev_t dev; 199 { 200 register struct tty *tp; 201 202 tp = &dz_tty[minor(dev)]; 203 (*linesw[tp->t_line].l_write)(tp); 204 } 205 206 /*ARGSUSED*/ 207 dzrint(dz) 208 int dz; 209 { 210 register struct tty *tp; 211 register int c; 212 register struct device *dzaddr; 213 register struct tty *tp0; 214 register int unit; 215 int s; 216 217 s = spl6(); /* see comment in clock.c */ 218 /* as long as we are here, service them all */ 219 for (unit = 0; unit < NDZ; unit += 8) { 220 if ((dzact & (1<<(unit>>3))) == 0) 221 continue; 222 dzaddr = dzpdma[unit].p_addr; 223 tp0 = &dz_tty[unit]; 224 while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 225 tp = tp0 + ((c>>8)&07); 226 if (tp >= &dz_tty[dz_cnt]) 227 continue; 228 if ((tp->t_state & ISOPEN) == 0) { 229 wakeup((caddr_t)&tp->t_rawq); 230 continue; 231 } 232 if (c&FRERROR) 233 /* framing error = break */ 234 if (tp->t_flags & RAW) 235 c = 0; /* null for getty */ 236 else 237 #ifdef IIASA 238 continue; 239 #else 240 c = tun.t_intrc; 241 #endif 242 if (c&OVERRUN) 243 printf("o"); 244 if (c&PERROR) 245 /* parity error */ 246 if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 247 || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 248 continue; 249 if (tp->t_line == NETLDISC) { 250 c &= 0177; 251 BKINPUT(c, tp); 252 } else 253 (*linesw[tp->t_line].l_rint)(c, tp); 254 } 255 } 256 splx(s); 257 } 258 259 /*ARGSUSED*/ 260 dzioctl(dev, cmd, addr, flag) 261 dev_t dev; 262 caddr_t addr; 263 { 264 register struct tty *tp; 265 register int unit = minor(dev); 266 register int dz = unit >> 3; 267 268 tp = &dz_tty[unit]; 269 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 270 if (cmd == 0) 271 return; 272 if (ttioctl(tp, cmd, addr, flag)) { 273 if (cmd==TIOCSETP || cmd==TIOCSETN) 274 dzparam(unit); 275 } else switch(cmd) { 276 277 case TIOCSBRK: 278 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 279 (dz_brk[dz] |= 1 << (unit&07)); 280 break; 281 case TIOCCBRK: 282 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 283 (dz_brk[dz] &= ~(1 << (unit&07))); 284 break; 285 case TIOCSDTR: 286 dzmodem(unit, ON); 287 break; 288 case TIOCCDTR: 289 dzmodem(unit, OFF); 290 break; 291 default: 292 u.u_error = ENOTTY; 293 } 294 } 295 296 dzparam(unit) 297 register int unit; 298 { 299 register struct tty *tp; 300 register struct device *dzaddr; 301 register int lpr; 302 303 tp = &dz_tty[unit]; 304 dzaddr = dzpdma[unit].p_addr; 305 dzaddr->dzcsr = DZ_IEN; 306 dzact |= (1<<(unit>>3)); 307 if (tp->t_ispeed == 0) { 308 dzmodem(unit, OFF); /* hang up line */ 309 return; 310 } 311 lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 312 #ifndef IIASA 313 if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 314 lpr |= BITS8; 315 else 316 lpr |= (BITS7|PENABLE); 317 if ((tp->t_flags & EVENP) == 0) 318 lpr |= OPAR; 319 #else IIASA 320 if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP)) 321 lpr |= BITS8; 322 else if (tp->t_flags & EVENP) 323 lpr |= (BITS7|PENABLE); 324 else if (tp->t_flags & ODDP) 325 lpr |= (BITS7|OPAR|PENABLE); 326 else 327 lpr |= BITS7; 328 #endif IIASA 329 if (tp->t_ispeed == 3) 330 lpr |= TWOSB; /* 110 baud: 2 stop bits */ 331 dzaddr->dzlpr = lpr; 332 } 333 334 dzxint(tp) 335 register struct tty *tp; 336 { 337 register struct pdma *dp; 338 register s; 339 s = spl6(); /* block the clock */ 340 341 dp = (struct pdma *)tp->t_addr; 342 tp->t_state &= ~BUSY; 343 if (tp->t_state & FLUSH) 344 tp->t_state &= ~FLUSH; 345 else 346 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 347 if (tp->t_line) 348 (*linesw[tp->t_line].l_start)(tp); 349 else 350 dzstart(tp); 351 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 352 dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 353 splx(s); 354 } 355 356 dzstart(tp) 357 register struct tty *tp; 358 { 359 register struct pdma *dp; 360 register struct device *dzaddr; 361 register int cc; 362 int s; 363 364 dp = (struct pdma *)tp->t_addr; 365 dzaddr = dp->p_addr; 366 s = spl5(); 367 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 368 goto out; 369 if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 370 tp->t_state &= ~ASLEEP; 371 if (tp->t_chan) 372 mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 373 else 374 wakeup((caddr_t)&tp->t_outq); 375 } 376 if (tp->t_outq.c_cc == 0) 377 goto out; 378 if (tp->t_flags&RAW) 379 cc = ndqb(&tp->t_outq, 0); 380 else { 381 cc = ndqb(&tp->t_outq, 0200); 382 if (cc == 0) { 383 cc = getc(&tp->t_outq); 384 timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6); 385 tp->t_state |= TIMEOUT; 386 goto out; 387 } 388 } 389 tp->t_state |= BUSY; 390 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 391 dp->p_end += cc; 392 dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); 393 out: 394 splx(s); 395 } 396 397 /* 398 * Stop output on a line. 399 * Assume call is made at spl6. 400 */ 401 /*ARGSUSED*/ 402 dzstop(tp, flag) 403 register struct tty *tp; 404 { 405 register struct pdma *dp; 406 register int s; 407 408 dp = (struct pdma *)tp->t_addr; 409 s = spl6(); 410 if (tp->t_state & BUSY) { 411 dp->p_end = dp->p_mem; 412 if ((tp->t_state&TTSTOP)==0) 413 tp->t_state |= FLUSH; 414 } 415 splx(s); 416 } 417 418 dzmodem(unit, flag) 419 register int unit; 420 { 421 register struct device *dzaddr; 422 register char bit; 423 424 dzaddr = dzpdma[unit].p_addr; 425 bit = 1<<(unit&07); 426 if (flag == OFF) 427 dzaddr->dzdtr &= ~bit; 428 else 429 dzaddr->dzdtr |= bit; 430 } 431 432 dzscan() 433 { 434 register i; 435 register struct device *dzaddr; 436 register bit; 437 register struct tty *tp; 438 439 for (i = 0; i < dz_cnt ; i++) { 440 dzaddr = dzpdma[i].p_addr; 441 tp = &dz_tty[i]; 442 bit = 1<<(i&07); 443 if (dzaddr->dzmsr & bit || (i == 6 || i == 7)) { 444 /* carrier present */ 445 if ((tp->t_state & CARR_ON) == 0) { 446 wakeup((caddr_t)&tp->t_rawq); 447 tp->t_state |= CARR_ON; 448 } 449 } else { 450 if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) { 451 /* carrier lost */ 452 if (tp->t_state&ISOPEN) { 453 gsignal(tp->t_pgrp, SIGHUP); 454 gsignal(tp->t_pgrp, SIGCONT); 455 dzaddr->dzdtr &= ~bit; 456 flushtty(tp, FREAD|FWRITE); 457 } 458 tp->t_state &= ~CARR_ON; 459 } 460 } 461 } 462 timeout(dzscan, (caddr_t)0, 2*HZ); 463 } 464 465 dztimer() 466 { 467 468 dzrint(0); 469 } 470 471 /* 472 * Reset state of driver if UBA reset was necessary. 473 * Reset parameters and restart transmission on open lines. 474 */ 475 dzreset(uban) 476 { 477 register int unit; 478 register struct tty *tp; 479 480 /*** WE SHOULD LOOK TO SEE IF WE CARE ABOUT UBA BEING RESET ***/ 481 482 printf(" dz"); 483 for (unit = 0; unit < NDZ; unit++) { 484 tp = &dz_tty[unit]; 485 if (tp->t_state & (ISOPEN|WOPEN)) { 486 dzparam(unit); 487 dzmodem(unit, ON); 488 tp->t_state &= ~BUSY; 489 dzstart(tp); 490 } 491 } 492 dztimer(); 493 } 494 #endif 495