--- cci/sys/vba/vcx.c 2019/07/28 12:24:19 1.1 +++ cci/sys/vba/vcx.c 2019/07/28 12:30:10 1.1.1.2 @@ -20,56 +20,46 @@ #ifdef VXPERF #include "../vba/scope.h" #endif VXPERF + #include "vbsc.h" #if NVBSC > 0 #include "../bsc/bscio.h" #include "../bsc/bsc.h" char bscport[NVXPORTS]; long bscno = 0; -#endif - -#ifdef BSC_DEBUG -#include "../bsc/bscdebug.h" -#endif - -#ifdef VX_DEBUG -long vxintr4 = 0; -long vxdebug = 0; -#include "../vba/vxdebug.h" +extern struct bsc bsc[]; #endif #define RSPquals 1 -struct vcx vcx[NVIOCX] ; -struct tty vx_tty[NVXPORTS]; -extern struct vcmds v_cmds[]; -extern long reinit; +struct vcx vcx[NVIOCX]; +struct tty vx_tty[NVXPORTS]; +extern struct vcmds v_cmds[]; +struct vba_device *vxinfo[NVIOCX]; -int vxstart() ; -int ttrstrt() ; +int vxstart(); +int ttrstrt(); caddr_t vtoph(); -struct vxcmd *vobtain() ; -struct vxcmd *nextcmd() ; +struct vxcmd *vobtain(); /* * Driver information for auto-configuration stuff. * (not tested and probably should be changed) */ int vxprobe(), vxattach(), vxrint(); -struct vba_device *vxinfo[NVIOCX]; long vxstd[] = { 0 }; struct vba_driver vxdriver = { vxprobe, 0, vxattach, 0, vxstd, "VIOC ", vxinfo }; char vxtype[NVIOCX]; /* 0: viox-x/vioc-b; 1: vioc-bop */ -char vxbbno = -1; char vxbopno[NVIOCX]; /* BOP board no. if indicated by vxtype[] */ +char vxbbno = -1; short vbtbl = -1; +int vx_cnt = NVXPORTS; /* needed by vmstat/iostat */ extern vbrall(); - vxprobe(reg) - caddr_t reg; +caddr_t reg; { register int br, cvec; register struct vblok *vp = (struct vblok *)reg; @@ -78,21 +68,23 @@ vxprobe(reg) br = 0; cvec = br; br = cvec; #endif - if(badaddr(vp, 1)) + if (badaddr(vp, 1)) return(0); - vp->v_fault = 0 ; - vp->v_vioc = V_BSY ; - vp->v_hdwre = V_RESET ; /* reset interrupt */ + vp->v_fault = 0; + vp->v_vioc = V_BSY; + vp->v_hdwre = V_RESET; /* reset interrupt */ DELAY(4000000); - return ( vp->v_fault == VREADY); + if (vp->v_fault != VREADY) + return(0); + return(1); } vxattach(ui) - register struct vba_device *ui; +register struct vba_device *ui; { VIOCBAS[ui->ui_unit] = ui->ui_addr; - vxinit(ui->ui_unit,1); + vxinit(ui->ui_unit, 1); } /* @@ -102,54 +94,72 @@ vxopen(dev, flag) { register struct tty *tp; /* pointer to tty struct for port */ register struct vcx *xp; /* pointer to VIOC-X info/cmd buffer */ - register d; /* minor device number */ - register long jj; - + register int d; /* minor device number */ + register int error; d = minor(dev); /* get minor device number */ if (d >= NVXPORTS) /* validate minor device number */ - return ENXIO; /* set errno to indicate bad port # */ + return(ENXIO); /* set errno to indicate bad port # */ tp = &vx_tty[d]; /* index the tty structure for port */ - xp = &vcx[d>>4]; /* index VIOC-X info/cmd area */ + xp = &vcx[d>>4]; /* index VIOC-X info/cmd area */ d &= 017; - /* If we did not find a board with the correct port number on - it, or the entry for the VIOC-X had no ports on it, inform the - caller that the port does not exist. */ - if(!( xp->v_loport <= d && d <= xp->v_hiport ) /* home? */ - || (xp->v_hiport - xp->v_loport)==0) - return ENXIO; /* bad minor device number */ - tp->t_addr = (caddr_t)xp; /* store address of VIOC-X info */ - tp->t_oproc = vxstart; /* store address of startup routine */ - tp->t_dev = dev; /* store major/minor device numbers */ - d = spl8(); - tp->t_state |= TS_WOPEN; /* mark device as waiting for open */ - if ((tp->t_state&TS_ISOPEN) == 0) /* is device already open? */ - { /* no, open it */ + /* + * If we are resetting the VIOC, wait until the LIDENT has + * completed. + */ + while (xp->v_state&V_RESETTING) + sleep((caddr_t)&xp->v_state); + + if (xp->v_hiport == xp->v_loport || /* no ports on this board */ + d < xp->v_loport || d > xp->v_hiport)/* not in the range of ports */ + return(ENXIO); /* bad minor device number */ + + if (isprinter(xp, d)) + /* + * Printers have different semantics than tty ports. + * They have a fixed output transliteration, no read, + * only one process may open them at a time, they always + * have carrier and processes cannot be attached to them. + */ + if (tp->t_state&TS_ISOPEN) + return(EBUSY); + + if ((tp->t_state&(TS_ISOPEN|TS_WOPEN))==0){/* is device already open? */ ttychars(tp); /* set default control chars */ - if (tp->t_ispeed == 0) /* if no default speeds set them */ - { - tp->t_ispeed = SSPEED; /* default input baud */ - tp->t_ospeed = SSPEED; /* default output baud */ + tp->t_addr = (caddr_t)xp;/* store addr of VIOC-X info */ + tp->t_oproc = vxstart; /* store address of startup routine */ + tp->t_dev = dev; /* store major/minor device numbers */ + if (tp->t_ispeed == 0) {/* if no default speeds set them */ + tp->t_ispeed = SSPEED;/* default input baud */ + tp->t_ospeed = SSPEED;/* default output baud */ tp->t_flags |= (ODDP|EVENP|ECHO); /* default modes */ } vxparam(dev); /* set parameters for this port */ } - splx(d); - /* ? if already open for exclusive use open fails unless caller is - root. */ + /* + * If already open for exclusive use open fails unless caller is root. + */ if (tp->t_state&TS_XCLUDE && u.u_uid!=0) - return EBUSY; /* device is busy, sorry */ + return(EBUSY); /* device is busy, sorry */ - /* wait for data carrier detect to go high */ d = spl8(); - if( !vcmodem(dev,VMOD_ON) ) - while( (tp->t_state&TS_CARR_ON) == 0 ) - sleep(&tp->t_canq,TTIPRI); - jj= (*linesw[tp->t_line].l_open)(dev,tp); /*let tty.c finish the open */ - splx(d); /* 1/2/85 : assures open complete */ - return (jj); + tp->t_state |= TS_WOPEN; /* mark device as waiting for open */ + /* + * Check for carrier + */ + if (vcmodem(dev, VMOD_ON)) + tp->t_state |= TS_CARR_ON; + else + tp->t_state &= ~TS_CARR_ON; + while ((tp->t_state&TS_CARR_ON) == 0) { + tp->t_state |= TS_WOPEN; + sleep(&tp->t_canq, TTIPRI); + } + error = (*linesw[tp->t_line].l_open)(dev, tp);/*let tty.c finish open */ + splx(d); + return(error); } /* @@ -159,60 +169,80 @@ vxclose(dev, flag) dev_t dev; int flag; { - register struct tty *tp; - register d; - - d = minor(dev) & 0377; - tp = &vx_tty[d]; - d = spl8(); - (*linesw[tp->t_line].l_close)(tp); - if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_HUPCLS)) - if( !vcmodem(dev,VMOD_OFF) ) - tp->t_state &= ~TS_CARR_ON; - /* wait for the last response */ - while(tp->t_state & TS_FLUSH) - sleep( (caddr_t)&tp->t_state, TTOPRI ) ; + register int d = minor(dev); + register struct tty *tp = &vx_tty[d]; + register int s = spl8(); + register int error; + + error = (*linesw[tp->t_line].l_close)(tp); + if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_HUPCLS)) { + register int flags = tp->t_flags; + + /* + ** Turn off echo to prevent infinite flushing + ** Flush output queue then turn off clear to send. + ** Always restore flags so line disipline will not change. + */ + tp->t_flags &= ~ECHO; + ttywait(tp); + tp->t_flags = flags; + vcmodem(dev, VMOD_OFF); + } + while ((tp->t_state&TS_FLUSH) && (tp->t_state&TS_BUSY)) + sleep((caddr_t)&tp->t_state, TTOPRI); ttyclose(tp); /* let tty.c finish the close */ - splx(d); + splx(s); + return(error); } /* * Read from a VX line. */ vxread(dev, uio) - dev_t dev; - struct uio *uio; +dev_t dev; +struct uio *uio; { - register struct tty *tp = &vx_tty[minor(dev) & 0377]; - return (*linesw[tp->t_line].l_read)(tp, uio); + register int d = minor(dev); + register struct tty *tp = &vx_tty[d]; + register struct vcx *xp = &vcx[d>>4]; + + d &= 0xf; + if (isprinter(xp, d)) + return(ENODEV); + return(*linesw[tp->t_line].l_read)(tp, uio); } /* - * write on a VX line + * Write on a VX line. */ vxwrite(dev, uio) - dev_t dev; - struct uio *uio; +dev_t dev; +struct uio *uio; { - register struct tty *tp = &vx_tty[minor(dev) & 0377]; - return (*linesw[tp->t_line].l_write)(tp, uio); + register int d = minor(dev); + register struct tty *tp = &vx_tty[d]; + + return(*linesw[tp->t_line].l_write)(tp, uio); } /* * VIOCX unsolicited interrupt. */ vxrint(n) -register n; /* mux number */ +int n; /* mux number */ { register struct tty *tp; register struct vcx *xp; register short *sp; - register struct vblok *kp; - register int i, c; + register int i; + register unsigned int c; + register int port; + struct tty *tp0; + struct vblok *kp; short *savsilo; struct silo { - char data; - char port; + char data; + unsigned char port; }; kp = VBAS(n); @@ -225,12 +255,16 @@ register n; /* mux number */ c = 5; switch (c) { #else - switch(kp->v_uqual&037) { + switch (kp->v_uqual&037) { #endif case 0: break; case 2: - printf(" ERR NBR %x\n",kp->v_ustat); + printf(" ERR NBR %x\n", kp->v_ustat); + if (kp->v_ustat == 0x40) { + printf("VIOC %x lost some read data\n", n); + return(0); + } vpanic("vc: VC PROC ERR"); vxstreset(n); return(0); @@ -240,48 +274,66 @@ register n; /* mux number */ case 4: return(1); default: - printf(" ERR NBR %x\n",kp->v_uqual); + printf(" ERR NBR %x\n", kp->v_uqual); vpanic("vc: VC UQUAL ERR"); vxstreset(n); return(0); } - if(xp->v_vers == V_NEW) { - register short *aa ; - aa = (short *)kp->v_usdata; - sp = (short *)(*aa + (char *)kp) ; - } else { - c = kp->v_usdata[0] << 6; - sp = (short *)((char *)kp + SILOBAS + c); - } + + /* + * Get the address of the silo in VIOC common memory. + */ + sp = (short *)((char *)kp + *(short *)kp->v_usdata); + nextsilo: + + /* + * See if the number of characters is reasonable. + */ i = *(savsilo = sp); - if (i == 0) return(1); - if(xp->v_vers == V_NEW) - if( i > xp->v_silosiz ) { - printf("vx: %d exceeds silo size\n",i) ; - i = xp->v_silosiz; - } - for(sp++;i > 0;i--,sp++) { - c = ((struct silo *)sp)->port & 017; - tp = &vx_tty[c+n*16]; - if(xp->v_loport > c || c > xp->v_hiport) - continue; /* port out of bounds */ - if( (tp->t_state & TS_ISOPEN) == 0) { - wakeup((caddr_t)&tp->t_rawq); + if (i > xp->v_silosiz) { + printf("vx: %d exceeds silo size\n", i); + i = xp->v_silosiz; + } + + /* + * Drain the silo. + */ + tp0 = &vx_tty[n<<4]; + for (sp++; i > 0; i--, sp++) { + port = ((struct silo *)sp)->port&017; + if (port < xp->v_loport || port > xp->v_hiport) + /* + * Not a valid port. + */ continue; - } + + tp = tp0 + port; + if ((tp->t_state&TS_ISOPEN) == 0) + /* + * Nobody is listening. + */ + continue; + + /* + * Fetch the character from vioc memory. + */ c = ((struct silo *)sp)->data; - switch(((struct silo *)sp)->port&(PERROR|FERROR)) { + + switch (((struct silo *)sp)->port&(PERROR|FERROR)) { case PERROR: case PERROR|FERROR: - if( (tp->t_flags&(EVENP|ODDP)) == EVENP - || (tp->t_flags & (EVENP|ODDP)) == ODDP ) + if ((tp->t_flags&(EVENP|ODDP)) == EVENP || + (tp->t_flags&(EVENP|ODDP)) == ODDP) continue; - if(!(((struct silo *)sp)->port&FERROR)) + if (!(((struct silo *)sp)->port&FERROR)) break; + case FERROR: - if(tp->t_flags & RAW) c = 0; - else c = tp->t_intrc; + if (tp->t_flags&RAW) + c = 0; + else + c = tp->t_intrc; } (*linesw[tp->t_line].l_rint)(c, tp); } @@ -290,33 +342,44 @@ nextsilo: } /* - * stty/gtty for VX + * stty/gtty for VX. */ vxioctl(dev, cmd, data, flag) -int dev; /* major, minor device numbers */ -int cmd; /* command */ +int dev; /* major, minor device numbers */ +int cmd; /* command */ caddr_t data; -int flag; +int flag; { - register struct tty *tp; - register error; + register int d = minor(dev); + register struct tty *tp = &vx_tty[d]; + register int error; + + switch (cmd) { + case VCMANUAL: + case VCGRS232: + case VCSRS232: + /* + * Intercept device specific commands. + */ + return(vcumodem(dev, cmd, data, flag)); + default: + break; + } - tp = &vx_tty[minor(dev) & 0377]; error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); if (error == 0) - return error; - if((error = ttioctl(tp, cmd, data, flag)) >= 0) + return(error); + if ((error = ttioctl(tp, cmd, data, flag)) >= 0) { if (cmd==TIOCSETP||cmd==TIOCSETN) vxparam(dev); - return error; + return(error); } else - return ENOTTY; + return(ENOTTY); } - vxparam(dev) -dev_t dev; +dev_t dev; { vxcparam(dev, 1); } @@ -326,42 +389,48 @@ dev_t dev; * registers. */ vxcparam(dev, wait) -dev_t dev; /* major, minor device numbers */ +dev_t dev; /* major, minor device numbers */ int wait; /* nonzero if we should wait for finish */ { - register struct tty *tp; - register struct vcx *xp; - register struct vxcmd *cp; - register s; + register struct tty *tp; + register struct vcx *xp; + register struct vxcmd *cp; + register int s = spl8(); tp = &vx_tty[minor(dev)]; /* pointer to tty structure for port */ xp = (struct vcx *)tp->t_addr; /* pointer to VIOCX info/cmd buffer */ + cp = vobtain(xp); - s = spl8(); cp->cmd = LPARAX; /* set command to "load parameters" */ cp->par[1] = minor(dev)&017; /* port number */ + /* + * Check for XON/XOFF flow control. + */ cp->par[2] = (tp->t_flags&RAW)? 0 : tp->t_startc; /* XON char */ cp->par[3] = (tp->t_flags&RAW)? 0 : tp->t_stopc; /* XOFF char */ - if(tp->t_flags&(RAW|LITOUT) || + if (tp->t_flags&(RAW|LITOUT) || (tp->t_flags&(EVENP|ODDP)) == (EVENP|ODDP)) { cp->par[4] = 0xc0; /* 8 bits of data */ cp->par[7] = 0; /* no parity */ } else { cp->par[4] = 0x40; /* 7 bits of data */ - if((tp->t_flags&(EVENP|ODDP)) == ODDP) + if ((tp->t_flags&(EVENP|ODDP)) == ODDP) cp->par[7] = 1; /* odd parity */ - else if((tp->t_flags&(EVENP|ODDP)) == EVENP) + else if ((tp->t_flags&(EVENP|ODDP)) == EVENP) cp->par[7] = 3; /* even parity */ else cp->par[7] = 0; /* no parity */ } cp->par[5] = (tp->t_stopbits == 0) ? 4 : tp->t_stopbits; - cp->par[6] = tp->t_ospeed; + if (tp->t_ospeed == EXTA || tp->t_ospeed == EXTB) + cp->par[6] = 19; /* 19200 BAUD */ + else + cp->par[6] = tp->t_ospeed; if (vcmd(xp->v_nbr, &cp->cmd) && wait) - sleep(cp,TTIPRI); + sleep(cp, TTIPRI); splx(s); } @@ -369,126 +438,80 @@ int wait; /* nonzero if we should wait * VIOCX command response interrupt. * For transmission, restart output to any active port. * For all other commands, just clean up. + * This routine is called with spl8 from vcmdrsp(). */ -vxxint(n,cp) +vxxint(n, cp) register int n; /* VIOC number */ -register struct vxcmd *cp; /* command structure */ +register struct vxcmd *cp; /* command structure */ { - register struct vxmit *vp, *pvp; - register struct tty *tp; - register struct vcx *xp; - register struct tty *hp; - register long port; + register struct vxmit *vp, *pvp; + register struct tty *tp; + register struct vcx *xp; + register struct tty *hp; + register int port; xp = &vcx[n]; - cp = (struct vxcmd *)( (long *)cp - 1); + cp = (struct vxcmd *)((long *)cp-1); #if NVBSC > 0 - switch(cp->cmd) { + switch (cp->cmd) { case MDMCTL1: case HUNTMD1: case LPARAX1: vrelease(xp, cp); wakeup(cp); return; } #endif - switch(cp->cmd&0xff00) { + switch (cp->cmd&0xff00) { case LIDENT: /* initialization complete */ - if (xp->v_state & V_RESETTING) { - vxfnreset(n,cp); - vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR); - } + if (xp->v_state&V_RESETTING) + vxfnreset(n, cp); cp->cmd++; return; case XMITDTA: case XMITIMM: break; case LPARAX: wakeup(cp); + case FDTATOX: default: /* MDMCTL or FDTATOX */ vrelease(xp, cp); - if (xp->v_state & V_RESETTING) { - vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR); - } return; } - for(vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizvxmit); + for (vp = (struct vxmit *)(cp->par + (cp->cmd&07)*sizvxmit); vp >= (struct vxmit *)cp->par; - vp = (struct vxmit *) ((char *)vp - sizvxmit) ) - { - tp = &vx_tty[(vp->line & 017)+n*16]; + vp = (struct vxmit *) ((char *)vp - sizvxmit)) { + tp = &vx_tty[(vp->line&017)+(n<<4)]; #if NVBSC > 0 -/* ======= BSC code ================ -*/ port = vp->line; if (tp->t_line == LDISP) { - vrelease(xp, cp) ; - /* Call bsctxd with logical bscport no; 0,1..4,5 */ - /* v_xmtcnt was set to BISYNC ctlr no in vxinit() */ + vrelease(xp, cp); + /* + * Call bsctxd with logical bscport no; 0,1..4,5. + * v_xmtcnt was set to BISYNC ctlr no in vxinit(). + */ bsctxd((xp->v_xmtcnt*NBSC)+port); - return ; + return; } if (bscport[(n<<4)+port] == BISYNC) { printf("\nvxxint: int. after line closed. (cmd:%lx)", cp->cmd&0xff); - vrelease(xp, cp) ; - return ; + vrelease(xp, cp); + return; } -/* ================================== -*/ #endif pvp = vp; tp->t_state &= ~TS_BUSY; - if(tp->t_state & TS_FLUSH) { + if (tp->t_state&TS_FLUSH) { tp->t_state &= ~TS_FLUSH; - wakeup( (caddr_t)&tp->t_state ) ; + wakeup((caddr_t)&tp->t_state); } else ndflush(&tp->t_outq, vp->bcount+1); } xp->v_xmtcnt--; - vrelease(xp,cp); - if(xp->v_vers == V_NEW) { - vp = pvp; - xp->v_actport[(vp->line & 017) - xp->v_loport] |= 1 ; - if(vxstart(tp) && (cp = nextcmd(xp)) != NULL) - { - xp->v_xmtcnt++; - vcmd(n, &cp->cmd); - return ; - } - xp->v_actport[(vp->line & 017) - xp->v_loport] = 0 ; - return ; - } - xp->v_actflg = 1; - hp = &vx_tty[xp->v_hiport+n*16]; - for(tp = &vx_tty[xp->v_loport+n*16];tp <= hp;tp++) - if(vxstart(tp) && (cp = nextcmd(xp)) != NULL) - { - xp->v_xmtcnt++; - vcmd(n, &cp->cmd); - } - if( (cp = nextcmd(xp)) != NULL ) /* command to send ? */ - { - xp->v_xmtcnt++; - vcmd(n,&cp->cmd); - } - xp->v_actflg = 0; -} - -/* - * Force out partial XMIT command after timeout - */ -vxforce(xp) -register struct vcx *xp; -{ - register struct vxcmd *cp; - register int s; - - s = spl8(); - if((cp = nextcmd(xp)) != NULL) { - xp->v_xmtcnt++; - vcmd(xp->v_nbr, &cp->cmd); - } - splx(s); + vrelease(xp, cp); + vp = pvp; + vxstart(tp); + return; } /* @@ -498,37 +521,37 @@ vxstart(tp) register struct tty *tp; { register short nch; - register struct vcx *xp; + register struct vcx *xp; register char *outb; register full = 0; - int k, s, port; + int s, port; s = spl8(); - port = minor(tp->t_dev) & 017; + port = minor(tp->t_dev)&017; xp = (struct vcx *)tp->t_addr; if (!(tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) { - if (tp->t_outq.c_cc<=TTLOWAT(tp)) { + if (tp->t_outq.c_cc <= TTLOWAT(tp)) { if (tp->t_state&TS_ASLEEP) { tp->t_state &= ~TS_ASLEEP; wakeup((caddr_t)&tp->t_outq); } if (tp->t_wsel) { - selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); + selwakeup(tp->t_wsel, tp->t_state&TS_WCOLL); tp->t_wsel = 0; tp->t_state &= ~TS_WCOLL; } } - if(tp->t_outq.c_cc == 0) { + if (tp->t_outq.c_cc == 0) { splx(s); return(0); } #ifdef VXPERF - scope_out(3); + scope_out(3); #endif VXPERF - if(!(tp->t_flags&(RAW|LITOUT))) + if (!(tp->t_flags&(RAW|LITOUT))) full = 0200; - if((nch = ndqb(&tp->t_outq, full)) == 0) { - if(full) { + if ((nch = ndqb(&tp->t_outq, full)) == 0) { + if (full) { nch = getc(&tp->t_outq); timeout(ttrstrt, (caddr_t)tp, (nch&0177) +6); tp->t_state |= TS_TIMEOUT; @@ -537,25 +560,11 @@ register struct tty *tp; } else { outb = (char *)tp->t_outq.c_cf; tp->t_state |= TS_BUSY; - if(xp->v_vers == V_NEW) - k = xp->v_actport[port - xp->v_loport] ; - else - k = xp->v_actflg ; - - full = vsetq(xp, port, outb, nch); - - if( (k&1) == 0 ) { /* not called from vxxint */ - if(full || xp->v_xmtcnt == 0) { - outb = (char *)(&nextcmd(xp)->cmd); - xp->v_xmtcnt++; - vcmd(xp->v_nbr, outb ); - } else - timeout(vxforce,xp,3); - } + vsend(xp, port, outb, nch); } } splx(s); - return(full); /* indicate if max commands or not */ + return; } /* @@ -564,10 +573,10 @@ register struct tty *tp; vxstop(tp) register struct tty *tp; { - register s; + register int s; s = spl8(); - if (tp->t_state & TS_BUSY) { + if (tp->t_state&TS_BUSY) { if ((tp->t_state&TS_TTSTOP)==0) { tp->t_state |= TS_FLUSH; } @@ -579,283 +588,269 @@ register struct tty *tp; * VIOCX Initialization. Makes free lists of command buffers. * Resets all viocx's. Issues a LIDENT command to each * viocx which establishes interrupt vectors and logical - * port numbers + * port numbers. */ -vxinit(i,wait) -register int i; -long wait; -{ - register struct vcx *xp; /* ptr to VIOC-X info/cmd buffer */ - register struct vblok *kp; /* pointer to VIOC-X control block */ - register struct vxcmd *cp; /* pointer to a command buffer */ - register char *resp; /* pointer to response buffer */ - register int j,ix; - register struct vcmds *cpp; +vxinit(i, wait) +register int i; +int wait; +{ + register struct vcx *xp; /* ptr to VIOC-X info/cmd buffer */ + register struct vblok *kp; /* pointer to VIOC-X control block */ + register struct vxcmd *cp; /* pointer to a command buffer */ + register char *resp; /* pointer to response buffer */ + register int j, ix; + register struct vcmds *cpp; char type; - register struct bsc *bp; /* bsc change */ - extern struct bsc bsc[]; +#if NVBSC > 0 + register struct bsc *bp; /* bsc change */ +#endif + /* + * Only initialize once. + */ if (vbtbl) { - for(j=0;jv_ident; - vxtype[i] = 0; /* Type is Viox-x */ - switch(type) { + vxtype[i] = 0; /* Type is VIOC-X */ + switch (type) { + case PVIOCX: case VIOCX: - { - xp->v_vers = V_OLD ; - /* set DCD for printer ports */ - for(j = 0;j < 16;j++) - if (kp->v_portyp[j] == 4 ) - kp->v_dcd |= 1 << j ; - } - break ; + printf("WARNING: Old vioc no longer supported.\n"); + xp->v_loport = xp->v_hiport = 0; + return; + case NWVIOCX: - { - xp->v_vers = V_NEW ; - xp->v_silosiz = kp->v_maxsilo ; - /* set DCD for printer ports */ - for(j = 0;j < 16;j++) - if (kp->v_portyp[j] == 4 ) - kp->v_dcd |= 1 << j ; - } - break ; - case PVIOCX: - xp->v_vers = V_OLD ; - break ; case NPVIOCX: - xp->v_vers = V_NEW ; - xp->v_silosiz = kp->v_maxsilo ; - break ; -#ifdef VIOCB + xp->v_vers = V_NEW; + xp->v_silosiz = kp->v_maxsilo; + /* + * Initialize the port types. + */ + for (j = 0; j < 16; j++) + xp->vx_type[j] = kp->v_portyp[j]; + break; + case VIOCB: /* old f/w, Bisync board */ - if (wait) /* Just boot up */ + if (wait) { /* Just boot up */ + if (bscno >= NVBSC) { + printf("\nVIOCB no%ld is not configured in software", bscno); + break; + } if (bscno >= MXVIOC_B) { printf("\nvxinit: exceed max no of VIOC-B:%ld", MXVIOC_B); break; + } } printf("(kp:%lx)(xp:%lx): %lx---%x OLD VIOC-B, ", (long)kp, (long)xp,(int)kp->v_ident, (int)kp->v_fault); - xp->v_vers = V_OLD ; - /* save device specific info */ - /*for(bp = &bsc[0]; bp <= &bsc[NBSC-1]; bp++) - bp->b_devregs = (caddr_t)xp ; - */ + xp->v_vers = V_OLD; if (wait) /* Use v_xmtcnt to */ xp->v_xmtcnt = (char)bscno; /* save VIOC-B ctlrno */ - else bscno = (long)xp->v_xmtcnt & 0x7f; + else + bscno = (long)xp->v_xmtcnt&0x7f; bp = &bsc[0+(bscno*4)]; - for(ix=0;ix<4;ix++,bp++) - bp->b_devregs = (caddr_t)xp ; + for (ix = 0; ix < 4; ix++, bp++) + bp->b_devregs = (caddr_t)xp; bscno++; - bscport[(i*16)+0] = BISYNC; - bscport[(i*16)+1] = BISYNC; - bscport[(i*16)+2] = BISYNC; - bscport[(i*16)+3] = BISYNC; - printf(",BSC no %d initialized.\n",bscno-1); - break ; -#endif + bscport[(i<<4)+0] = BISYNC; + bscport[(i<<4)+1] = BISYNC; + bscport[(i<<4)+2] = BISYNC; + bscport[(i<<4)+3] = BISYNC; + printf(" Bisync initialized\n"); + break; -#ifdef NWVIOCB case NWVIOCB: /* new f/w, Bisync board */ - if (wait) /* Just boot up */ + if (wait) { /* Just boot up */ + if (bscno >= NVBSC) { + printf("\nVIOCB no%ld is not configured in software", bscno); + break; + } if (bscno >= MXVIOC_B) { printf("\nvxinit: exceed max no of VIOC-B:%ld", MXVIOC_B); break; } - printf("(kp:%lx)(xp:%lx): %lx---%x 16K VIOC-B", - (long)kp, (long)xp,(int)kp->v_ident, - (int)kp->v_fault); - xp->v_vers = V_NEW ; - xp->v_silosiz = kp->v_maxsilo ; - /* save device specific info */ + } + xp->v_vers = V_NEW; + xp->v_silosiz = kp->v_maxsilo; if (wait) /* Use v_xmtcnt to */ xp->v_xmtcnt = (char)bscno; /* save VIOC-B ctlrno */ - else bscno = (long)xp->v_xmtcnt & 0x7f; + else + bscno = (long)xp->v_xmtcnt&0x7f; bp = &bsc[bscno*4]; - for(ix=0;ix<4;ix++,bp++) - bp->b_devregs = (caddr_t)xp ; + for (ix = 0; ix < 4; ix++, bp++) + bp->b_devregs = (caddr_t)xp; bscno++; - bscport[(i*16)+0] = BISYNC; - bscport[(i*16)+1] = BISYNC; - bscport[(i*16)+2] = BISYNC; - bscport[(i*16)+3] = BISYNC; - printf(",BSC no %d initialized.\n",bscno-1); - if(CBSIZE > kp->v_maxxmt) - printf("vxinit: Warning CBSIZE > maxxmt\n") ; - break ; -#endif + bscport[(i<<4)+0] = BISYNC; + bscport[(i<<4)+1] = BISYNC; + bscport[(i<<4)+2] = BISYNC; + bscport[(i<<4)+3] = BISYNC; + printf(" Bisync initialized\n"); + break; + case VBOPID: /* VIOC-BOP */ - vxbbno++; - vxtype[i] = 1; - vxbopno[i] = vxbbno; - printf("VIOC-BOP no. %d at %lx\n",vxbopno[i],VIOCBAS[i]); + if (vxtype[i] == 0) { /* don't increment if already seen */ + vxbbno++; + vxtype[i] = 1; + vxbopno[i] = vxbbno; + } + printf(" VIOC-BOP initialized\n"); + default: - return ; /* Not a viocx type */ + return; /* Not a viocx type */ } - xp->v_nbr = -1; /* no number for it yet */ - xp->v_maxcmd = xp->v_vers == V_NEW ? 24 : 4; + xp->v_nbr = -1; /* no number for it yet */ + xp->v_maxcmd = xp->v_vers == V_NEW ? 23 : 3; - for(j=0; jvx_lst[j]; /* index a buffer */ cp->c_fwd = &xp->vx_lst[j+1]; /* point to next buf */ } xp->vx_avail = &xp->vx_lst[0]; /* set idx to 1st free buf */ cp->c_fwd = (struct vxcmd *)0; /* mark last buf in free list */ - cp = vobtain(xp); /* grap the control block */ - cp->cmd = LIDENT; /* set command type */ + /* + * Assures proper state when reinit. in case of INT. ERR + */ + cpp->v_cmdsem = cpp->v_curcnt = cpp->v_fill = 0; + cpp->v_empty = cpp->v_itrfill = cpp->v_itrempt = 0; + + cp = vobtain(xp); /* grap the control block */ + cp->cmd = LIDENT; /* set command type */ cp->par[0] = i * 4 + VCVECT; /* ack vector */ cp->par[1] = cp->par[0] + 1; /* cmd resp vector */ cp->par[3] = cp->par[0] + 2; /* unsol intr vector */ - cp->par[4] = 15; /* max ports, no longer used */ - cp->par[5] = 0; /* set 1st port number */ - vcmd(i, &cp->cmd); /* initialize the VIOC-X */ - - if (!wait) return; - while(cp->cmd == LIDENT); /* wait for command completion */ - - /* calculate address of response buffer */ - resp = (char *)kp; - resp += kp->v_rspoff & 0x3FFF; - - if(resp[0] != 0 && (resp[0]&0177) != 3) /* did init work? */ - { - vrelease(xp,cp); /* init failed */ + cp->par[4] = 15; /* max ports, no longer used */ + cp->par[5] = 0; /* set 1st port number */ + vcmd(i, &cp->cmd); /* initialize the VIOC-X */ + if (!wait) + return; + + while (cp->cmd == LIDENT) /* wait for command completion */ + ; + + /* + * Calculate address of response buffer. + */ + resp = (char *)kp; + resp += kp->v_rspoff&0x3FFF; + + if (resp[0] != 0 && (resp[0]&0177) != 3) { /* did init work? */ + vrelease(xp, cp); /* init failed */ return; /* try next VIOC-X */ } xp->v_loport = cp->par[5]; /* save low port number */ - xp->v_hiport = cp->par[7];/* VIOC knows high port numbr */ - vrelease(xp,cp); /* done with this control block */ - xp->v_nbr = i; /* assign VIOC-X board number */ + xp->v_hiport = cp->par[7]; /* VIOC knows high port numbr */ + vrelease(xp, cp); /* done with this control block */ + xp->v_nbr = i; /* assign VIOC-X board number */ } /* - * Obtain a command buffer + * Obtain a command buffer. */ struct vxcmd * vobtain(xp) -register struct vcx *xp; +register struct vcx *xp; { - - register struct vxcmd *p; - register s; + register struct vxcmd *p; + register int s; s = spl8(); p = xp->vx_avail; - if(p == (struct vxcmd *)0) { -#ifdef VX_DEBUG - if (vxintr4 & VXNOBUF) vxintr4 &= ~VXNOBUF; -#endif + if (p == (struct vxcmd *)0) { vpanic("vx: no buffs"); vxstreset(xp - vcx); splx(s); - return(vobtain(xp)); + return(vobtain(xp)); /* guaranteed to work this time */ } xp->vx_avail = (xp->vx_avail)->c_fwd; splx(s); - return( (struct vxcmd *)p); + return((struct vxcmd *)p); } /* - * Release a command buffer + * Release a command buffer. */ -vrelease(xp,cp) -register struct vcx *xp; -register struct vxcmd *cp; +vrelease(xp, cp) +register struct vcx *xp; +register struct vxcmd *cp; { + register int s = spl8(); - register s; - -#ifdef VX_DEBUG - if (vxintr4 & VXNOBUF) return; -#endif - s = spl8(); cp->c_fwd = xp->vx_avail; xp->vx_avail = cp; splx(s); } /* - * vxcmd - - * + * Arrange for "cnt" bytes from "addr" to be written to port number + * "port" on VIOC described by "xp". */ -struct vxcmd * -nextcmd(xp) -register struct vcx *xp; -{ - register struct vxcmd *cp; - register int s; - - s = spl8(); - cp = xp->vx_build; - xp->vx_build = (struct vxcmd *)0; - splx(s); - return(cp); -} - -/* - * assemble transmits into a multiple command. - * up to 8 transmits to 8 lines can be assembled together - */ -vsetq(xp ,d ,addr, cnt) -register struct vcx *xp; -caddr_t addr; -{ +vsend(xp, port, addr, cnt) +register struct vcx *xp;/* points to vioc control structure for this port */ +int port; /* port number to get the data */ +caddr_t addr; /* beginning address of the block */ +register int cnt; /* size of the block of characters */ +{ + register struct vxcmd *cp; + register struct vxmit *mp; + register int i; + register char *src, *dst; + + /* + * Get a command. + */ + cp = vobtain(xp); - register struct vxcmd *cp; - register struct vxmit *mp; - register char *p; - register i; + /* + * Fill out the port information. + */ + mp = (struct vxmit *)cp->par; + mp->bcount = cnt-1; + mp->line = port; - cp = xp->vx_build; - if(cp == (struct vxcmd *)0) { - cp = vobtain(xp); - xp->vx_build = cp; - cp->cmd = XMITDTA; + if (cnt <= 6) { + /* + * If small enough, we can give the data directly to + * the vioc, eliminating the need for DMA. + */ + cp->cmd = XMITIMM; + src = addr; + i = cnt; } else { - if((cp->cmd & 07) == 07) { - vpanic("vx: vsetq overflow"); - vxstreset(xp->v_nbr); - return(0); - } - cp->cmd++; + /* + * Get the physical address of the block to DMA. + */ + cp->cmd = XMITDTA; + addr = vtoph(0, (caddr_t)addr); + src = (char *)&addr; + i = sizeof(addr); } - mp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizvxmit); - mp->bcount = cnt-1; - - mp->line = d; - if((xp->v_vers == V_NEW) && (cnt <= 6)) { - cp->cmd = XMITIMM ; - p = addr; - /* bcopy(addr, &(char *)mp->ostream, cnt) ; */ - } else { - addr = vtoph(0, (caddr_t)addr) ; /* should be a sys address */ - p = (char *)&addr; - cnt = sizeof addr; - /* mp->ostream = addr ; */ - } - for(i=0; iostream[i] = *p++; - if(xp->v_vers == V_NEW) - return(1) ; - else - return((cp->cmd&07) == 7) ; /* Indicate if full */ + /* + * Copy the data or address into the command. + */ + dst = mp->ostream; + while (--i >= 0) + *dst++ = *src++; + + xp->v_xmtcnt++; + vcmd(xp->v_nbr, (char *)&cp->cmd); + return; } #endif