bsc -> tahoebsc; sna -> tahoesna
[unix-history] / usr / src / sys / tahoe / vba / vx.c
CommitLineData
e6453f14 1/* vx.c 1.4 86/01/12 */
b8c32975
SL
2
3#include "vx.h"
4#if NVX > 0
5/*
336ca318 6 * VIOC-X driver
b8c32975 7 */
9d915fad 8#include "../tahoe/pte.h"
b8c32975
SL
9
10#include "../h/param.h"
11#include "../h/ioctl.h"
12#include "../h/tty.h"
13#include "../h/dir.h"
14#include "../h/user.h"
15#include "../h/map.h"
b8c32975 16#include "../h/buf.h"
b8c32975
SL
17#include "../h/conf.h"
18#include "../h/file.h"
19#include "../h/uio.h"
9d915fad
SL
20#include "../h/proc.h"
21#include "../h/vm.h"
22
23#include "../tahoevba/vbavar.h"
24#include "../tahoevba/vioc.h"
b8c32975 25#ifdef VXPERF
9d915fad 26#include "../tahoevba/scope.h"
b8c32975
SL
27#endif VXPERF
28#include "vbsc.h"
29#if NVBSC > 0
e6453f14
SL
30#include "../tahoebsc/bscio.h"
31#include "../tahoebsc/bsc.h"
b8c32975
SL
32char bscport[NVXPORTS];
33#endif
34
35#ifdef BSC_DEBUG
e6453f14 36#include "../tahoebsc/bscdebug.h"
b8c32975
SL
37#endif
38
39#ifdef VX_DEBUG
40long vxintr4 = 0;
41long vxdebug = 0;
e6453f14 42#include "../tahoevba/vxdebug.h"
b8c32975
SL
43#endif
44
45#define RSPquals 1
46
336ca318
SL
47struct vcx vcx[NVIOCX] ;
48struct tty vx_tty[NVXPORTS];
49extern struct vcmds v_cmds[];
50extern long reinit;
b8c32975
SL
51
52int vxstart() ;
53int ttrstrt() ;
336ca318
SL
54struct vxcmd *vobtain() ;
55struct vxcmd *nextcmd() ;
b8c32975
SL
56
57/*
58 * Driver information for auto-configuration stuff.
59 * (not tested and probably should be changed)
60 */
61int vxprobe(), vxattach(), vxrint();
62struct vba_device *vxinfo[NVIOCX];
63long vxstd[] = { 0 };
64struct vba_driver vxdriver =
336ca318 65 { vxprobe, 0, vxattach, 0, vxstd, "vx", vxinfo };
b8c32975 66
336ca318
SL
67char vxtype[NVIOCX]; /* 0: viox-x/vioc-b; 1: vioc-bop */
68char vxbbno = -1;
69char vxbopno[NVIOCX]; /* BOP board no. if indicated by vxtype[] */
70int vxivec[NVIOCX]; /* interrupt vector base */
71extern vbrall();
b8c32975 72
336ca318 73vxprobe(reg, vi)
b8c32975 74 caddr_t reg;
336ca318 75 struct vba_device *vi;
b8c32975 76{
336ca318 77 register int br, cvec; /* must be r12, r11 */
b8c32975
SL
78 register struct vblok *vp = (struct vblok *)reg;
79
80#ifdef lint
81 br = 0; cvec = br; br = cvec;
9d915fad 82 vackint(0); vunsol(0); vcmdrsp(0); vxfreset(0);
b8c32975 83#endif
9d915fad
SL
84 if (badaddr((caddr_t)vp, 1))
85 return (0);
86 vp->v_fault = 0;
87 vp->v_vioc = V_BSY;
88 vp->v_hdwre = V_RESET; /* reset interrupt */
b8c32975 89 DELAY(4000000);
9d915fad
SL
90 if (vp->v_fault != VREADY)
91 return (0);
336ca318
SL
92#ifdef notdef
93 /*
94 * Align vioc interrupt vector base to 4 vector
95 * boundary and fitting in 8 bits (is this necessary,
96 * wish we had documentation).
97 */
98 if ((vi->ui_hd->vh_lastiv -= 3) > 0xff)
99 vi->ui_hd->vh_lastiv = 0xff;
100 vxivec[vi->ui_unit] = vi->ui_hd->vh_lastiv =
101 vi->ui_hd->vh_lastiv &~ 0x3;
102#else
103 vxivec[vi->ui_unit] = 0x40+vi->ui_unit*4;
104#endif
105 br = 0x18, cvec = vxivec[vi->ui_unit]; /* XXX */
9d915fad 106 return (sizeof (*vp));
b8c32975
SL
107}
108
336ca318
SL
109vxattach(vi)
110 register struct vba_device *vi;
b8c32975 111{
9d915fad 112
336ca318
SL
113 VIOCBAS[vi->ui_unit] = vi->ui_addr;
114 vxinit(vi->ui_unit, (long)1);
b8c32975
SL
115}
116
117/*
118 * Open a VX line.
119 */
9d915fad 120/*ARGSUSED*/
b8c32975
SL
121vxopen(dev, flag)
122{
123 register struct tty *tp; /* pointer to tty struct for port */
124 register struct vcx *xp; /* pointer to VIOC-X info/cmd buffer */
125 register d; /* minor device number */
126 register long jj;
127
128
129 d = minor(dev); /* get minor device number */
130 if (d >= NVXPORTS) /* validate minor device number */
131 return ENXIO; /* set errno to indicate bad port # */
132 tp = &vx_tty[d]; /* index the tty structure for port */
133
134 xp = &vcx[d>>4]; /* index VIOC-X info/cmd area */
135 d &= 017;
136
137 /* If we did not find a board with the correct port number on
138 it, or the entry for the VIOC-X had no ports on it, inform the
139 caller that the port does not exist. */
140 if(!( xp->v_loport <= d && d <= xp->v_hiport ) /* home? */
141 || (xp->v_hiport - xp->v_loport)==0)
142 return ENXIO; /* bad minor device number */
143 tp->t_addr = (caddr_t)xp; /* store address of VIOC-X info */
144 tp->t_oproc = vxstart; /* store address of startup routine */
145 tp->t_dev = dev; /* store major/minor device numbers */
146 d = spl8();
147 tp->t_state |= TS_WOPEN; /* mark device as waiting for open */
148 if ((tp->t_state&TS_ISOPEN) == 0) /* is device already open? */
149 { /* no, open it */
150 ttychars(tp); /* set default control chars */
151 if (tp->t_ispeed == 0) /* if no default speeds set them */
152 {
153 tp->t_ispeed = SSPEED; /* default input baud */
154 tp->t_ospeed = SSPEED; /* default output baud */
155 tp->t_flags |= (ODDP|EVENP|ECHO); /* default modes */
156 }
157 vxparam(dev); /* set parameters for this port */
158 }
159 splx(d);
160 /* ? if already open for exclusive use open fails unless caller is
161 root. */
162 if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
163 return EBUSY; /* device is busy, sorry */
164
165 /* wait for data carrier detect to go high */
166 d = spl8();
167 if( !vcmodem(dev,VMOD_ON) )
168 while( (tp->t_state&TS_CARR_ON) == 0 )
9d915fad 169 sleep((caddr_t)&tp->t_canq,TTIPRI);
b8c32975
SL
170 jj= (*linesw[tp->t_line].l_open)(dev,tp); /*let tty.c finish the open */
171 splx(d); /* 1/2/85 : assures open complete */
172 return (jj);
173}
174
175/*
176 * Close a VX line.
177 */
9d915fad 178/*ARGSUSED*/
b8c32975
SL
179vxclose(dev, flag)
180dev_t dev;
181int flag;
182{
183 register struct tty *tp;
184 register d;
185
186 d = minor(dev) & 0377;
187 tp = &vx_tty[d];
188 d = spl8();
189 (*linesw[tp->t_line].l_close)(tp);
190 if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_HUPCLS))
191 if( !vcmodem(dev,VMOD_OFF) )
192 tp->t_state &= ~TS_CARR_ON;
193 /* wait for the last response */
194 while(tp->t_state & TS_FLUSH)
195 sleep( (caddr_t)&tp->t_state, TTOPRI ) ;
196 ttyclose(tp); /* let tty.c finish the close */
197 splx(d);
198}
199
200/*
201 * Read from a VX line.
202 */
203vxread(dev, uio)
204 dev_t dev;
205 struct uio *uio;
206{
207 register struct tty *tp = &vx_tty[minor(dev) & 0377];
208 return (*linesw[tp->t_line].l_read)(tp, uio);
209}
210
211/*
212 * write on a VX line
213 */
214vxwrite(dev, uio)
215 dev_t dev;
216 struct uio *uio;
217{
218 register struct tty *tp = &vx_tty[minor(dev) & 0377];
219 return (*linesw[tp->t_line].l_write)(tp, uio);
220}
221
222/*
223 * VIOCX unsolicited interrupt.
224 */
225vxrint(n)
226register n; /* mux number */
227{
228 register struct tty *tp;
229 register struct vcx *xp;
230 register short *sp;
231 register struct vblok *kp;
232 register int i, c;
233 short *savsilo;
234 struct silo {
235 char data;
236 char port;
237 };
238
239 kp = VBAS(n);
240 xp = &vcx[n];
241 switch(kp->v_uqual&037) {
242 case 0:
243 break;
244 case 2:
245 printf(" ERR NBR %x\n",kp->v_ustat);
246 vpanic("vc: VC PROC ERR");
247 vxstreset(n);
248 return(0);
249 case 3:
250 vcmintr(n);
251 return(1);
252 case 4:
253 return(1);
254 default:
255 printf(" ERR NBR %x\n",kp->v_uqual);
256 vpanic("vc: VC UQUAL ERR");
257 vxstreset(n);
258 return(0);
259 }
260 if(xp->v_vers == V_NEW) {
261 register short *aa ;
262 aa = (short *)kp->v_usdata;
263 sp = (short *)(*aa + (char *)kp) ;
264 } else {
265 c = kp->v_usdata[0] << 6;
266 sp = (short *)((char *)kp + SILOBAS + c);
267 }
b8c32975
SL
268 i = *(savsilo = sp);
269 if (i == 0) return(1);
270 if(xp->v_vers == V_NEW)
271 if( i > xp->v_silosiz ) {
272 printf("vx: %d exceeds silo size\n",i) ;
273 i = xp->v_silosiz;
274 }
275 for(sp++;i > 0;i--,sp++) {
276 c = ((struct silo *)sp)->port & 017;
277 tp = &vx_tty[c+n*16];
278 if(xp->v_loport > c || c > xp->v_hiport)
279 continue; /* port out of bounds */
280 if( (tp->t_state & TS_ISOPEN) == 0) {
281 wakeup((caddr_t)&tp->t_rawq);
282 continue;
283 }
284 c = ((struct silo *)sp)->data;
285 switch(((struct silo *)sp)->port&(PERROR|FERROR)) {
286 case PERROR:
287 case PERROR|FERROR:
288 if( (tp->t_flags&(EVENP|ODDP)) == EVENP
289 || (tp->t_flags & (EVENP|ODDP)) == ODDP )
290 continue;
291 if(!(((struct silo *)sp)->port&FERROR))
292 break;
293 case FERROR:
294 if(tp->t_flags & RAW) c = 0;
295 else c = tp->t_intrc;
296 }
297 (*linesw[tp->t_line].l_rint)(c, tp);
298 }
299 *savsilo = 0;
300 return(1);
301}
302
303/*
304 * stty/gtty for VX
305 */
306vxioctl(dev, cmd, data, flag)
307int dev; /* major, minor device numbers */
308int cmd; /* command */
309caddr_t data;
310int flag;
311{
312 register struct tty *tp;
313 register error;
314
315 tp = &vx_tty[minor(dev) & 0377];
316 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
317 if (error == 0)
318 return error;
319 if((error = ttioctl(tp, cmd, data, flag)) >= 0)
320 {
321 if (cmd==TIOCSETP||cmd==TIOCSETN)
322 vxparam(dev);
323 return error;
324 } else
325 return ENOTTY;
326}
327
328
329vxparam(dev)
330dev_t dev;
331{
332 vxcparam(dev, 1);
333}
334
335/*
336 * Set parameters from open or stty into the VX hardware
337 * registers.
338 */
339vxcparam(dev, wait)
340dev_t dev; /* major, minor device numbers */
341int wait; /* nonzero if we should wait for finish */
342{
343 register struct tty *tp;
344 register struct vcx *xp;
345 register struct vxcmd *cp;
346 register s;
347
348 tp = &vx_tty[minor(dev)]; /* pointer to tty structure for port */
349 xp = (struct vcx *)tp->t_addr; /* pointer to VIOCX info/cmd buffer */
350 cp = vobtain(xp);
351 s = spl8();
352 cp->cmd = LPARAX; /* set command to "load parameters" */
353 cp->par[1] = minor(dev)&017; /* port number */
354
355 cp->par[2] = (tp->t_flags&RAW)? 0 : tp->t_startc; /* XON char */
356 cp->par[3] = (tp->t_flags&RAW)? 0 : tp->t_stopc; /* XOFF char */
357
358 if(tp->t_flags&(RAW|LITOUT) ||
359 (tp->t_flags&(EVENP|ODDP)) == (EVENP|ODDP)) {
360 cp->par[4] = 0xc0; /* 8 bits of data */
361 cp->par[7] = 0; /* no parity */
362 } else {
363 cp->par[4] = 0x40; /* 7 bits of data */
364 if((tp->t_flags&(EVENP|ODDP)) == ODDP)
365 cp->par[7] = 1; /* odd parity */
366 else if((tp->t_flags&(EVENP|ODDP)) == EVENP)
367 cp->par[7] = 3; /* even parity */
368 else
369 cp->par[7] = 0; /* no parity */
370 }
371 cp->par[5] = 0x4; /* 1 stop bit */
372 cp->par[6] = tp->t_ospeed;
373
9d915fad
SL
374 if (vcmd(xp->v_nbr, (caddr_t)&cp->cmd) && wait)
375 sleep((caddr_t)cp,TTIPRI);
b8c32975
SL
376 splx(s);
377}
378
379/*
380 * VIOCX command response interrupt.
381 * For transmission, restart output to any active port.
382 * For all other commands, just clean up.
383 */
384vxxint(n,cp)
385register int n; /* VIOC number */
386register struct vxcmd *cp; /* command structure */
387{
388 register struct vxmit *vp, *pvp;
389 register struct tty *tp;
390 register struct vcx *xp;
391 register struct tty *hp;
392
393 xp = &vcx[n];
394 cp = (struct vxcmd *)( (long *)cp - 1);
395#if NVBSC > 0
396 switch(cp->cmd) {
397 case MDMCTL1: case HUNTMD1: case LPARAX1:
398 vrelease(xp, cp);
399 wakeup(cp);
400 return;
401 }
402#endif
403 switch(cp->cmd&0xff00) {
404 case LIDENT: /* initialization complete */
405 if (xp->v_state & V_RESETTING) {
406 vxfnreset(n,cp);
407 vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR);
408 }
409 cp->cmd++;
410 return;
411 case XMITDTA: case XMITIMM:
412 break;
413 case LPARAX:
9d915fad 414 wakeup((caddr_t)cp);
b8c32975
SL
415 default: /* MDMCTL or FDTATOX */
416 vrelease(xp, cp);
417 if (xp->v_state & V_RESETTING) {
418 vinthandl(n,((V_BSY | RSPquals) << 8) | V_INTR);
419 }
420 return;
421 }
422 for(vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizvxmit);
423 vp >= (struct vxmit *)cp->par;
424 vp = (struct vxmit *) ((char *)vp - sizvxmit) )
425 {
426 tp = &vx_tty[(vp->line & 017)+n*16];
427/* cjk buffer bug */
428#if NVBSC > 0
429 /* bsc change */
430 if (tp->t_line == LDISP) {
431 vrelease(xp, cp);
432 bsctxd((vp->line & 017));
433 return ;
434 }
435 /* End of bsc change */
436#endif
437/* cjk */
438 pvp = vp;
439 tp->t_state &= ~TS_BUSY;
440 if(tp->t_state & TS_FLUSH) {
441 tp->t_state &= ~TS_FLUSH;
442 wakeup( (caddr_t)&tp->t_state ) ;
443 }
444 else
445 ndflush(&tp->t_outq, vp->bcount+1);
446 }
447 xp->v_xmtcnt--;
448 vrelease(xp,cp);
449 if(xp->v_vers == V_NEW) {
450 vp = pvp;
451 xp->v_actport[(vp->line & 017) - xp->v_loport] |= 1 ;
452 if(vxstart(tp) && (cp = nextcmd(xp)) != NULL)
453 {
454 xp->v_xmtcnt++;
9d915fad 455 vcmd(n, (caddr_t)&cp->cmd);
b8c32975
SL
456 return ;
457 }
458 xp->v_actport[(vp->line & 017) - xp->v_loport] = 0 ;
459 return ;
460 }
461 xp->v_actflg = 1;
462 hp = &vx_tty[xp->v_hiport+n*16];
463 for(tp = &vx_tty[xp->v_loport+n*16];tp <= hp;tp++)
464 if(vxstart(tp) && (cp = nextcmd(xp)) != NULL)
465 {
466 xp->v_xmtcnt++;
9d915fad 467 vcmd(n, (caddr_t)&cp->cmd);
b8c32975
SL
468 }
469 if( (cp = nextcmd(xp)) != NULL ) /* command to send ? */
470 {
471 xp->v_xmtcnt++;
9d915fad 472 vcmd(n, (caddr_t)&cp->cmd);
b8c32975
SL
473 }
474 xp->v_actflg = 0;
475}
476
477/*
478 * Force out partial XMIT command after timeout
479 */
480vxforce(xp)
481register struct vcx *xp;
482{
483 register struct vxcmd *cp;
484 register int s;
485
486 s = spl8();
487 if((cp = nextcmd(xp)) != NULL) {
488 xp->v_xmtcnt++;
9d915fad 489 vcmd(xp->v_nbr, (caddr_t)&cp->cmd);
b8c32975
SL
490 }
491 splx(s);
492}
493
494/*
495 * Start (restart) transmission on the given VX line.
496 */
497vxstart(tp)
498register struct tty *tp;
499{
9d915fad 500 register short n;
b8c32975
SL
501 register struct vcx *xp;
502 register char *outb;
503 register full = 0;
504 int k, s, port;
505
506 s = spl8();
507 port = minor(tp->t_dev) & 017;
508 xp = (struct vcx *)tp->t_addr;
509 if (!(tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) {
510 if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
511 if (tp->t_state&TS_ASLEEP) {
512 tp->t_state &= ~TS_ASLEEP;
513 wakeup((caddr_t)&tp->t_outq);
514 }
515 if (tp->t_wsel) {
516 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
517 tp->t_wsel = 0;
518 tp->t_state &= ~TS_WCOLL;
519 }
520 }
521 if(tp->t_outq.c_cc == 0) {
522 splx(s);
523 return(0);
524 }
525#ifdef VXPERF
526 scope_out(3);
527#endif VXPERF
528 if(!(tp->t_flags&(RAW|LITOUT)))
529 full = 0200;
9d915fad 530 if((n = ndqb(&tp->t_outq, full)) == 0) {
b8c32975 531 if(full) {
9d915fad
SL
532 n = getc(&tp->t_outq);
533 timeout(ttrstrt, (caddr_t)tp, (n&0177) +6);
b8c32975
SL
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
9d915fad 545 full = vsetq(xp, port, outb, n);
b8c32975
SL
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
9d915fad 553 timeout(vxforce,(caddr_t)xp,3);
b8c32975
SL
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 */
564vxstop(tp)
565register 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 */
584vxinit(i,wait)
585register int i;
586long 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;
b8c32975 593 char type;
9d915fad 594#if NVBSC > 0
b8c32975
SL
595 register struct bsc *bp; /* bsc change */
596 extern struct bsc bsc[];
9d915fad 597#endif
b8c32975
SL
598
599
600 kp = VBAS(i); /* get base adr of cntl blok for VIOC */
601
602 xp = &vcx[i]; /* index info/command buffers */
b8c32975
SL
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 */
336ca318
SL
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 */
b8c32975
SL
682 cp->par[4] = 15; /* max ports, no longer used */
683 cp->par[5] = 0; /* set 1st port number */
9d915fad 684 vcmd(i, (caddr_t)&cp->cmd); /* initialize the VIOC-X */
b8c32975
SL
685
686 if (!wait) return;
336ca318
SL
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);
b8c32975
SL
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 */
711struct vxcmd *
712vobtain(xp)
713register 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 */
738vrelease(xp,cp)
739register struct vcx *xp;
740register 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 */
758struct vxcmd *
759nextcmd(xp)
760register 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 */
9d915fad 776vsetq(xp ,d ,addr, n)
b8c32975
SL
777register struct vcx *xp;
778caddr_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);
9d915fad 801 mp->bcount = n-1;
b8c32975
SL
802
803 mp->line = d;
9d915fad 804 if((xp->v_vers == V_NEW) && (n <= 6)) {
b8c32975
SL
805 cp->cmd = XMITIMM ;
806 p = addr;
9d915fad 807 /* bcopy(addr, &(char *)mp->ostream, n) ; */
b8c32975 808 } else {
9d915fad
SL
809 addr = (caddr_t)vtoph((struct proc *)0, (unsigned)addr);
810 /* should be a sys address */
b8c32975 811 p = (char *)&addr;
9d915fad 812 n = sizeof addr;
b8c32975
SL
813 /* mp->ostream = addr ; */
814 }
9d915fad 815 for(i=0; i<n; i++)
b8c32975
SL
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