1 /* vx.c 1.5 86/01/12 */ 2 3 #include "vx.h" 4 #if NVX > 0 5 /* 6 * VIOC-X driver 7 */ 8 #ifdef VXPERF 9 #define DOSCOPE 10 #endif 11 12 #include "../tahoe/pte.h" 13 14 #include "param.h" 15 #include "ioctl.h" 16 #include "tty.h" 17 #include "dir.h" 18 #include "user.h" 19 #include "map.h" 20 #include "buf.h" 21 #include "conf.h" 22 #include "file.h" 23 #include "uio.h" 24 #include "proc.h" 25 #include "vm.h" 26 27 #include "../tahoevba/vbavar.h" 28 #include "../tahoevba/vioc.h" 29 #include "../tahoevba/scope.h" 30 #include "vbsc.h" 31 #if NVBSC > 0 32 #include "../tahoebsc/bscio.h" 33 #include "../tahoebsc/bsc.h" 34 char bscport[NVXPORTS]; 35 #endif 36 37 #ifdef BSC_DEBUG 38 #include "../tahoebsc/bscdebug.h" 39 #endif 40 41 #ifdef VX_DEBUG 42 long vxintr4 = 0; 43 long vxdebug = 0; 44 #include "../tahoevba/vxdebug.h" 45 #endif 46 47 #define RSPquals 1 48 49 struct vcx vcx[NVIOCX] ; 50 struct tty vx_tty[NVXPORTS]; 51 extern struct vcmds v_cmds[]; 52 extern long reinit; 53 54 int vxstart() ; 55 int ttrstrt() ; 56 struct vxcmd *vobtain() ; 57 struct vxcmd *nextcmd() ; 58 59 /* 60 * Driver information for auto-configuration stuff. 61 * (not tested and probably should be changed) 62 */ 63 int vxprobe(), vxattach(), vxrint(); 64 struct vba_device *vxinfo[NVIOCX]; 65 long vxstd[] = { 0 }; 66 struct vba_driver vxdriver = 67 { vxprobe, 0, vxattach, 0, vxstd, "vx", vxinfo }; 68 69 char vxtype[NVIOCX]; /* 0: viox-x/vioc-b; 1: vioc-bop */ 70 char vxbbno = -1; 71 char vxbopno[NVIOCX]; /* BOP board no. if indicated by vxtype[] */ 72 int vxivec[NVIOCX]; /* interrupt vector base */ 73 extern vbrall(); 74 75 vxprobe(reg, vi) 76 caddr_t reg; 77 struct vba_device *vi; 78 { 79 register int br, cvec; /* must be r12, r11 */ 80 register struct vblok *vp = (struct vblok *)reg; 81 82 #ifdef lint 83 br = 0; cvec = br; br = cvec; 84 vackint(0); vunsol(0); vcmdrsp(0); vxfreset(0); 85 #endif 86 if (badaddr((caddr_t)vp, 1)) 87 return (0); 88 vp->v_fault = 0; 89 vp->v_vioc = V_BSY; 90 vp->v_hdwre = V_RESET; /* reset interrupt */ 91 DELAY(4000000); 92 if (vp->v_fault != VREADY) 93 return (0); 94 #ifdef notdef 95 /* 96 * Align vioc interrupt vector base to 4 vector 97 * boundary and fitting in 8 bits (is this necessary, 98 * wish we had documentation). 99 */ 100 if ((vi->ui_hd->vh_lastiv -= 3) > 0xff) 101 vi->ui_hd->vh_lastiv = 0xff; 102 vxivec[vi->ui_unit] = vi->ui_hd->vh_lastiv = 103 vi->ui_hd->vh_lastiv &~ 0x3; 104 #else 105 vxivec[vi->ui_unit] = 0x40+vi->ui_unit*4; 106 #endif 107 br = 0x18, cvec = vxivec[vi->ui_unit]; /* XXX */ 108 return (sizeof (*vp)); 109 } 110 111 vxattach(vi) 112 register struct vba_device *vi; 113 { 114 115 VIOCBAS[vi->ui_unit] = vi->ui_addr; 116 vxinit(vi->ui_unit, (long)1); 117 } 118 119 /* 120 * Open a VX line. 121 */ 122 /*ARGSUSED*/ 123 vxopen(dev, flag) 124 { 125 register struct tty *tp; /* pointer to tty struct for port */ 126 register struct vcx *xp; /* pointer to VIOC-X info/cmd buffer */ 127 register d; /* minor device number */ 128 register long jj; 129 130 131 d = minor(dev); /* get minor device number */ 132 if (d >= NVXPORTS) /* validate minor device number */ 133 return ENXIO; /* set errno to indicate bad port # */ 134 tp = &vx_tty[d]; /* index the tty structure for port */ 135 136 xp = &vcx[d>>4]; /* index VIOC-X info/cmd area */ 137 d &= 017; 138 139 /* If we did not find a board with the correct port number on 140 it, or the entry for the VIOC-X had no ports on it, inform the 141 caller that the port does not exist. */ 142 if(!( xp->v_loport <= d && d <= xp->v_hiport ) /* home? */ 143 || (xp->v_hiport - xp->v_loport)==0) 144 return ENXIO; /* bad minor device number */ 145 tp->t_addr = (caddr_t)xp; /* store address of VIOC-X info */ 146 tp->t_oproc = vxstart; /* store address of startup routine */ 147 tp->t_dev = dev; /* store major/minor device numbers */ 148 d = spl8(); 149 tp->t_state |= TS_WOPEN; /* mark device as waiting for open */ 150 if ((tp->t_state&TS_ISOPEN) == 0) /* is device already open? */ 151 { /* no, open it */ 152 ttychars(tp); /* set default control chars */ 153 if (tp->t_ispeed == 0) /* if no default speeds set them */ 154 { 155 tp->t_ispeed = SSPEED; /* default input baud */ 156 tp->t_ospeed = SSPEED; /* default output baud */ 157 tp->t_flags |= (ODDP|EVENP|ECHO); /* default modes */ 158 } 159 vxparam(dev); /* set parameters for this port */ 160 } 161 splx(d); 162 /* ? if already open for exclusive use open fails unless caller is 163 root. */ 164 if (tp->t_state&TS_XCLUDE && u.u_uid!=0) 165 return EBUSY; /* device is busy, sorry */ 166 167 /* wait for data carrier detect to go high */ 168 d = spl8(); 169 if( !vcmodem(dev,VMOD_ON) ) 170 while( (tp->t_state&TS_CARR_ON) == 0 ) 171 sleep((caddr_t)&tp->t_canq,TTIPRI); 172 jj= (*linesw[tp->t_line].l_open)(dev,tp); /*let tty.c finish the open */ 173 splx(d); /* 1/2/85 : assures open complete */ 174 return (jj); 175 } 176 177 /* 178 * Close a VX line. 179 */ 180 /*ARGSUSED*/ 181 vxclose(dev, flag) 182 dev_t dev; 183 int flag; 184 { 185 register struct tty *tp; 186 register d; 187 188 d = minor(dev) & 0377; 189 tp = &vx_tty[d]; 190 d = spl8(); 191 (*linesw[tp->t_line].l_close)(tp); 192 if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_HUPCLS)) 193 if( !vcmodem(dev,VMOD_OFF) ) 194 tp->t_state &= ~TS_CARR_ON; 195 /* wait for the last response */ 196 while(tp->t_state & TS_FLUSH) 197 sleep( (caddr_t)&tp->t_state, TTOPRI ) ; 198 ttyclose(tp); /* let tty.c finish the close */ 199 splx(d); 200 } 201 202 /* 203 * Read from a VX line. 204 */ 205 vxread(dev, uio) 206 dev_t dev; 207 struct uio *uio; 208 { 209 register struct tty *tp = &vx_tty[minor(dev) & 0377]; 210 return (*linesw[tp->t_line].l_read)(tp, uio); 211 } 212 213 /* 214 * write on a VX line 215 */ 216 vxwrite(dev, uio) 217 dev_t dev; 218 struct uio *uio; 219 { 220 register struct tty *tp = &vx_tty[minor(dev) & 0377]; 221 return (*linesw[tp->t_line].l_write)(tp, uio); 222 } 223 224 /* 225 * VIOCX unsolicited interrupt. 226 */ 227 vxrint(n) 228 register n; /* mux number */ 229 { 230 register struct tty *tp; 231 register struct vcx *xp; 232 register short *sp; 233 register struct vblok *kp; 234 register int i, c; 235 short *savsilo; 236 struct silo { 237 char data; 238 char port; 239 }; 240 241 kp = VBAS(n); 242 xp = &vcx[n]; 243 switch(kp->v_uqual&037) { 244 case 0: 245 break; 246 case 2: 247 printf(" ERR NBR %x\n",kp->v_ustat); 248 vpanic("vc: VC PROC ERR"); 249 vxstreset(n); 250 return(0); 251 case 3: 252 vcmintr(n); 253 return(1); 254 case 4: 255 return(1); 256 default: 257 printf(" ERR NBR %x\n",kp->v_uqual); 258 vpanic("vc: VC UQUAL ERR"); 259 vxstreset(n); 260 return(0); 261 } 262 if(xp->v_vers == V_NEW) { 263 register short *aa ; 264 aa = (short *)kp->v_usdata; 265 sp = (short *)(*aa + (char *)kp) ; 266 } else { 267 c = kp->v_usdata[0] << 6; 268 sp = (short *)((char *)kp + SILOBAS + c); 269 } 270 i = *(savsilo = sp); 271 if (i == 0) return(1); 272 if(xp->v_vers == V_NEW) 273 if( i > xp->v_silosiz ) { 274 printf("vx: %d exceeds silo size\n",i) ; 275 i = xp->v_silosiz; 276 } 277 for(sp++;i > 0;i--,sp++) { 278 c = ((struct silo *)sp)->port & 017; 279 tp = &vx_tty[c+n*16]; 280 if(xp->v_loport > c || c > xp->v_hiport) 281 continue; /* port out of bounds */ 282 if( (tp->t_state & TS_ISOPEN) == 0) { 283 wakeup((caddr_t)&tp->t_rawq); 284 continue; 285 } 286 c = ((struct silo *)sp)->data; 287 switch(((struct silo *)sp)->port&(PERROR|FERROR)) { 288 case PERROR: 289 case PERROR|FERROR: 290 if( (tp->t_flags&(EVENP|ODDP)) == EVENP 291 || (tp->t_flags & (EVENP|ODDP)) == ODDP ) 292 continue; 293 if(!(((struct silo *)sp)->port&FERROR)) 294 break; 295 case FERROR: 296 if(tp->t_flags & RAW) c = 0; 297 else c = tp->t_intrc; 298 } 299 (*linesw[tp->t_line].l_rint)(c, tp); 300 } 301 *savsilo = 0; 302 return(1); 303 } 304 305 /* 306 * stty/gtty for VX 307 */ 308 vxioctl(dev, cmd, data, flag) 309 int dev; /* major, minor device numbers */ 310 int cmd; /* command */ 311 caddr_t data; 312 int flag; 313 { 314 register struct tty *tp; 315 register error; 316 317 tp = &vx_tty[minor(dev) & 0377]; 318 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 319 if (error == 0) 320 return error; 321 if((error = ttioctl(tp, cmd, data, flag)) >= 0) 322 { 323 if (cmd==TIOCSETP||cmd==TIOCSETN) 324 vxparam(dev); 325 return error; 326 } else 327 return ENOTTY; 328 } 329 330 331 vxparam(dev) 332 dev_t dev; 333 { 334 vxcparam(dev, 1); 335 } 336 337 /* 338 * Set parameters from open or stty into the VX hardware 339 * registers. 340 */ 341 vxcparam(dev, wait) 342 dev_t dev; /* major, minor device numbers */ 343 int wait; /* nonzero if we should wait for finish */ 344 { 345 register struct tty *tp; 346 register struct vcx *xp; 347 register struct vxcmd *cp; 348 register s; 349 350 tp = &vx_tty[minor(dev)]; /* pointer to tty structure for port */ 351 xp = (struct vcx *)tp->t_addr; /* pointer to VIOCX info/cmd buffer */ 352 cp = vobtain(xp); 353 s = spl8(); 354 cp->cmd = LPARAX; /* set command to "load parameters" */ 355 cp->par[1] = minor(dev)&017; /* port number */ 356 357 cp->par[2] = (tp->t_flags&RAW)? 0 : tp->t_startc; /* XON char */ 358 cp->par[3] = (tp->t_flags&RAW)? 0 : tp->t_stopc; /* XOFF char */ 359 360 if(tp->t_flags&(RAW|LITOUT) || 361 (tp->t_flags&(EVENP|ODDP)) == (EVENP|ODDP)) { 362 cp->par[4] = 0xc0; /* 8 bits of data */ 363 cp->par[7] = 0; /* no parity */ 364 } else { 365 cp->par[4] = 0x40; /* 7 bits of data */ 366 if((tp->t_flags&(EVENP|ODDP)) == ODDP) 367 cp->par[7] = 1; /* odd parity */ 368 else if((tp->t_flags&(EVENP|ODDP)) == EVENP) 369 cp->par[7] = 3; /* even parity */ 370 else 371 cp->par[7] = 0; /* no parity */ 372 } 373 cp->par[5] = 0x4; /* 1 stop bit */ 374 cp->par[6] = tp->t_ospeed; 375 376 if (vcmd(xp->v_nbr, (caddr_t)&cp->cmd) && wait) 377 sleep((caddr_t)cp,TTIPRI); 378 splx(s); 379 } 380 381 /* 382 * VIOCX command response interrupt. 383 * For transmission, restart output to any active port. 384 * For all other commands, just clean up. 385 */ 386 vxxint(n,cp) 387 register int n; /* VIOC number */ 388 register struct vxcmd *cp; /* command structure */ 389 { 390 register struct vxmit *vp, *pvp; 391 register struct tty *tp; 392 register struct vcx *xp; 393 register struct tty *hp; 394 395 xp = &vcx[n]; 396 cp = (struct vxcmd *)( (long *)cp - 1); 397 #if NVBSC > 0 398 switch(cp->cmd) { 399 case MDMCTL1: case HUNTMD1: case LPARAX1: 400 vrelease(xp, cp); 401 wakeup(cp); 402 return; 403 } 404 #endif 405 switch(cp->cmd&0xff00) { 406 case LIDENT: /* initialization complete */ 407 if (xp->v_state & V_RESETTING) { 408 vxfnreset(n,cp); 409 vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR); 410 } 411 cp->cmd++; 412 return; 413 case XMITDTA: case XMITIMM: 414 break; 415 case LPARAX: 416 wakeup((caddr_t)cp); 417 default: /* MDMCTL or FDTATOX */ 418 vrelease(xp, cp); 419 if (xp->v_state & V_RESETTING) { 420 vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR); 421 } 422 return; 423 } 424 for(vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizvxmit); 425 vp >= (struct vxmit *)cp->par; 426 vp = (struct vxmit *) ((char *)vp - sizvxmit) ) 427 { 428 tp = &vx_tty[(vp->line & 017)+n*16]; 429 /* cjk buffer bug */ 430 #if NVBSC > 0 431 /* bsc change */ 432 if (tp->t_line == LDISP) { 433 vrelease(xp, cp); 434 bsctxd((vp->line & 017)); 435 return ; 436 } 437 /* End of bsc change */ 438 #endif 439 /* cjk */ 440 pvp = vp; 441 tp->t_state &= ~TS_BUSY; 442 if(tp->t_state & TS_FLUSH) { 443 tp->t_state &= ~TS_FLUSH; 444 wakeup( (caddr_t)&tp->t_state ) ; 445 } 446 else 447 ndflush(&tp->t_outq, vp->bcount+1); 448 } 449 xp->v_xmtcnt--; 450 vrelease(xp,cp); 451 if(xp->v_vers == V_NEW) { 452 vp = pvp; 453 xp->v_actport[(vp->line & 017) - xp->v_loport] |= 1 ; 454 if(vxstart(tp) && (cp = nextcmd(xp)) != NULL) 455 { 456 xp->v_xmtcnt++; 457 vcmd(n, (caddr_t)&cp->cmd); 458 return ; 459 } 460 xp->v_actport[(vp->line & 017) - xp->v_loport] = 0 ; 461 return ; 462 } 463 xp->v_actflg = 1; 464 hp = &vx_tty[xp->v_hiport+n*16]; 465 for(tp = &vx_tty[xp->v_loport+n*16];tp <= hp;tp++) 466 if(vxstart(tp) && (cp = nextcmd(xp)) != NULL) 467 { 468 xp->v_xmtcnt++; 469 vcmd(n, (caddr_t)&cp->cmd); 470 } 471 if( (cp = nextcmd(xp)) != NULL ) /* command to send ? */ 472 { 473 xp->v_xmtcnt++; 474 vcmd(n, (caddr_t)&cp->cmd); 475 } 476 xp->v_actflg = 0; 477 } 478 479 /* 480 * Force out partial XMIT command after timeout 481 */ 482 vxforce(xp) 483 register struct vcx *xp; 484 { 485 register struct vxcmd *cp; 486 register int s; 487 488 s = spl8(); 489 if((cp = nextcmd(xp)) != NULL) { 490 xp->v_xmtcnt++; 491 vcmd(xp->v_nbr, (caddr_t)&cp->cmd); 492 } 493 splx(s); 494 } 495 496 /* 497 * Start (restart) transmission on the given VX line. 498 */ 499 vxstart(tp) 500 register struct tty *tp; 501 { 502 register short n; 503 register struct vcx *xp; 504 register char *outb; 505 register full = 0; 506 int k, s, port; 507 508 s = spl8(); 509 port = minor(tp->t_dev) & 017; 510 xp = (struct vcx *)tp->t_addr; 511 if (!(tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) { 512 if (tp->t_outq.c_cc<=TTLOWAT(tp)) { 513 if (tp->t_state&TS_ASLEEP) { 514 tp->t_state &= ~TS_ASLEEP; 515 wakeup((caddr_t)&tp->t_outq); 516 } 517 if (tp->t_wsel) { 518 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 519 tp->t_wsel = 0; 520 tp->t_state &= ~TS_WCOLL; 521 } 522 } 523 if(tp->t_outq.c_cc == 0) { 524 splx(s); 525 return(0); 526 } 527 scope_out(3); 528 if(!(tp->t_flags&(RAW|LITOUT))) 529 full = 0200; 530 if((n = ndqb(&tp->t_outq, full)) == 0) { 531 if(full) { 532 n = getc(&tp->t_outq); 533 timeout(ttrstrt, (caddr_t)tp, (n&0177) +6); 534 tp->t_state |= TS_TIMEOUT; 535 full = 0; 536 } 537 } else { 538 outb = (char *)tp->t_outq.c_cf; 539 tp->t_state |= TS_BUSY; 540 if(xp->v_vers == V_NEW) 541 k = xp->v_actport[port - xp->v_loport] ; 542 else 543 k = xp->v_actflg ; 544 545 full = vsetq(xp, port, outb, n); 546 547 if( (k&1) == 0 ) { /* not called from vxxint */ 548 if(full || xp->v_xmtcnt == 0) { 549 outb = (char *)(&nextcmd(xp)->cmd); 550 xp->v_xmtcnt++; 551 vcmd(xp->v_nbr, outb ); 552 } else 553 timeout(vxforce,(caddr_t)xp,3); 554 } 555 } 556 } 557 splx(s); 558 return(full); /* indicate if max commands or not */ 559 } 560 561 /* 562 * Stop output on a line. 563 */ 564 vxstop(tp) 565 register struct tty *tp; 566 { 567 register s; 568 569 s = spl8(); 570 if (tp->t_state & TS_BUSY) { 571 if ((tp->t_state&TS_TTSTOP)==0) { 572 tp->t_state |= TS_FLUSH; 573 } 574 } 575 splx(s); 576 } 577 578 /* 579 * VIOCX Initialization. Makes free lists of command buffers. 580 * Resets all viocx's. Issues a LIDENT command to each 581 * viocx which establishes interrupt vectors and logical 582 * port numbers 583 */ 584 vxinit(i,wait) 585 register int i; 586 long wait; 587 { 588 register struct vcx *xp; /* ptr to VIOC-X info/cmd buffer */ 589 register struct vblok *kp; /* pointer to VIOC-X control block */ 590 register struct vxcmd *cp; /* pointer to a command buffer */ 591 register char *resp; /* pointer to response buffer */ 592 register int j; 593 char type; 594 #if NVBSC > 0 595 register struct bsc *bp; /* bsc change */ 596 extern struct bsc bsc[]; 597 #endif 598 599 600 kp = VBAS(i); /* get base adr of cntl blok for VIOC */ 601 602 xp = &vcx[i]; /* index info/command buffers */ 603 type = kp->v_ident; 604 vxtype[i] = 0; /* Type is Viox-x */ 605 switch(type) { 606 case VIOCX: 607 { 608 xp->v_vers = V_OLD ; 609 /* set DCD for printer ports */ 610 for(j = 0;j < 16;j++) 611 if (kp->v_portyp[j] == 4 ) 612 kp->v_dcd |= 1 << j ; 613 } 614 break ; 615 case NWVIOCX: 616 { 617 xp->v_vers = V_NEW ; 618 xp->v_silosiz = kp->v_maxsilo ; 619 /* set DCD for printer ports */ 620 for(j = 0;j < 16;j++) 621 if (kp->v_portyp[j] == 4 ) 622 kp->v_dcd |= 1 << j ; 623 } 624 break ; 625 case PVIOCX: 626 xp->v_vers = V_OLD ; 627 break ; 628 case NPVIOCX: 629 xp->v_vers = V_NEW ; 630 xp->v_silosiz = kp->v_maxsilo ; 631 break ; 632 #if NVBSC > 0 633 case VIOCB: /* old f/w, Bisync board */ 634 printf("%X: %x%x OLD VIOC-B, ", 635 (long)kp, (int)kp->v_ident, 636 (int)kp->v_fault); 637 xp->v_vers = V_OLD ; 638 /* save device specific info */ 639 for(bp = &bsc[0]; bp <= &bsc[NBSC]; bp++) 640 bp->b_devregs = (caddr_t)xp ; 641 printf("%d BSC Ports initialized.\n",NBSC); 642 break ; 643 644 case NWVIOCB: /* new f/w, Bisync board */ 645 printf("%X: %x%x 16K VIOC-B, ", 646 (long)kp, (int)kp->v_ident, 647 (int)kp->v_fault); 648 xp->v_vers = V_NEW ; 649 xp->v_silosiz = kp->v_maxsilo ; 650 /* save device specific info */ 651 for(bp = &bsc[0]; bp <= &bsc[NBSC]; bp++) 652 bp->b_devregs = (caddr_t)xp ; 653 printf("%d BSC Ports initialized.\n",NBSC); 654 if(CBSIZE > kp->v_maxxmt) 655 printf("vxinit: Warning CBSIZE > maxxmt\n") ; 656 break ; 657 #endif 658 case VBOPID: /* VIOC-BOP */ 659 vxbbno++; 660 vxtype[i] = 1; 661 vxbopno[i] = vxbbno; 662 printf("VIOC-BOP no. %d at %lx\n",vxbopno[i],VIOCBAS[i]); 663 default: 664 return ; /* Not a viocx type */ 665 } 666 xp->v_nbr = -1; /* no number for it yet */ 667 xp->v_maxcmd = xp->v_vers == V_NEW ? 24 : 4; 668 669 for(j=0; j<NVCXBUFS; j++) /* init all cmd buffers */ 670 { 671 cp = &xp->vx_lst[j]; /* index a buffer */ 672 cp->c_fwd = &xp->vx_lst[j+1]; /* point to next buf */ 673 } 674 xp->vx_avail = &xp->vx_lst[0]; /* set idx to 1st free buf */ 675 cp->c_fwd = (struct vxcmd *)0; /* mark last buf in free list */ 676 677 cp = vobtain(xp); /* grap the control block */ 678 cp->cmd = LIDENT; /* set command type */ 679 cp->par[0] = vxivec[i]; /* ack vector */ 680 cp->par[1] = cp->par[0]+1; /* cmd resp vector */ 681 cp->par[3] = cp->par[0]+2; /* unsol intr vector */ 682 cp->par[4] = 15; /* max ports, no longer used */ 683 cp->par[5] = 0; /* set 1st port number */ 684 vcmd(i, (caddr_t)&cp->cmd); /* initialize the VIOC-X */ 685 686 if (!wait) return; 687 for (j = 0; cp->cmd == LIDENT && j < 4000000; j++) 688 ; 689 if (j >= 4000000) 690 printf("vx%d: didn't respond to LIDENT\n", i); 691 692 /* calculate address of response buffer */ 693 resp = (char *)kp; 694 resp += kp->v_rspoff & 0x3FFF; 695 696 if(resp[0] != 0 && (resp[0]&0177) != 3) /* did init work? */ 697 { 698 vrelease(xp,cp); /* init failed */ 699 return; /* try next VIOC-X */ 700 } 701 702 xp->v_loport = cp->par[5]; /* save low port number */ 703 xp->v_hiport = cp->par[7];/* VIOC knows high port numbr */ 704 vrelease(xp,cp); /* done with this control block */ 705 xp->v_nbr = i; /* assign VIOC-X board number */ 706 } 707 708 /* 709 * Obtain a command buffer 710 */ 711 struct vxcmd * 712 vobtain(xp) 713 register struct vcx *xp; 714 { 715 716 register struct vxcmd *p; 717 register s; 718 719 s = spl8(); 720 p = xp->vx_avail; 721 if(p == (struct vxcmd *)0) { 722 #ifdef VX_DEBUG 723 if (vxintr4 & VXNOBUF) vxintr4 &= ~VXNOBUF; 724 #endif 725 vpanic("vx: no buffs"); 726 vxstreset(xp - vcx); 727 splx(s); 728 return(vobtain(xp)); 729 } 730 xp->vx_avail = (xp->vx_avail)->c_fwd; 731 splx(s); 732 return( (struct vxcmd *)p); 733 } 734 735 /* 736 * Release a command buffer 737 */ 738 vrelease(xp,cp) 739 register struct vcx *xp; 740 register struct vxcmd *cp; 741 { 742 743 register s; 744 745 #ifdef VX_DEBUG 746 if (vxintr4 & VXNOBUF) return; 747 #endif 748 s = spl8(); 749 cp->c_fwd = xp->vx_avail; 750 xp->vx_avail = cp; 751 splx(s); 752 } 753 754 /* 755 * vxcmd - 756 * 757 */ 758 struct vxcmd * 759 nextcmd(xp) 760 register struct vcx *xp; 761 { 762 register struct vxcmd *cp; 763 register int s; 764 765 s = spl8(); 766 cp = xp->vx_build; 767 xp->vx_build = (struct vxcmd *)0; 768 splx(s); 769 return(cp); 770 } 771 772 /* 773 * assemble transmits into a multiple command. 774 * up to 8 transmits to 8 lines can be assembled together 775 */ 776 vsetq(xp ,d ,addr, n) 777 register struct vcx *xp; 778 caddr_t addr; 779 { 780 781 register struct vxcmd *cp; 782 register struct vxmit *mp; 783 register char *p; 784 register i; 785 786 cp = xp->vx_build; 787 if(cp == (struct vxcmd *)0) { 788 cp = vobtain(xp); 789 xp->vx_build = cp; 790 cp->cmd = XMITDTA; 791 } else { 792 if((cp->cmd & 07) == 07) { 793 vpanic("vx: vsetq overflow"); 794 vxstreset(xp->v_nbr); 795 return(0); 796 } 797 cp->cmd++; 798 } 799 800 mp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizvxmit); 801 mp->bcount = n-1; 802 803 mp->line = d; 804 if((xp->v_vers == V_NEW) && (n <= 6)) { 805 cp->cmd = XMITIMM ; 806 p = addr; 807 /* bcopy(addr, &(char *)mp->ostream, n) ; */ 808 } else { 809 addr = (caddr_t)vtoph((struct proc *)0, (unsigned)addr); 810 /* should be a sys address */ 811 p = (char *)&addr; 812 n = sizeof addr; 813 /* mp->ostream = addr ; */ 814 } 815 for(i=0; i<n; i++) 816 mp->ostream[i] = *p++; 817 if(xp->v_vers == V_NEW) 818 return(1) ; 819 else 820 return((cp->cmd&07) == 7) ; /* Indicate if full */ 821 } 822 #endif 823