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