#include "../tahoevba/vioc.h"
#include "../sna/snadebug.h"
#include "../tahoevba/scope.h"
extern struct vcx vcx
[] ;
extern struct tty vx_tty
[];
struct vcmds v_cmds
[NVIOCX
] ;
extern struct vxcmd
*vobtain();
#include "../vba/vxdebug.h"
* Write a command out to the VIOC
register caddr_t cmdad
; /* command address */
register struct vcmds
*cp
;
if (xp
->v_state
&V_RESETTING
&& cmdad
!= NULL
) {
* When the vioc is resetting, don't process
* anything other than LIDENT commands.
register struct vxcmd
*cmdp
= (struct vxcmd
*)
((char *)cmdad
- sizeof(cmdp
->c_fwd
));
if (cmdp
->cmd
!= LIDENT
) {
if (cmdad
!= (caddr_t
) 0) {
cp
->cmdbuf
[cp
->v_fill
] = cmdad
;
if( ++cp
->v_fill
>= VC_CMDBUFL
) cp
->v_fill
= 0 ;
if(cp
->v_fill
== cp
->v_empty
) {
vpanic("vc: CMD Q OVFLO") ;
if(cp
->v_cmdsem
&& cp
->v_curcnt
< vcx
[n
].v_maxcmd
) {
vinthandl(n
, ((V_BSY
| CMDquals
) << 8) | V_INTR
) ;
* VIOC acknowledge interrupt. The VIOC has received the new
* command. If no errors, the new command becomes one of 16 (max)
* current commands being executed.
register n
; /* VIOC number */
register struct vblok
*vp
;
register struct vcmds
*cp
;
if (vxtype
[n
]) { /* Its a BOP */
printf("vack: interrupt from BOP at VIOC%d,1st vector.\n",n
);
vbrall(n
); /* Int. from BOP, port 0 */
if( vp
->v_vcid
& V_ERR
) {
printf ("INTR ERR type = %x VIOC = %x, v_dcd: %lx\n",
vp
->v_vcid
& 07, n
, vp
->v_dcd
& 0xff);
/* resp = (char *)vp + (vp->v_rspoff & 0x7FFF); */
resp
= (char *)(&vcx
[n
])->v_mricmd
;
printf("%x ", resp
[i
]&0xff);
vpanic( "\nvcc: vackint") ;
if((vp
->v_hdwre
&017) == CMDquals
) {
if (vxintr4
& VXERR4
) { /* causes VIOC INTR ERR 4 */
register struct vxcmd
*cp1
;
register struct vxcmd
*cp0
= (struct vxcmd
*)
((long)cp
->cmdbuf
[cp
->v_empty
] - 4);
if ((cp0
->cmd
== XMITDTA
) || (cp0
->cmd
== XMITIMM
)) {
(void) vcmd(n
,&cp1
->cmd
);
cp
->v_curcmd
[vp
->v_vcid
& VCMDLEN
-1] = cp
->cmdbuf
[cp
->v_empty
] ;
if( ++cp
->v_empty
>= VC_CMDBUFL
) cp
->v_empty
= 0 ;
if( ++cp
->v_itrempt
>= VC_IQLEN
) cp
->v_itrempt
= 0 ;
(void) vcmd(n
, (caddr_t
)0); /* queue next cmd, if any */
* Command Response interrupt. The Vioc has completed
* a command. The command may now be returned to
* the appropriate device driver .
register struct vblok
*vp
;
register struct vcmds
*cp
;
if (vxtype
[n
]) { /* Its a BOP */
printf("vcmdrsp: stray interrupt from BOP at VIOC%d...\n",n
);
resp
+= vp
->v_rspoff
& 0x7FFF;
if( (k
=resp
[1]) & V_UNBSY
) {
cp
->v_curcmd
[k
] = (caddr_t
)0;
k
= *((short *)&resp
[4]); /* cmd operation code */
if((k
& 0xFF00) == LIDENT
) { /* want hiport number */
for(k
=0; k
<VRESPLEN
; k
++)
vxxint(n
, (struct vxcmd
*)cmd
) ;
if ((&vcx
[n
])->v_state
== V_RESETTING
) return;
vpanic( "vc, cmdresp debug") ;
vinthandl(n
, ( (V_BSY
| RSPquals
) << 8 ) | V_INTR
) ;
register struct vblok
*vp
;
if (vxtype
[n
]) { /* Its a BOP */
printf("vunsol: stray interrupt from BOP at VIOC%d...\n",n
);
if(vp
->v_uqual
& V_UNBSY
) {
vinthandl(n
, ( (V_BSY
| UNSquals
) << 8 ) | V_INTR
) ;
vpanic("vc: UNSOL INT ERR") ;
register struct vcmds
*cp
;
register int empflag
= 0 ;
if( cp
->v_itrfill
== cp
->v_itrempt
) empflag
++ ;
cp
->v_itrqueu
[cp
->v_itrfill
] = item
;
if( ++cp
->v_itrfill
>= VC_IQLEN
) cp
->v_itrfill
= 0 ;
if(cp
->v_itrfill
== cp
->v_itrempt
) {
vpanic( "vc: INT Q OVFLO" ) ;
else if( empflag
) vintempt(n
) ;
register struct vcmds
*cp
;
register struct vblok
*vp
;
if(vp
->v_vioc
& V_BSY
) return ;
if(cp
->v_itrempt
== cp
->v_itrfill
) return ;
item
= cp
->v_itrqueu
[cp
->v_itrempt
] ;
intr
= (short *)&vp
->v_vioc
;
switch( (item
>> 8) & 03 ) {
case CMDquals
: /* command */
if(cp
->v_empty
== cp
->v_fill
|| vp
->v_vcbsy
&V_BSY
)
(&vcx
[n
])->v_mricmd
= (caddr_t
)cp
->cmdbuf
[cp
->v_empty
];
phys
= vtoph((struct proc
*)0, (unsigned)cp
->cmdbuf
[cp
->v_empty
]) ; /* should be a sys address */
vp
->v_vcp
[0] = ((short *)&phys
)[0];
vp
->v_vcp
[1] = ((short *)&phys
)[1];
case RSPquals
: /* command response */
case UNSquals
: /* unsolicited interrupt */
/* start a reset on a vioc after error (hopefully) */
register struct vblok
*vp
;
register struct vxcmd
*cp
;
if (xp
->v_state
&V_RESETTING
)
* Avoid infinite recursion.
* Zero out the vioc structures, mark the vioc as being
* reset, reinitialize the free command list, reset the vioc
* and start a timer to check on the progress of the reset.
bzero((caddr_t
)&v_cmds
[n
], (unsigned)sizeof (struct vcmds
));
bzero((caddr_t
)xp
, (unsigned)sizeof (struct vcx
));
* Setting V_RESETTING prevents others from issuing
* commands while allowing currently queued commands to
xp
->v_state
|= V_RESETTING
;
for(j
=0; j
<NVCXBUFS
; j
++) /* init all cmd buffers */
cp
= &xp
->vx_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 */
printf("resetting VIOC %x .. ", n
);
vp
->v_hdwre
= V_RESET
; /* reset interrupt */
timeout(vxinreset
, (caddr_t
)n
, hz
*5);
/* continue processing a reset on a vioc after an error (hopefully) */
register int n
= (int)vioc
;
register struct vblok
*vp
;
* See if the vioc has reset.
if (vp
->v_fault
!= VREADY
) {
* Send a LIDENT to the vioc and mess with carrier flags
* on parallel printer ports.
* Restore modem control, parameters and restart output.
* Since the vioc can handle no more then 24 commands at a time
* and we could generate as many as 48 commands, we must do this in
* phases, issuing no more then 16 commands at a time.
/* finish the reset on the vioc after an error (hopefully) */
register struct vxcmd
*cp
;
register struct vblok
*vp
;
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
= n
; /* assign VIOC-X board number */
xp
->v_state
&= ~V_RESETTING
;
* Restore modem information and control.
for(i
=xp
->v_loport
; i
<=xp
->v_hiport
; i
++) {
if (tp
->t_state
&(TS_ISOPEN
|TS_WOPEN
)) {
tp
->t_state
&= ~TS_CARR_ON
;
vcmodem(tp
->t_dev
, VMOD_ON
);
if (tp
->t_state
&TS_CARR_ON
) {
wakeup((caddr_t
)&tp
->t_canq
) ;
if(tp
->t_state
& TS_ISOPEN
) {
ttyflush(tp
, FREAD
|FWRITE
);
wakeup((caddr_t
)&tp
->t_state
) ;
if((tp
->t_flags
&NOHANG
)==0) {
gsignal(tp
->t_pgrp
, SIGHUP
) ;
gsignal(tp
->t_pgrp
, SIGCONT
);
* If carrier has changed while we were resetting,
* take appropriate action.
if (on
&& (tp
->t_state
&TS_CARR_ON
) == 0) {
tp
->t_state
|= TS_CARR_ON
;
wakeup((caddr_t
)&tp
->t_canq
) ;
} else if (!on
&& tp
->t_state
&TS_CARR_ON
) {
tp
->t_state
&= ~TS_CARR_ON
;
if(tp
->t_state
& TS_ISOPEN
) {
ttyflush(tp
, FREAD
|FWRITE
);
wakeup((caddr_t
)&tp
->t_state
) ;
if((tp
->t_flags
&NOHANG
)==0) {
gsignal(tp
->t_pgrp
, SIGHUP
) ;
gsignal(tp
->t_pgrp
, SIGCONT
);
xp
->v_state
|= V_RESETTING
;
timeout(vxrestart
, (caddr_t
)n
, hz
);
* Restore a particular aspect of the VIOC.
register struct tty
*tp
, *tp0
;
register int n
= (int)vioc
;
printf("vxrestart %d ",cnt
);
xp
->v_state
&= ~V_RESETTING
;
for(i
=xp
->v_loport
; i
<=xp
->v_hiport
; i
++) {
tp
->t_state
&= ~(TS_BUSY
|TS_TIMEOUT
);
if(tp
->t_state
&(TS_ISOPEN
|TS_WOPEN
)) /* restart pending output */
if (tp
->t_state
&(TS_WOPEN
|TS_ISOPEN
))
xp
->v_state
|= V_RESETTING
;
timeout(vxrestart
, (caddr_t
)(n
+ 1*256), hz
);
vxstreset(minor(dev
)>>4); /* completes asynchronously */
if (n
< 0 || n
> NVX
|| VBAS(n
) == NULL
)
vcx
[n
].v_state
&= ~V_RESETTING
;
return(0); /* completes asynchronously */