1 /* dh.c 4.13 81/02/10 */ 2 3 #include "dh.h" 4 #if NDH11 > 0 5 /* 6 * DH-11 driver 7 * 8 * Loaded with dhdm if there are DM-11's otherwise with dhfdm. 9 * 10 * NB: WE HAVEN'T TESTED dhdm CODE ON VAX. 11 */ 12 13 #include "../h/param.h" 14 #include "../h/conf.h" 15 #include "../h/dir.h" 16 #include "../h/user.h" 17 #include "../h/tty.h" 18 #include "../h/map.h" 19 #include "../h/pte.h" 20 #include "../h/buf.h" 21 #include "../h/uba.h" 22 #include "../h/bk.h" 23 #include "../h/clist.h" 24 #include "../h/mx.h" 25 26 /* This is to block the clock because we are using the silos */ 27 /* SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME */ 28 #define spl5 spl6 29 30 #define UBACVT(x,uban) (cbase[uban] + (short)((x)-(char *)cfree)) 31 32 int dhcntrlr(), dhslave(), dhrint(), dhxint(); 33 struct uba_dinfo *dhinfo[NDH11]; 34 u_short dhstd[] = { 0 }; 35 int (*dhivec[])() = { dhrint, dhxint, 0 }; /* note: order matters */ 36 struct uba_driver dhdriver = 37 { dhcntrlr, dhslave, (int (*)())0, 0, 0, dhstd, dhinfo, dhivec }; 38 39 struct tty dh11[NDH11*16]; 40 int dhact; 41 int dhisilo; 42 int ndh11 = NDH11*16; 43 int dhstart(); 44 int ttrstrt(); 45 int dh_ubinfo[4]; 46 int cbase[4]; 47 48 /* 49 * Hardware control bits 50 */ 51 #define BITS6 01 52 #define BITS7 02 53 #define BITS8 03 54 #define TWOSB 04 55 #define PENABLE 020 56 /* DEC manuals incorrectly say this bit causes generation of even parity. */ 57 #define OPAR 040 58 #define HDUPLX 040000 59 60 #define IENAB 030100 61 #define NXM 02000 62 #define CLRNXM 0400 63 #define PERROR 010000 64 #define FRERROR 020000 65 #define OVERRUN 040000 66 #define XINT 0100000 67 #define SSPEED 7 /* standard speed: 300 baud */ 68 69 /* 70 * DM control bits 71 */ 72 #define TURNON 03 /* CD lead + line enable */ 73 #define TURNOFF 01 /* line enable */ 74 #define DTR 02 /* data terminal ready */ 75 #define RQS 04 /* request to send */ 76 77 /* 78 * Software copy of last dhbar 79 */ 80 short dhsar[NDH11]; 81 82 struct device 83 { 84 union { 85 short dhcsr; 86 char dhcsrl; 87 } un; 88 short dhnxch; 89 short dhlpr; 90 unsigned short dhcar; 91 short dhbcr; 92 unsigned short dhbar; 93 short dhbreak; 94 short dhsilo; 95 }; 96 97 dhcntrlr(ui, reg) 98 struct uba_dinfo *ui; 99 caddr_t reg; 100 { 101 102 ((struct device *)reg)->un.dhcsr |= IENABLE; 103 /* get it to interrupt */ 104 } 105 106 dhslave(ui, reg, slaveno) 107 struct uba_dinfo *ui; 108 caddr_t reg; 109 { 110 111 /* could fill in local tables for the dh here */ 112 } 113 114 /* 115 * Open a DH11 line. 116 */ 117 /*ARGSUSED*/ 118 dhopen(dev, flag) 119 dev_t dev; 120 { 121 register struct tty *tp; 122 register int unit, dh; 123 register struct device *addr; 124 register struct uba_dinfo *ui; 125 int s; 126 127 unit = minor(dev); 128 dh = unit >> 4; 129 if (unit >= NDH11*16 || (ui = dhinfo[dh])->ui_alive == 0) { 130 u.u_error = ENXIO; 131 return; 132 } 133 tp = &dh11[unit]; 134 ui = dhinfo[dh]; 135 addr = (struct device *)ui->ui_addr; 136 tp->t_addr = (caddr_t)addr; 137 tp->t_oproc = dhstart; 138 tp->t_iproc = NULL; 139 tp->t_state |= WOPEN; 140 s = spl6(); 141 if (dh_ubinfo[ui->ui_ubanum]) { 142 /* 512+ is a kludge to try to get around a hardware problem */ 143 dh_ubinfo[ui->ui_ubanum] = 144 uballoc((caddr_t)cfree, 145 512+NCLIST*sizeof(struct cblock), 0); 146 cbase[ui->ui_ubanum] = (short)dh_ubinfo[ui->ui_ubanum]; 147 } 148 splx(s); 149 addr->un.dhcsr |= IENAB; 150 dhact |= (1<<dh); 151 if ((tp->t_state&ISOPEN) == 0) { 152 ttychars(tp); 153 if (tp->t_ispeed == 0) { 154 tp->t_ispeed = SSPEED; 155 tp->t_ospeed = SSPEED; 156 tp->t_flags = ODDP|EVENP|ECHO; 157 } 158 dhparam(unit); 159 } 160 if (tp->t_state&XCLUDE && u.u_uid!=0) { 161 u.u_error = EBUSY; 162 return; 163 } 164 dmopen(dev); 165 (*linesw[tp->t_line].l_open)(dev, tp); 166 } 167 168 /* 169 * Close a DH11 line. 170 */ 171 /*ARGSUSED*/ 172 dhclose(dev, flag) 173 dev_t dev; 174 int flag; 175 { 176 register struct tty *tp; 177 register unit; 178 179 unit = minor(dev); 180 tp = &dh11[unit]; 181 (*linesw[tp->t_line].l_close)(tp); 182 /* 183 * Turn of the break bit in case somebody did a TIOCSBRK without 184 * a TIOCCBRK. 185 */ 186 ((struct device *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); 187 if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0) 188 dmctl(unit, TURNOFF, DMSET); 189 ttyclose(tp); 190 } 191 192 /* 193 * Read from a DH11 line. 194 */ 195 dhread(dev) 196 dev_t dev; 197 { 198 register struct tty *tp; 199 200 tp = &dh11[minor(dev)]; 201 (*linesw[tp->t_line].l_read)(tp); 202 } 203 204 /* 205 * write on a DH11 line 206 */ 207 dhwrite(dev) 208 dev_t dev; 209 { 210 register struct tty *tp; 211 212 tp = &dh11[minor(dev)]; 213 (*linesw[tp->t_line].l_write)(tp); 214 } 215 216 /* 217 * DH11 receiver interrupt. 218 */ 219 dhrint(dh) 220 int dh; 221 { 222 register struct tty *tp; 223 register c; 224 register struct device *addr; 225 register struct tty *tp0; 226 register struct uba_dinfo *ui; 227 int s; 228 229 s = spl6(); /* see comment in clock.c */ 230 ui = dhinfo[dh]; 231 addr = (struct device *)ui->ui_addr; 232 tp0 = &dh11[dh*16]; 233 while ((c = addr->dhnxch) < 0) { /* char. present */ 234 tp = tp0 + ((c>>8)&017); 235 if (tp >= &dh11[NDH11*16]) 236 continue; 237 if((tp->t_state&ISOPEN)==0) { 238 wakeup((caddr_t)tp); 239 continue; 240 } 241 if (c&PERROR) 242 if ((tp->t_flags&(EVENP|ODDP))==EVENP 243 || (tp->t_flags&(EVENP|ODDP))==ODDP ) 244 continue; 245 if (c&OVERRUN) 246 printf("O"); 247 if (c&FRERROR) /* break */ 248 if (tp->t_flags&RAW) 249 c = 0; /* null (for getty) */ 250 else 251 #ifdef IIASA 252 continue; 253 #else 254 c = tun.t_intrc; 255 #endif 256 if (tp->t_line == NETLDISC) { 257 c &= 0177; 258 BKINPUT(c, tp); 259 } else 260 (*linesw[tp->t_line].l_rint)(c,tp); 261 } 262 splx(s); 263 } 264 265 /* 266 * stty/gtty for DH11 267 */ 268 /*ARGSUSED*/ 269 dhioctl(dev, cmd, addr, flag) 270 caddr_t addr; 271 { 272 register struct tty *tp; 273 register unit = minor(dev); 274 275 tp = &dh11[unit]; 276 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr); 277 if (cmd==0) 278 return; 279 if (ttioctl(tp, cmd, addr, flag)) { 280 if (cmd==TIOCSETP||cmd==TIOCSETN) 281 dhparam(unit); 282 } else switch(cmd) { 283 case TIOCSBRK: 284 ((struct device *)(tp->t_addr))->dhbreak |= 1<<(unit&017); 285 break; 286 case TIOCCBRK: 287 ((struct device *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017)); 288 break; 289 case TIOCSDTR: 290 dmctl(unit, DTR|RQS, DMBIS); 291 break; 292 case TIOCCDTR: 293 dmctl(unit, DTR|RQS, DMBIC); 294 break; 295 default: 296 u.u_error = ENOTTY; 297 } 298 } 299 300 /* 301 * Set parameters from open or stty into the DH hardware 302 * registers. 303 */ 304 dhparam(unit) 305 register int unit; 306 { 307 register struct tty *tp; 308 register struct device *addr; 309 register int lpar; 310 int s; 311 312 tp = &dh11[unit]; 313 addr = (struct device *)tp->t_addr; 314 s = spl5(); 315 addr->un.dhcsrl = (unit&017) | IENAB; 316 /* 317 * Hang up line? 318 */ 319 if ((tp->t_ispeed)==0) { 320 tp->t_state |= HUPCLS; 321 dmctl(unit, TURNOFF, DMSET); 322 return; 323 } 324 lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6); 325 if ((tp->t_ispeed) == 4) /* 134.5 baud */ 326 lpar |= BITS6|PENABLE|HDUPLX; 327 else if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT)) 328 lpar |= BITS8; 329 else 330 lpar |= BITS7|PENABLE; 331 if ((tp->t_flags&EVENP) == 0) 332 lpar |= OPAR; 333 if ((tp->t_ospeed) == 3) /* 110 baud */ 334 lpar |= TWOSB; 335 addr->dhlpr = lpar; 336 splx(s); 337 } 338 339 /* 340 * DH11 transmitter interrupt. 341 * Restart each line which used to be active but has 342 * terminated transmission since the last interrupt. 343 */ 344 dhxint(dh) 345 int dh; 346 { 347 register struct tty *tp; 348 register struct device *addr; 349 short ttybit, bar, *sbar; 350 register struct uba_dinfo *ui; 351 register unit; 352 int s; 353 354 s = spl6(); /* block the clock */ 355 ui = dhinfo[dh]; 356 addr = (struct device *)ui->ui_addr; 357 addr->un.dhcsr &= (short)~XINT; 358 if (addr->un.dhcsr & NXM) { 359 addr->un.dhcsr |= CLRNXM; 360 printf("dh clr NXM\n"); 361 } 362 sbar = &dhsar[dh]; 363 bar = *sbar & ~addr->dhbar; 364 unit = dh * 16; ttybit = 1; 365 for(; bar; unit++, ttybit <<= 1) { 366 if(bar&ttybit) { 367 *sbar &= ~ttybit; 368 bar &= ~ttybit; 369 tp = &dh11[unit]; 370 tp->t_state &= ~BUSY; 371 if (tp->t_state&FLUSH) 372 tp->t_state &= ~FLUSH; 373 else { 374 addr->un.dhcsrl = (unit&017)|IENAB; 375 ndflush(&tp->t_outq, 376 (int)(short)addr->dhcar- 377 UBACVT(tp->t_outq.c_cf,ui->ui_ubanum)); 378 } 379 if (tp->t_line) 380 (*linesw[tp->t_line].l_start)(tp); 381 else 382 dhstart(tp); 383 } 384 } 385 splx(s); 386 } 387 388 /* 389 * Start (restart) transmission on the given DH11 line. 390 */ 391 dhstart(tp) 392 register struct tty *tp; 393 { 394 register struct device *addr; 395 register int nch, dh, unit; 396 int s; 397 398 /* 399 * If it's currently active, or delaying, 400 * no need to do anything. 401 */ 402 s = spl5(); 403 unit = minor(tp->t_dev); 404 dh = unit >> 4; 405 addr = (struct device *)tp->t_addr; 406 if (tp->t_state&(TIMEOUT|BUSY|TTSTOP)) 407 goto out; 408 if ((tp->t_state&ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { 409 tp->t_state &= ~ASLEEP; 410 if (tp->t_chan) 411 mcstart(tp->t_chan, (caddr_t)&tp->t_outq); 412 else 413 wakeup((caddr_t)&tp->t_outq); 414 } 415 if (tp->t_outq.c_cc == 0) 416 goto out; 417 if (tp->t_flags & RAW) 418 nch = ndqb(&tp->t_outq, 0); 419 else { 420 nch = ndqb(&tp->t_outq, 0200); 421 if (nch == 0) { 422 nch = getc(&tp->t_outq); 423 timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6); 424 tp->t_state |= TIMEOUT; 425 goto out; 426 } 427 } 428 if (nch) { 429 addr->un.dhcsrl = (unit&017)|IENAB; 430 addr->dhcar = UBACVT(tp->t_outq.c_cf, 431 dhinfo[dh]->ui_ubanum); 432 addr->dhbcr = -nch; 433 nch = 1<<(unit&017); 434 addr->dhbar |= nch; 435 dhsar[dh] |= nch; 436 tp->t_state |= BUSY; 437 } 438 out: 439 splx(s); 440 } 441 442 /* 443 * Stop output on a line. 444 * Assume call is made at spl6. 445 */ 446 /*ARGSUSED*/ 447 dhstop(tp, flag) 448 register struct tty *tp; 449 { 450 register struct device *addr; 451 register int unit, s; 452 453 addr = (struct device *)tp->t_addr; 454 s = spl6(); 455 if (tp->t_state & BUSY) { 456 unit = minor(tp->t_dev); 457 addr->un.dhcsrl = (unit&017) | IENAB; 458 if ((tp->t_state&TTSTOP)==0) 459 tp->t_state |= FLUSH; 460 addr->dhbcr = -1; 461 } 462 splx(s); 463 } 464 465 int dhsilo = 16; 466 /* 467 * Silo control is fixed strategy 468 * here, paralleling only option available 469 * on DZ-11. 470 */ 471 /*ARGSUSED*/ 472 dhtimer() 473 { 474 register int dh; 475 register struct device *addr; 476 register struct uba_dinfo *ui; 477 478 dh = 0; 479 do { 480 ui = dhinfo[dh]; 481 addr = (struct device *)ui->ui_addr; 482 if (dhact & (1<<dh)) { 483 if ((dhisilo & (1<<dh)) == 0) { 484 addr->dhsilo = dhsilo; 485 dhisilo |= 1<<dh; 486 } 487 dhrint(dh); 488 } 489 dh++; 490 } while (dh < NDH11); 491 } 492 493 /* 494 * Reset state of driver if UBA reset was necessary. 495 * Reset the csrl and lpr registers on open lines, and 496 * restart transmitters. 497 */ 498 dhreset(uban) 499 { 500 register int dh, unit; 501 register struct tty *tp; 502 register struct device *addr; 503 register struct uba_dinfo *ui; 504 int uba; 505 506 /*** WE SHOULD LOOK TO SEE IF UBA BEING RESET IS INTERESTING ***/ 507 508 printf(" dh"); 509 dhisilo = 0; 510 for (uba = 0; uba < numuba; uba++) 511 if (dh_ubinfo[uba]) { 512 ubarelse(uba, &dh_ubinfo[uba]); 513 dh_ubinfo[uba] = uballoc(uba, (caddr_t)cfree, 514 512+NCLIST*sizeof (struct cblock), 0); 515 cbase[uba] = (short)dh_ubinfo; 516 } 517 dh = 0; 518 do { 519 if (dhact & (1<<dh)) 520 ((struct device *)dhinfo[dh]->ui_addr)->un.dhcsr |= 521 IENAB; 522 dh++; 523 } while (dh < NDH11); 524 for (unit = 0; unit < NDH11*16; unit++) { 525 tp = &dh11[unit]; 526 if (tp->t_state & (ISOPEN|WOPEN)) { 527 dhparam(unit); 528 dmctl(unit, TURNON, DMSET); 529 tp->t_state &= ~BUSY; 530 dhstart(tp); 531 } 532 } 533 dhtimer(); 534 } 535 536 #if DHDM 537 #include "../dev/dhdm.c" 538 #else 539 #include "../dev/dhfdm.c" 540 #endif 541 #endif 542