PGM VMIDRIV
REL
************************************************************
* *
* Device driver for the Logica VTS VMI-1 intelligent *
* multibus ring (Polynet) interface. *
* *
************************************************************
MPICMSK EQU #C2
V.DEMPTY EQU #40
ERRVEC EQU #3FC
VMICTRL EQU #50
VMIDATA EQU #51
*
* Pkt types
*
A.TELL EQU 979
A.AHA EQU 978
A.INIT EQU 977
A.CLEAR EQU 976
*
* DCB symbols
*
* 0 device driver ptr (BCPL)
* 2 link to code (=0)
* 4
D.ID EQU 6 id
D.WKQ EQU 8 work q
D.START EQU 10 start rtn for qpkt
D.STOP EQU 14
D.CALL EQU 18
D.INT EQU 20
D.I EQU D.CALL+6
D.VEC EQU 24
*
* Pkt sumbols
P.ID EQU 2
P.TYPE EQU 4
P.RES1 EQU 6
P.RES2 EQU 8
P.A1 EQU 10
P.A2 EQU 12
*
* The Rootnode
*
CRNTSK EQU #506
DEVMVP EQU #51A
DEVINT EQU #51E
DEVRET EQU #522
*
DW VMINITI init. routine
DW VMUNINI unin. routine
*
* Initialisation routine,
* entry: BX = MC DCB address
* preserve: DX,DI,BP
VMINIT MOV D.START(BX),!VMISTART
MOV D.STOP(BX),!VMISTOP
MOV D.START+2(BX),CS
MOV D.STOP+2(BX),CS
*
MOV D.INT(BX),!VMINT CALLS offset
MOV D.INT+2(BX),CS
MOV SI,D.VEC(BX) interrupt vector no.
ADD SI,!40
SHL SI
SHL SI
MOV (SI),BX plug int. vec. with CALLS address
ADD (SI),!D.CALL
MOV 2(SI),!0
RETS
*
* Uninitialisation,
* entry: BX = MC DCB address
* preserve: BX
VMUNIN MOV SI,D.VEC(BX) int. vec no.
* disable interrupts
MOV CX,SI
MOV DL,!1
SHL DL,CL
IN MPICMSK
OR AL,DL
OUT MPICMSK
*
ADD SI,!40
SHL SI
SHL SI
MOV AX,ERRVEC
MOV (SI),AX
MOV AX,ERRVEC+2
MOV 2(SI),AX
RETS
*
* Start routine,
* entry: BX = MC DCB address
* SI = BCPL pkt address
* return: non-zero
* preserve: BP,DI
*
VMISTART SHL SI MC pkt addr
MOV D.WKQ(BX),!0 clear work q
MOV AX,P.TYPE(SI)
CMP AX,!A.CLEAR
JNE VMI0
* clear interrupt by reading control port
IN VMICTRL
JMP RPKT
*
VMI0 CMP AX,!A.TELL
JNE VMI1
* interrupt the VMI-1
OUT VMIDATA
JMP RPKT
*
VMI1 CMP AX,!A.AHA
JNE VMI2
* pkt to pick up signal from VMI-1,
* is there one pending?
CMP PENDFLG,!0
JE VMI10 not pending
* is one, return pkt
MOV PENDFLG,!0 clear flag
JMP RPKT
*
VMI10 MOV AHAPKT,SI save MC pkt addr (only one)
RETS
*
VMI2 CMP AX,!A.INIT
JE VMI3
JMP RPKT return junk pkt
* perform initialisation, arg1 is byte offset of shared memory
VMI3 OUT VMICTRL reset the b****r
* write the start address
MOV AX,P.A1(SI)
CALL SVMI writes AL
MOV AX,P.A1(SI)
MOV AL,AH
CALL SVMI
XOR AL,AL
CALL SVMI
CALL SVMI
*
MOV AHAPKT,!0
MOV PENDFLG,!0
MOV P.RES1(SI),!0 result is 0
MOV CL,D.VEC(BX)
* enable ints.
MOV DL,!1
SHL DL,CL
NOT DL
IN MPICMSK
AND AL,DL
OUT MPICMSK
*
* return pkt to sender
RPKT MOV CX,D.ID(BX)
MOV BX,CRNTSK
SHL BX
JIS DEVMVP & return from this routine
*
* Stop
*
VMISTOP RETS
*
* Interrupt service,
* return aha pkt or set flag.
VMINT PUSH BX
PUSH AX
PUSH CX
PUSH DX
PUSH SI
MOV BX,SP
MOV BX,10(BX) get old IP pointing into DCB
*
MOV SI,AHAPKT
OR SI,SI exists ahapkt?
JE VMINA no
* return aha pkt
MOV AHAPKT,!0
MOV PENDFLG,!0
MOV CX,D.ID-D.I(BX)
MOV BX,CRNTSK
SHL BX
CIS DEVMVP
JIS DEVINT
* set pending flag
VMINA MOV PENDFLG,!1
JIS DEVRET quick return
*
* Svmi routine sends init. data to VMI-1 from AL.
SVMI MOV AH,AL save
S0 IN VMICTRL
TEST AL,!V.DEMPTY
JE S0 not ready
MOV AL,AH
OUT VMIDATA write
RET
*
EVEN
DSEG
VMINITI DW VMINIT
DW 0
VMUNINI DW VMUNIN
DW 0
*
PENDFLG DW 0
AHAPKT DW 0
*
END