1 /* dz.c 4.23 81/03/09 */ 2 3 #include "dz.h" 4 #if NDZ > 0 5 /* 6 * DZ-11 Driver 7 * 8 * This driver mimics dh.c; see it for explanation of common code. 9 */ 10 #include "bk.h" 11 #include "../h/param.h" 12 #include "../h/systm.h" 13 #include "../h/tty.h" 14 #include "../h/dir.h" 15 #include "../h/user.h" 16 #include "../h/map.h" 17 #include "../h/pte.h" 18 #include "../h/buf.h" 19 #include "../h/vm.h" 20 #include "../h/ubavar.h" 21 #include "../h/conf.h" 22 #include "../h/pdma.h" 23 #include "../h/bk.h" 24 #include "../h/file.h" 25 #include "../h/mx.h" 26 27 /* 28 * Driver information for auto-configuration stuff. 29 */ 30 int dzprobe(), dzattach(), dzrint(); 31 struct uba_device *dzinfo[NDZ]; 32 u_short dzstd[] = { 0 }; 33 struct uba_driver dzdriver = 34 { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo }; 35 36 #define NDZLINE (NDZ*8) 37 38 /* 39 * Registers and bits 40 */ 41 42 /* Bits in dzlpr */ 43 #define BITS7 020 44 #define BITS8 030 45 #define TWOSB 040 46 #define PENABLE 0100 47 #define OPAR 0200 48 49 /* Bits in dzrbuf */ 50 #define DZ_PE 010000 51 #define DZ_FE 020000 52 #define DZ_DO 040000 53 54 /* Bits in dzcsr */ 55 #define DZ_CLR 020 /* Reset dz */ 56 #define DZ_MSE 040 /* Master Scan Enable */ 57 #define DZ_RIE 0100 /* Receiver Interrupt Enable */ 58 #define DZ_SAE 010000 /* Silo Alarm Enable */ 59 #define DZ_TIE 040000 /* Transmit Interrupt Enable */ 60 #define DZ_IEN (DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE) 61 62 /* Flags for modem-control */ 63 #define DZ_ON 1 64 #define DZ_OFF 0 65 66 int dzstart(), dzxint(), dzdma(); 67 int ttrstrt(); 68 struct tty dz_tty[NDZLINE]; 69 int dz_cnt = { NDZLINE }; 70 int dzact; 71 72 struct device { 73 short dzcsr; /* control-status register */ 74 short dzrbuf; /* receiver buffer */ 75 #define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */ 76 char dztcr; /* transmit control register */ 77 char dzdtr; /* data terminal ready */ 78 char dztbuf; /* transmit buffer */ 79 char dzbrk; /* break control */ 80 #define dzmsr dzbrk /* modem status register */ 81 }; 82 /* 83 * Software copy of dzbrk since it isn't readable 84 */ 85 char dz_brk[NDZ]; 86 char dzsoftCAR[NDZ]; 87 88 /* 89 * The dz doesn't interrupt on carrier transitions, so 90 * we have to use a timer to watch it. 91 */ 92 char dz_timer; /* timer started? */ 93 94 /* 95 * Pdma structures for fast output code 96 */ 97 struct pdma dzpdma[NDZLINE]; 98 99 char dz_speeds[] = 100 { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 }; 101 102 dzprobe(reg) 103 caddr_t reg; 104 { 105 register int br, cvec; 106 register struct device *dzaddr = (struct device *)reg; 107 108 #ifdef lint 109 br = 0; cvec = br; br = cvec; 110 #endif 111 dzaddr->dzcsr = DZ_TIE|DZ_MSE; 112 dzaddr->dztcr = 1; /* enable any line */ 113 DELAY(100000); 114 dzaddr->dzcsr = DZ_CLR; /* reset everything */ 115 if (cvec && cvec != 0x200) 116 cvec -= 4; 117 return (1); 118 } 119 120 dzattach(ui) 121 register struct uba_device *ui; 122 { 123 register struct pdma *pdp = &dzpdma[ui->ui_unit*8]; 124 register struct tty *tp = &dz_tty[ui->ui_unit*8]; 125 register int cntr; 126 extern dzscan(); 127 128 for (cntr = 0; cntr < 8; cntr++) { 129 pdp->p_addr = (struct device *)ui->ui_addr; 130 pdp->p_arg = (int)tp; 131 pdp->p_fcn = dzxint; 132 pdp++, tp++; 133 } 134 dzsoftCAR[ui->ui_unit] = ui->ui_flags; 135 if (dz_timer == 0) { 136 dz_timer++; 137 timeout(dzscan, (caddr_t)0, hz); 138 } 139 return (1); 140 } 141 142 /*ARGSUSED*/ 143 dzopen(dev, flag) 144 dev_t dev; 145 { 146 register struct tty *tp; 147 register int unit; 148 149 unit = minor(dev); 150 if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) { 151 u.u_error = ENXIO; 152 return; 153 } 154 tp = &dz_tty[unit]; 155 tp->t_addr = (caddr_t)&dzpdma[unit]; 156 tp->t_oproc = dzstart; 157 tp->t_iproc = NULL; 158 tp->t_state |= WOPEN; 159 if ((tp->t_state & ISOPEN) == 0) { 160 ttychars(tp); 161 tp->t_ospeed = tp->t_ispeed = B300; 162 tp->t_flags = ODDP|EVENP|ECHO; 163 /* tp->t_state |= HUPCLS; */ 164 dzparam(unit); 165 } else if (tp->t_state&XCLUDE && u.u_uid != 0) { 166 u.u_error = EBUSY; 167 return; 168 } 169 dzmodem(unit, DZ_ON); 170 (void) spl5(); 171 while ((tp->t_state & CARR_ON) == 0) { 172 tp->t_state |= WOPEN; 173 sleep((caddr_t)&tp->t_rawq, TTIPRI); 174 } 175 (void) spl0(); 176 (*linesw[tp->t_line].l_open)(dev, tp); 177 } 178 179 /*ARGSUSED*/ 180 dzclose(dev, flag) 181 dev_t dev; 182 { 183 register struct tty *tp; 184 register int unit; 185 int dz; 186 187 unit = minor(dev); 188 dz = unit >> 3; 189 tp = &dz_tty[unit]; 190 (*linesw[tp->t_line].l_close)(tp); 191 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 192 (dz_brk[dz] &= ~(1 << (unit&07))); 193 if (tp->t_state & HUPCLS) 194 dzmodem(unit, DZ_OFF); 195 ttyclose(tp); 196 } 197 198 dzread(dev) 199 dev_t dev; 200 { 201 register struct tty *tp; 202 203 tp = &dz_tty[minor(dev)]; 204 (*linesw[tp->t_line].l_read)(tp); 205 } 206 207 dzwrite(dev) 208 dev_t dev; 209 { 210 register struct tty *tp; 211 212 tp = &dz_tty[minor(dev)]; 213 (*linesw[tp->t_line].l_write)(tp); 214 } 215 216 /*ARGSUSED*/ 217 dzrint(dz) 218 int dz; 219 { 220 register struct tty *tp; 221 register int c; 222 register struct device *dzaddr; 223 register struct tty *tp0; 224 register int unit; 225 int overrun = 0; 226 227 if ((dzact & (1<<dz)) == 0) 228 return; 229 unit = dz * 8; 230 dzaddr = dzpdma[unit].p_addr; 231 tp0 = &dz_tty[unit]; 232 while ((c = dzaddr->dzrbuf) < 0) { /* char present */ 233 tp = tp0 + ((c>>8)&07); 234 if (tp >= &dz_tty[dz_cnt]) 235 continue; 236 if ((tp->t_state & ISOPEN) == 0) { 237 wakeup((caddr_t)&tp->t_rawq); 238 continue; 239 } 240 if (c&DZ_FE) 241 if (tp->t_flags & RAW) 242 c = 0; 243 else 244 c = tun.t_intrc; 245 if (c&DZ_DO && overrun == 0) { 246 printf("dz%d: silo overflow\n", dz); 247 overrun = 1; 248 } 249 if (c&DZ_PE) 250 if (((tp->t_flags & (EVENP|ODDP)) == EVENP) 251 || ((tp->t_flags & (EVENP|ODDP)) == ODDP)) 252 continue; 253 #if NBK > 0 254 if (tp->t_line == NETLDISC) { 255 c &= 0177; 256 BKINPUT(c, tp); 257 } else 258 #endif 259 (*linesw[tp->t_line].l_rint)(c, tp); 260 } 261 } 262 263 /*ARGSUSED*/ 264 dzioctl(dev, cmd, addr, flag) 265 dev_t dev; 266 caddr_t addr; 267 { 268 register struct tty *tp; 269 register int unit = minor(dev); 270 register int dz = unit >> 3; 271 272 tp = &dz_tty[unit]; 273 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 274 if (cmd == 0) 275 return; 276 if (ttioctl(tp, cmd, addr, flag)) { 277 if (cmd==TIOCSETP || cmd==TIOCSETN) 278 dzparam(unit); 279 } else switch(cmd) { 280 281 case TIOCSBRK: 282 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 283 (dz_brk[dz] |= 1 << (unit&07)); 284 break; 285 case TIOCCBRK: 286 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk = 287 (dz_brk[dz] &= ~(1 << (unit&07))); 288 break; 289 case TIOCSDTR: 290 dzmodem(unit, DZ_ON); 291 break; 292 case TIOCCDTR: 293 dzmodem(unit, DZ_OFF); 294 break; 295 default: 296 u.u_error = ENOTTY; 297 } 298 } 299 300 dzparam(unit) 301 register int unit; 302 { 303 register struct tty *tp; 304 register struct device *dzaddr; 305 register int lpr; 306 307 tp = &dz_tty[unit]; 308 dzaddr = dzpdma[unit].p_addr; 309 dzaddr->dzcsr = DZ_IEN; 310 dzact |= (1<<(unit>>3)); 311 if (tp->t_ispeed == 0) { 312 dzmodem(unit, DZ_OFF); /* hang up line */ 313 return; 314 } 315 lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07); 316 if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW)) 317 lpr |= BITS8; 318 else 319 lpr |= (BITS7|PENABLE); 320 if ((tp->t_flags & EVENP) == 0) 321 lpr |= OPAR; 322 if (tp->t_ispeed == B110) 323 lpr |= TWOSB; 324 dzaddr->dzlpr = lpr; 325 } 326 327 dzxint(tp) 328 register struct tty *tp; 329 { 330 register struct pdma *dp; 331 register s; 332 333 s = spl5(); /* block pdma interrupts */ 334 dp = (struct pdma *)tp->t_addr; 335 tp->t_state &= ~BUSY; 336 if (tp->t_state & FLUSH) 337 tp->t_state &= ~FLUSH; 338 else 339 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 340 if (tp->t_line) 341 (*linesw[tp->t_line].l_start)(tp); 342 else 343 dzstart(tp); 344 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0) 345 dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07)); 346 splx(s); 347 } 348 349 dzstart(tp) 350 register struct tty *tp; 351 { 352 register struct pdma *dp; 353 register struct device *dzaddr; 354 register int cc; 355 int s; 356 357 dp = (struct pdma *)tp->t_addr; 358 dzaddr = dp->p_addr; 359 s = spl5(); 360 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) 361 goto out; 362 if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) { 363 tp->t_state &= ~ASLEEP; 364 if (tp->t_chan) 365 mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 366 else 367 wakeup((caddr_t)&tp->t_outq); 368 } 369 if (tp->t_outq.c_cc == 0) 370 goto out; 371 if (tp->t_flags&RAW) 372 cc = ndqb(&tp->t_outq, 0); 373 else { 374 cc = ndqb(&tp->t_outq, 0200); 375 if (cc == 0) { 376 cc = getc(&tp->t_outq); 377 timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6); 378 tp->t_state |= TIMEOUT; 379 goto out; 380 } 381 } 382 tp->t_state |= BUSY; 383 dp->p_end = dp->p_mem = tp->t_outq.c_cf; 384 dp->p_end += cc; 385 dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */ 386 out: 387 splx(s); 388 } 389 390 /* 391 * Stop output on a line. 392 */ 393 /*ARGSUSED*/ 394 dzstop(tp, flag) 395 register struct tty *tp; 396 { 397 register struct pdma *dp; 398 register int s; 399 400 dp = (struct pdma *)tp->t_addr; 401 s = spl5(); 402 if (tp->t_state & BUSY) { 403 dp->p_end = dp->p_mem; 404 if ((tp->t_state&TTSTOP)==0) 405 tp->t_state |= FLUSH; 406 } 407 splx(s); 408 } 409 410 dzmodem(unit, flag) 411 register int unit; 412 { 413 register struct device *dzaddr; 414 register char bit; 415 416 dzaddr = dzpdma[unit].p_addr; 417 bit = 1<<(unit&07); 418 if (flag == DZ_OFF) 419 dzaddr->dzdtr &= ~bit; 420 else 421 dzaddr->dzdtr |= bit; 422 } 423 424 dzscan() 425 { 426 register i; 427 register struct device *dzaddr; 428 register bit; 429 register struct tty *tp; 430 431 for (i = 0; i < dz_cnt ; i++) { 432 dzaddr = dzpdma[i].p_addr; 433 if (dzaddr == 0) 434 continue; 435 tp = &dz_tty[i]; 436 bit = 1<<(i&07); 437 if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) { 438 /* carrier present */ 439 if ((tp->t_state & CARR_ON) == 0) { 440 wakeup((caddr_t)&tp->t_rawq); 441 tp->t_state |= CARR_ON; 442 } 443 } else { 444 if ((tp->t_state&CARR_ON) && 445 (tp->t_local&LNOHANG)==0) { 446 /* carrier lost */ 447 if (tp->t_state&ISOPEN) { 448 gsignal(tp->t_pgrp, SIGHUP); 449 gsignal(tp->t_pgrp, SIGCONT); 450 dzaddr->dzdtr &= ~bit; 451 flushtty(tp, FREAD|FWRITE); 452 } 453 tp->t_state &= ~CARR_ON; 454 } 455 } 456 } 457 timeout(dzscan, (caddr_t)0, 2*hz); 458 } 459 460 dztimer() 461 { 462 int dz; 463 464 for (dz = 0; dz < NDZ; dz++) 465 dzrint(dz); 466 } 467 468 /* 469 * Reset state of driver if UBA reset was necessary. 470 * Reset parameters and restart transmission on open lines. 471 */ 472 dzreset(uban) 473 int uban; 474 { 475 register int unit; 476 register struct tty *tp; 477 register struct uba_device *ui; 478 479 for (unit = 0; unit < NDZLINE; unit++) { 480 ui = dzinfo[unit >> 3]; 481 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0) 482 continue; 483 if (unit%8 == 0) 484 printf(" dz%d", unit>>3); 485 tp = &dz_tty[unit]; 486 if (tp->t_state & (ISOPEN|WOPEN)) { 487 dzparam(unit); 488 dzmodem(unit, DZ_ON); 489 tp->t_state &= ~BUSY; 490 dzstart(tp); 491 } 492 } 493 dztimer(); 494 } 495 #endif 496