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