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