þ a‹R þ w =þ mP9     þ hý	 o<   þ nSystem-wide$TITLE ('New GPiB Device Driver  8/20/82')
$DEBUG

NAME GPiBdriver

;DATE : AUGUST 27, 1982
;AUTHOR : KATHY WHEELER
;REVISION DATE : 1) August 30,1982
;                2) September 7, 1982
;                3) September 8, 1982
;                4) September 21, 1982
;                5) September 22, 1982
;                6) September 23, 1982
;                7) September 24, 1982
;                8) September 27, 1982
;                9) September 29, 1982
;               10) October 5, 1982
;               11) October 5, 1982
;               12) October 7,1982
;               13) November 19, 1982
;               14) March 11, 1983
;               15) June 4, 1983
;               16) December 10, 1983
;               17) January 11, 1983
;               18) January 11, 1983
;               19) May 14, 1984
;REVISION AUTHOR : Kathy Wheeler
;REASON: 1) Add o/s routines for interrupt management and
;watchdog timer. 2) Make watchdog timer work, put in deacti-
;vate. 3) Fix SRQ bug (check 6th bit to see if this is de-
;vice that is SRQing) and fix interrupt read to do any
;length string.  4) Self-modifying code to fix the movsb
;problem - Dave P. made me do it.  5) Fix the multi-tasking
;hanging problem by getting rid of a spurious errorcode re-
;turn in GPiBSPOLL.  6) Fix the watchdog timer handling rou-
;tine so that is will implement the self-modifying code of
;DMAread (remember, Dave P. made me do it).  7) make the 
;watchdog timer routine work. Check the errorcode in PUT-
;ERROR to see if previously set.  Reset watchdog as soon as
;you enter the DMAtimeout routine.  8) Put in version string
;for identification purposes and set up semaphore around
;bbiidriver.  9) Make the SRQ non-interruptable while in the
;driver (interruptable while outside) because of background
;task interference and remove re-init procedure after en-
;countering an error during a transfer. 10) Make the watch-
;dog timeout the max amount.  For SetStat, mode0, make sure
;that the selective device clear does not do a PUTERROR (see
;if this is causing the gpib on the compass side to hang.
;11) Put in an cpDelay call following a Signal Semaphore to
;see if that will speed up the driver. 12) Reset the inter-
;face upon reception of SetStatus mode0 (specific device
;clear) and re-init following an error on the bus. 13) The
;BX register in the Selective Device Clear routine of GPiB
;SETSTATUS is overwritten by mistake.  Replace BX with the
;DX register when setting the GPiBioSEG.  14) Replace Os
;calls with Cp calls for compatibility with os.  15) Repair
;faulty jumps in GPiBSPoll.  16) I screwed around with the
;code trying to fix the faulty interrupt problem.  I neglect
;ed to back up this version, before doing so.  I think this
;code is fine, but no guarantees.  17) Multi-tasking bug
;found in GridServer GPiB version.  In interrupt service
;routine, gpib ints need to be enabled before the OsDelay of
;zero to prevent losing interrupt.   18) This version is for
;the splitboard Compass.  The movsb buffer location of
;0e000:0 changes to 0dfa0:0.  19) Changed the EQU 'GPiBdma-
;SEG' to a SEGMENT variable to be set at locate time of the
;PROM code.

;GRiD CORPORATION, PROPRIETOR

;GPiB Device Driver Overview:

;This module is the INGRiD interface to the GPiB bus.  As a
;device driver, its interface to the operating sytem is a 
;procedure of the format:

;  OsDevice : PROCEDURE (req, pCB, pError);

;where pCB points to a control block and pError points to a
;place to put the error and req(uest) is a word.

;GPiB driver performs the following functions on the GPIB
;bus:

;   1. Data Transfers in the following modes:
;        - Hi-speed (pseudo DMA) with binary data
;        - Lo-speed (interrupt driven) with binary data
;        - Lo-speed (interrupt driven) with ASCII data
;   2. Service request
;   3. Serial Poll
;   4. Micro-command

;The GPiB driver intitializes as a Controller in Charge / 
;Talker / Listener.  In consequence, it assumes that there
;are no other Controller in Charge's on the GPiB bus at
;power-up time.
;Upon entry to the GPiB driver the "req" is decoded and the
;function performed.  In consequence, there are four main
;routines to process the requests:

;   1. GPiBinit
;   2. GPiBread
;   3. GPiBwrite
;   4. GPiBsetstatus

;Any other request is not supported by the GPiB driver.  
$EJ
; ********************************************************
; *** START OF CODE **************************************
; ********************************************************



;*** GPIB DRIVER EXTERNALS ********************************

EXTRN   CpCreateSemaphore:FAR
EXTRN   CpWait:FAR
EXTRN   CpSignal:FAR
EXTRN   CpDelay:FAR
EXTRN   CpEnableInterrupt:FAR
EXTRN   CpDisableInterrupt:FAR
EXTRN   CpSetInterrupt:FAR
EXTRN   CpEndOfInterrupt:FAR
EXTRN   CpSetWatchdogHandler:FAR
EXTRN   CpCatchAll:FAR

;Procedural and functional interfaces to the above OS calls:

;CpCreateSemaphore:PROCEDURE (sid) CLEAN;
;  DCL sid SELECTOR;
;  END;

;CpWait:PROCEDURE (sid, timelimit, pError) WORD CLEAN;
;  DCL sid SELECTOR; 
;  DCL timelimit WORD;
;  DCL pError PTR;
;  END;

;CpSignal:PROCEDURE (sid, mode, note, pError) CLEAN;
;  DCL sid SELECTOR;
;  DCL mode BYTE;
;  DCL note WORD;
;  DCL pError PTR;
;  END;

;CpDelay:PROCEDURE (timelimit) CLEAN;
;  DCL timelimit WORD;
;  END;

;CpEnableInterrupt:PROCEDURE (interruptID, mode) CLEAN;
;  DCL (interrupt, mode) BYTE;
;  END;

;CpDisableInterrupt:PROCEDURE (interruptID) CLEAN;
;  DCL interruptID BYTE;
;  END;

;CpSetInterrupt:PROCEDURE (interruptID, pRoutine) PTR CLEAN;
;  DCL interruptID BYTE;
;  DCL pRoutine PTR;
;  END;

;CpEndOfInterrupt:PROCEDURE (interruptID) CLEAN;
;  DCL interruptID BYTE;
;  END;

;CpSetWatchdogHandler:PROCEDURE (pRoutine) PTR CLEAN;
;  DCL pRoutine PTR;
;  END;

;CpCatchAll:PROCEDURE (command, theData) WORD CLEAN;
;  DCL (command, theData) WORD;
;  END;

;*** GPIB DEVICE DRIVER PUBLICS ***************************

PUBLIC    GPiBdriver
PUBLIC    SEMAdisk
PUBLIC    SMCmove
PUBLIC    GPiBversion
PUBLIC    SEMAdiskgetin
$EJ
;**************************************************
; *** DATA SEGMENT DECLARATIONS **************************

DGROUP GROUP DATA
CGROUP GROUP CODE
DATA SEGMENT PUBLIC 'DATA'

; Create a structure for the control block sent to the GPiB-
; driver by the calling process:

paramlist STRUC

  connection  DW  ?
  pBuffer     DD  ?
  position    DD  ?
  pLength     DW  ?
  mode        DB  ?
  drive       DB  ?
  intAddr     DB  ?
  pOverflow   DD  ?

paramlist ENDS

;Allocate storage for useful parameters used by GPiB device
;driver:

request       DW  0    ; request from application
pCBlock       DD  0    ; pointer to parameter list
ErrorPtr      DD  0    ; pointer to location to place error
Time          DW  0    ; holding reg for timeout figure
AllRdy_Init   DB  0    ; flag for initing procs once 
Service       DB  0    ; flag for Service Req pending
InXfer        DB  0    ; flag for BI interrupt
INTdone       DB  0    ; flag when int service routine done
reinit        DB  0    ; flag for reiniting bus after error
asyncSRQ      DB  0    ; flag for srqs outside of gpibdriver
SignalErr     DW  0    ; place to put error on OsSignal
DMAeoiORerr   DW  0    ; dmaread interrupt for EOI
eoiReceived   DW  0    ; received eoi during dmaread

;Create a table of words for the GPIB device SIDS:

DeviceSID     DW  32 DUP (0)
DevSIDenb     DD  0    ; bit map for enb/dsbl of srq devices

;Create a table of SID codes for semaphores used in GPiB 
;driver:

SEMAentry     DW  0    ; semaphore for GPiBdriver
SEMAdata      DW  0    ; semaphore for waiting on data i/o

;Create an area of bytes for self-modifying code to imple-
;ment the movsb instruction for the dma-read.

SMCmove       LABEL FAR

SMCstorage    DB  3 DUP (0) ;room for "rep movsb, ret" or
                            ;"nop, nop, ret"
;
DATA ENDS
;
; *** END OF DATA SEGMENT *********************************
;**********************************************************
$EJ
;**********************************************************
;
; Declaration of MOVSB buffer SEGMENT
;
;**********************************************************


GPiBdmaSEG     SEGMENT      ;segment for dma move to/from
                            ;9914A for splitboard compass

GPiBdmaSEG     ENDS
$EJ
;
;**********************************************************
; *** START OF STACK SEGMENT ******************************
;
STACK SEGMENT STACK 'STACK'
;
STACK ENDS
;
; *** END OF STACK SEGMENT ********************************
;**********************************************************
;
;**********************************************************
; *** ENTRY to GPiBdriver Semaphore Declaration ***********
;
SEMAsegA  SEGMENT PARA 'DATA'
;
SEMAphoreA   DB 16 DUP (?)
;
SEMAsegA  ENDS
;
;**********************************************************

;**********************************************************
; *** GPiB Data Semaphore Declaration *********************
;
SEMAsegB  SEGMENT PARA 'DATA'
;
SEMAphoreB   DB 16 DUP (?)
;
SEMAsegB  ENDS
;
;**********************************************************

;**********************************************************
; *** OsDskDriver Semaphore Declaration *******************
;
SEMAsegC  SEGMENT PARA 'DATA'
;
SEMAdisk   DB 16 DUP (?)
;
SEMAsegC  ENDS
;
;**********************************************************

;**********************************************************
; *** Entrance to BBiiDriver Semaphore Declaration ********
;
SEMAsegD  SEGMENT PARA 'DATA'
;
SEMAdiskgetin   DB 16 DUP (?)
;
SEMAsegD  ENDS
;
;**********************************************************
$EJ
;
;**********************************************************
; *** START OF CODE SEGMENT *******************************
;
CODE SEGMENT PUBLIC 'CODE'
ASSUME CS:CGROUP, DS:DGROUP, SS:STACK
;
;Setup an ASCII string to declare the version number of this
;GPiB device driver:

GPiBversion    DB 'GPiB 1.1 11/19/82'

; *** MODULE EQUATES **************************************
;
;REQUEST CODES:

ddInit         EQU 0
ddRead         EQU 4
ddWrite        EQU 5
ddSetStat      EQU 20
ddDeactivate   EQU 21
;
;
;ERROR CODES:

eOK            EQU 0
eNotSupport    EQU 23
eGPiBnotResp   EQU 452
eGPiBtimeout   EQU 451
eGPiBoutofmem  EQU 453    ;??????
;
interruptStat  EQU 0H
readISR        EQU 09H

;
;TI-9914A READ/WRITE REGISTERS:

;READ REGISTERS:

INT0           EQU 0
INT1           EQU 2
BUSSTAT        EQU 6
DATAIN         EQU 0EH

;WRITE REGISTERS:

INTM0          EQU 0
INTM1          EQU 2
AUXCMD         EQU 6
DATAOUT        EQU 0EH
DATAOUT2       EQU 1EH

GPiBioSEG      EQU 0dff8h   ;segment of 9914A port

;INTERRUPT CONTROLLER - 80130:

INTGPiBid      EQU 1        ;interruptID for CpRoutines
INTGPiBmode    EQU 0        ;edge triggered

;Keyboard Watchdog Timer EQUATES:

WDenable       EQU 106h     ;enable watchdog timer
WDdisable      EQU 06h      ;disable watchdog timer
WDinterval     EQU 11       ;set timeout interval
WDtimeout      EQU 0ffh     ;timeout period (4 secs)

;GPiB MESSAGE EQUATES:

UNL            EQU 3FH      ;unlisten
UNT            EQU 5FH      ;untalk
SPE            EQU 18H      ;serial poll enable
SPD            EQU 19H      ;serial poll disable
SELDEVCLR      EQU 04H      ;selective device clear
DEVCLR         EQU 14H      ;universal device clear

;GPiB COMMANDS:

tcs            EQU 0DH
tca            EQU 0CH
gts            EQU 0BH
ton            EQU 8AH
lon            EQU 89H
diston         EQU 0AH
dislon         EQU 09H
rst            EQU 80H
clrrst         EQU 0H
sic            EQU 8FH
clrsic         EQU 0FH
seoi           EQU 08H
pts            EQU 16H

;GPiB MASK FOR INTERRUPTS:

THEEND         EQU 08H
EOI            EQU 08H
BIN            EQU 20H
BOUT           EQU 10H
ERR            EQU 40H
DAV            EQU 40H
NDAC           EQU 20H
SRQ            EQU 02H

INTM0_RD       EQU 28H   ;BI, END
INTM0_WT       EQU 18H   ;BO, END
INTM1_WT       EQU 40H   ;ERR
INTM0_DMA      EQU 08H   ;END
INTM1_DMA      EQU 40H   ;ERR

; GENERAL EQUATES:

TRUEW          EQU 0FFFFH
FALSE          EQU 0H
TRUE           EQU 0FFH

; MODES FOR SET STATUS REQUESTS:

MODE0          EQU 0H
MODE1          EQU 1H
MODE2          EQU 2H
NOW            EQU 01H
LATER          EQU 81h
$EJ 
;**********************************************************
;*** MAIN MODULE - GPiBdriver *****************************
;*** High level software interface to the device driver.
;*** PLM procedural interface:
;***
;***   GPiBdriver : PROCEDURE (req, pCB, pError);
;***
;*** The initial code of the module is gated with a sema-
;*** phore to prevent more than one call to the interface.
;***
;*** Input: req, pCB
;***
;*** Output: pError
;**********************************************************

GPiBdriver   PROC   FAR

             push   DS               ;save seg from call
             mov    AX,DATA          ;get this modules seg
             mov    DS,AX
             mov    AL,AllRdy_Init   ;initialized already?
             cmp    AL,TRUE
             jne    GETPARAMS        ;no, get call's params
             push   SEMAentry        ;gate for the driver
             mov    CX,TRUEW
             push   CX               ;infinite timeout
             push   BP
             mov    BP,SP
             mov    CX,[BP+0ch]      ;offset to error
             mov    BX,[BP+0eh]      ;segment to error ptr
             pop    BP               ;*this is the error ptr
             push   BX               ;for the next process
             push   CX               ;to go thru the driver*
             call   CpWait

GETPARAMS:   pop    BX               ;DS of call
             pop    CX               ;return CS
             pop    DX               ;return IP
             pop    Word Ptr ErrorPtr ;ptr to error location
             pop    Word Ptr ErrorPtr+2
             pop    Word Ptr pCBlock ;ptr to paramlist struc
             pop    Word Ptr pCBlock+2
             pop    request          ;call's request
             push   DX
             push   CX
             push   BX
             push   BP               ;save environment
             mov    BP,SP

; Start of GPiBdriver functionality (decode of requests):

             call   GETERROR        ;see if error occurred
             or     AX,AX
             jnz    STUBRET         ;error on wait
             mov    AX,request
             cmp    AX,ddInit        ;is req=initialize?
             je     GPiBINIT         ;yes
             mov    BL,reinit        ;init because of error?
             cmp    BL,TRUE
             je     GOINIT           ;yes
             mov    BL,AllRdy_Init   ;driver initialized?
             cmp    BL,TRUE
             je     CHKREQ           ;yes
GOINIT:      jmp    GPiBinit         ;no, initialize

CHKREQ:      cmp    AX,ddRead        ;read from GPIB?
             jne    CHKREQ2          ;no
             jmp    GPiBREAD         ;yes

CHKREQ2:     cmp    AX,ddWrite       ;write to GPIB
             jne    CHKREQ3          ;no
             jmp    GPiBWRITE        ;yes

CHKREQ3:     cmp    AX,ddSetStat     ;set status for GPIB?
             jne    CHKREQ4          ;no
             jmp    GPiBSETSTAT      ;yes

CHKREQ4:     cmp    AX,ddDeactivate  ;deactivate a device?
             jne    STUBERR          ;no, don't support
             push   DS
             lds    BX,pCBlock       ;get parameter block
             les    DI,[BX].pOverflow ;get overflow block
             mov    ES:Byte Ptr[DI],MODE2 ;tell set status
                                     ;that we're doing a set
                                     ;srq.  We're really re-
                                     ;setting the srq.
             pop    DS
             jmp    GPiBSETSTAT      ;go and reset device

STUBERR:     mov    AX,eNotSupport
             call   PUTERROR         ;report error

STUBRET:     mov    AX,DATA
             mov    DS,AX
             call   GETERROR
             push   DI
             push   ES
             push   AX               ;save possible error
             mov    BX,SEMAentry     ;make gate open
             mov    CX,NOW           ;signal is on event
             xor    AX,AX            ;note=0000h
             call   SIGNALSEMA
             pop    AX
             pop    ES               ;no,get error from op
             pop    DI
             or     AX,AX            ;was op OK?
             jz     STUBRET2         ;yes,keep err from sig
             mov    ES:[DI],AX       ;put error code in ptr
STUBRET2:    call   GETERROR
             or     AX,AX            ;error?
             jz     STUBRET3         ;no
             mov    reinit,TRUE      ;yes, reinit
STUBRET3:    pop    BP
             pop    DS
             ret                     ;return to call


$EJ
;**********************************************************
;*** GPiBINIT Module **************************************
;*** Initialize the TI-9914A. Then determine if this is the
;*** first initialization pass. If it is, then fork the 
;*** GPiBintserv and GPiBtimeout routines.  Also, create the
;*** semaphores for the program.  If it is not the first
;*** initialization pass, then the interface may be initia-
;*** lized because there was an error with the previous op-
;*** eration that passed through.  If that occurred, then
;*** the interface is reinitialized and the program goes 
;*** back to GPiBdriver to perform the request.
;***
;*** Inputs : req, pCB
;***
;*** Outputs : pError
;***
;**********************************************************

GPiBINIT     LABEL  NEAR

             mov    AX,eOK
             call   PUTERROR         ;assume init will be ok
             mov    AX,GPiBioSeg     ;seg for 9914A
             mov    ES,AX
             mov    DI,AUXCMD        ;offset for cmd reg
             mov    ES:Byte Ptr[DI],rst
             mov    ES:Byte Ptr[DI],sic
             mov    ES:Byte Ptr[DI],clrrst
             mov    CL,78h           ;delay for reset op
             shr    CL,CL
             mov    ES:Byte Ptr[DI],clrsic
             mov    ES:Byte Ptr[DI],ton    ;in talker state
             call   CHKBOUT          ;go and see if ok
             or     AX,AX            ;any error?
             jz     INIT1            ;no
             call   PUTERROR         ;yes
             jmp    STUBRET

INIT1:       mov    ES:Byte Ptr DATAOUT,DEVCLR ;to send clr

             mov    AX,1f4h          ;delay for .5 seconds
             push   AX               ;so, disk can process
             call   CpDelay          ;the device clear
             cmp    AllRdy_Init,TRUE ;GPIB inited once?
             jne    FORKMODS         ;no, do fork of procs
             cmp    reinit,TRUE      ;previous error?
             je     INIT2            ;yes
             jmp    STUBRET          ;no
INIT2:       mov    reinit,FALSE     ;reset flag
             mov    AX,request       ;get request
             jmp    CHKREQ           ;go do request

FORKMODS:    mov    AllRdy_Init,TRUE ;make flag true
;
; create semaphores for the driver
;
             mov    AX,SEG SEMAphoreA ;get allocated segment
             mov    SEMAentry,AX      ;save it
             push   AX
             call   CpCreateSemaphore ;go tell os about it
             mov    AX,SEG SEMAphoreB ;get allocated segment
             mov    SEMAdata,AX       ;save it
             push   AX
             call   CpCreateSemaphore
;
; set the interrupt service routine address in the vector
; table
;
             mov    AX,INTGPiBid
             push   AX
             mov    AX,CODE
             push   AX
             mov    AX,Offset GPiBint
                                     ;offset = int serv rou
             push   AX
             call   CpSetInterrupt

             mov    AX,CODE          ;setup watchdog timer
             push   AX               ;routine
             mov    AX,Offset DMAtimeout
             push   AX
             call   CpSetWatchdogHandler

             mov    AX,request       ;request=init
             or     AX,AX
             jz     MAKSIDEND        ;yes
             jmp    CHKREQ           ;no, do request
MAKSIDEND:   jmp    STUBRET          ;end of init routine
$EJ
;**********************************************************
;*** GPiBREAD Module **************************************
;*** The function of this module is to read from a device
;*** on the GPIB bus into a buffer pointed to by pBuffer in 
;*** the paramlist structure.  The data transfer can be 
;*** pseudo-DMA or interrupt driven (binary or ASCII data).
;***
;*** Inputs : pCB
;***
;*** Outputs : pError
;***
;**********************************************************

GPiBREAD     LABEL  NEAR

             call   SETUP
                                     ;AL = intAddr
                                     ;AH = datamode
                                     ;ES = ErrorPtr
                                     ;DS = DATA
             mov    request,0        ;make 0 for int routine
             or     AL,40H
             or     AH,AH             ;is it DMA mode?
             jnz    READ1            ;no
             jmp    DMAREAD          ;pseudo-DMA mode

READ1:       mov    DL,INTM0_WT
             mov    DH,INTM1_WT
             call   SETUPINTS         ;enable interrupts
             call   XFERCHAR          ;send out address
             call   RSTCTRL           ;set up to listen
;
; Set up 9914 int mask registers for BI,ERR,END,SRQ

             mov    DL,INTM0_RD
             mov    DH,INTM1_WT
             call   SETUPINTS
             push   DS
             lds    BX,pCBlock
             les    SI,[BX].pOverflow
             mov    DH,ES:Byte Ptr[SI+1] ;get EOSChar
             mov    CX,[BX].plength   ;get supposed count
             les    SI,[BX].pBuffer   ;seg and off of buffer
             pop    DS
             mov    DS:Byte Ptr InXfer,TRUE      ;dont send
                                                 ;   char
             
READLOOP:    call   XFERCHAR          ;wait for int
             push   ES
             mov    BX,GPiBioSEG
             mov    ES,BX
             mov    DL,ES:Byte Ptr DATAIN ;get receive byte
             pop    ES
             
; AL contains INT1 register

             call   SETINTR           ;set gpib ints
             test   AL,THEEND         ;did we get an EOI?
             jnz    READEND           ;yes
             cmp    DH,TRUE           ;EOS enabled?
             je     CHKCNT            ;no
             cmp    DL,DH             ;this char = EOS?
             je     READEND           ;yes
CHKCNT:      dec    CX                ;dec count
             jz     OvrFlow           ;if not zero, loop
             mov    ES:Byte Ptr[SI],DL ;put in pBuffer
             inc    SI                ;inc buff ptr
             jmp    READLOOP

; DL goes into bit bucket on overflow
             
OvrFlow:     inc    CX                ;make CX one more so
             jmp    READLOOP          ;that we loop on ovflo

READEND:     mov    ES:Byte Ptr[SI],DL ;put in pBuffer
             inc    SI
             push   DS
             lds    BX,pCBlock
             les    DI,[BX].pBuffer   ;original ptr
             sub    SI,DI             ;get count read
             mov    [BX].pLength,SI   ;put it into param
             pop    DS
READEND1:    mov    AX,GPiBioSEG
             mov    ES,AX
READEND2:    mov    AL,ES:Byte Ptr BUSSTAT
             test   AL,NDAC           ;look for release of 
             jz     READEND2          ;bus by device
             mov    DI,AUXCMD
             mov    ES:Byte Ptr[DI],tca

; back into controller state

             mov    DS:Byte Ptr InXfer,FALSE ;resetflag
             call   CHKBOUT
             or     AX,AX             ;any error
             jz     READEND3          ;no
             call   PUTERROR          ;yes
             jmp    STUBRET

READEND3:    mov    ES:Byte Ptr[DI],dislon
             mov    ES:Byte Ptr[DI],ton
             mov    ES:Byte Ptr DATAOUT,UNT
             call   GPiBSPOLL       ;see if SRQ occurred
             call   RDWTEND
             jmp    STUBRET         ;end of read

;
; DMAREAD - subroutine to do a pseudo-DMA transfer of data
; over the gbib bus.
;

DMAREAD      LABEL  NEAR

             call   DMASETUP
             call   XFERCHAR          ;send out address
             call   RSTCTRL
             mov    DMAeoiORerr,TRUEW ;make int routine work
             mov    ES:Byte Ptr INTM0,08h
             mov    SI,Offset SMCmove
             mov    Byte Ptr[SI],0f3h   ;setup instruction
             mov    Byte Ptr[SI+1],0a4h ;rep movsb
             mov    Byte Ptr[SI+2],0cbh ;ret
             mov    eoiReceived,0     ;no got eoi yet
             call   SETgpibINT        ;set interrupt
             call   SETwatchdog       ;set watchdog timer
             lds    BX,pCBlock
             mov    CX,[BX].pLength      ;count of transfer
             les    DI,[BX].pBuffer     ;pointer to buffer
             mov    AX,GPiBdmaSEG      ;add of 9914
             mov    DS,AX
             xor    SI,SI             ;read from 0e0000h
             cld                      ;set dir flag to inc

             call   SMCmove              ;put in buffer

             mov    AX,DATA
             mov    DS,AX
ovrfloloop:  mov    AX,eoiReceived
             or     AX,AX             ;have we got eoi?
             jnz    endofstring       ;yes

             push   DS
             mov    AX,GPiBioSEG
             mov    DS,AX
             mov    SI,DATAIN         ;take bytes and put
             mov    AL,[SI]           ;them in bit bucket
             pop    DS
             jmp    ovrfloloop        ;loop til eoi

endofstring: mov    AX,GPiBioSEG
             mov    DS,AX
             mov    AL,DS:Byte Ptr INT0
             test   AL,BIN
             jz     nomorebytes       ;any bytes left?
             mov    AL,DS:Byte Ptr DATAIN ;bad read in movsb
             stosb                    ;yes, get it & store
nomorebytes: mov    AX,DATA
             mov    DS,AX
             mov    DMAeoiORerr,0      ;reset flag
             lds    BX,pCBlock
             mov    SI,Word Ptr[BX].pBuffer ;orig ptr
             sub    DI,SI
             mov    [BX].pLength,DI   ;store count
             mov    AX,DATA
             mov    DS,AX
             call   RSTwatchdog
             jmp    READEND1          ;finish up

$EJ
;**********************************************************
;*** GPiBWRITE MODULE *************************************
;*** This module writes the chunk of data in pBuffer out to
;*** the specified device on the bus in either of two modes:
;*** pseudo-DMA or interrupt driven (binary or ASCII data).
;***
;*** Inputs : pCB
;***
;*** Outputs : pError
;***
;**********************************************************

GPiBWRITE    LABEL  NEAR

             call   SETUP
;AL = intAddr
;AH = datamode
;ES = ErrorPtr
;DS = DATA
             or     AL,20H
             or     AH,AH             ;is it DMA mode?
             jnz    WRITE1            ;no
             jmp    DMAWRITE          ;pseudo-DMA mode

; Setup mask for BO, ERR, EOI, SRQ

WRITE1:      mov    DL,INTM0_WT
             mov    DH,INTM1_WT
             call   SETUPINTS         ;enable interrupts
             call   XFERCHAR          ;send out address
             mov    AX,GPiBioSEG      ;nope
             mov    ES,AX
             mov    ES:Byte Ptr AUXCMD,gts ;control standby
             
             mov    DS:Byte Ptr INTdone,TRUE ;set int flag
             lds    BX,pCBlock
             mov    CX,[BX].pLength   ;count of chars to go
             lds    SI,[BX].pBuffer   ;start of string
             dec    CX                ;make one less
             jz     WRITEND           ;if one char jump over
                                      ;loop and send
             cld

WRITELOOP:   lodsb                    ;get first byte
             call   XFERCHAR          ;send out char in AX
             loop   WRITELOOP         ;loop til count=0

WRITEND:     mov    AX,GPiBioSEG
             mov    ES,AX
             mov    AX,DATA
             mov    DS,AX
             push   DS
             mov    ES:Byte Ptr AUXCMD,seoi ;last char out
             lds    BX,pCBlock
             push   SI
             les    SI,[BX].pOverflow
             mov    AL,ES:Byte Ptr[SI+1] ;EOSchar?
             cmp    AL,TRUE
             pop    SI
             jne    WRITEND1          ;yes, send it
             les    DI,[BX].pBuffer
             mov    AL,ES:Byte Ptr[SI]  ;Get last byte
WRITEND1:    pop    DS
             call   XFERCHAR          ;send out last char
             mov    AX,GPiBioSEG
             mov    ES,AX
WRITEND2:    mov    ES:Byte Ptr AUXCMD,tca
             mov    AL,UNL            ;tell device to
             call   XFERCHAR          ;unlisten
             call   GPiBSPOLL       ;see if srq occurred
             call   RDWTEND
             jmp    STUBRET         ;end of routine
  
DMAWRITE:    
;the following instruction is for debugging

             call    DMASETUP
             call    XFERCHAR         ;send out address
             mov     SI,Offset SMCmove
             mov     Byte Ptr[SI],0f3h   ;setup instruction
             mov     Byte Ptr[SI+1],0a4h ;rep movsb
             mov     Byte Ptr[SI+2],0cbh ;ret
             mov     DMAeoiORerr,TRUEW  ;in dma mode
             mov     eoiReceived,0    ;no got eoi or err yet
             call    SETwatchdog      ;set watchdog timer
             mov     ES:Byte Ptr AUXCMD,gts ;turn off ctrler
             lds     BX,pCBlock
             mov     CX,[BX].pLength 
             les     SI,[BX].pBuffer
             mov     AX,ES
             mov     DS,AX
             mov     AX,GPiBdmaSEG
             mov     ES,AX
             xor     DI,DI          ;destination is 0e0000h
             xor     BX,BX
             CLD              ; set dir flag to increment

; CX CONTAINS COUNT
; SI CONTAINS SOURCE OF STRING
; DI CONTAINS DESTINATION
; BX IS USED AS FLAG

             dec     CX             ; ONE CHAR IN STRING?
             jz      SEND1          ; YES

             call    SMCmove        ; do transfer till zero

SEND1:       mov     BX,DATA
             mov     DS,BX
             mov     DMAeoiORerr,0   ;done with main write
             call    RSTwatchdog    ;reset watchdog timer
             mov     AX,eoiReceived ;did we get an err?
             or      AX,AX
             jnz     errOnWrite     ;yes, watchdog or buserr

             mov     DS:Byte Ptr InXfer,TRUE
             mov     DS:Byte Ptr INTdone,TRUE
             call    SETINTR
             call    XFERCHAR
             lds     BX,pCBlock
             mov     AX,[BX+4]      ;segment of pbuffer
             mov     DS,AX
             mov     AX,GPiBioSEG
             mov     ES,AX
             mov     ES:BYTE PTR AUXCMD,SEOI   
             mov     AL,[SI]
             mov     ES:Byte Ptr DATAOUT,AL ;write byte

             mov     AX,DATA
             mov     DS,AX
             mov     DS:Byte Ptr InXfer,FALSE
             jmp     WRITEND2

errOnWrite:  mov     AX,GPiBioSEG
             mov     ES,AX
             mov     AL,ES:Byte Ptr INT1 ;was it bus err?
             test    AL,ERR
             jz      errOnWrite2     ;no, timeout
             mov     AX,eGPiBnotResp
             call    PUTERROR
errOnWrite2: jmp     WRITEND2       ;go and finish up
$EJ
;**********************************************************
;*** SUBROUTINES FOR GPIBREAD AND GPIBWRITE ***************
;***
;**********************************************************


SETUP        PROC  NEAR

;setup parameters for use in the routine

             push    DS
             mov     asyncSRQ,FALSE ;no async SRQs
             lds     BX,pCBlock     ;get operation params
             mov     AL,[BX].intAddr ;addr of device
             and     AL,01fh        ;mask
             les     SI,[BX].pOverflow ;get other params
             mov     AH,ES:Byte Ptr[SI] ;get data mode
             mov     CX,ES:Word Ptr[SI+3] ;get timeout
             pop     DS
             mov     time,CX
             push    AX
             mov     AX,eOK
             call    PUTERROR       ;assume things go ok
             pop     AX
             mov     DS:Byte Ptr InXfer,FALSE ;set flag null
             ret

;DL = Address
;DH = Data Mode
;ES = ErrorPtr

SETUP        ENDP

;
; DMASETUP is a routine to setup the interrupts and the 
; watchdog timer for the DMA mode of the GPiB driver.
;

DMASETUP     PROC    NEAR

             mov     DL,INTM0_WT

DMASETUP2    PROC    NEAR

             mov     DH,INTM1_DMA
             call    SETUPINTS
             ret                    ;yes, return

DMASETUP2    ENDP
DMASETUP     ENDP

;
; XFERCHAR is a subroutine to wait for the following condi-
; tions on the GPIB bus: BO or ERR.  If neither of these
; two conditions occur then the routine times out.
;

XFERCHAR     PROC   NEAR

             push   DS
             push   ES
             push   CX
             push   SI
             push   DX

             mov    BX,DATA
             mov    DS,BX
             mov    BL,DS:Byte Ptr InXfer
             or     BL,BL
             jnz    XFERCHAR2         ;jump if reading
             mov    BX,GPiBioSeg
             mov    ES,BX
             mov    ES:Byte Ptr DATAOUT, AL ;write char
             call   SETINTR

XFERCHAR2:   push   SEMAdata          ;SID
             push   time              ;timeout
             les    BX,ErrorPtr       ;error pointer
             push   ES
             push   BX
             call   CpWait            ;wait till signal

             pop    DX
             pop    SI
             pop    CX                ;partially pop stack

;
; CHKERRS is a subroutine to check for possible errors foll-
; owing an interrupt return vis CpSignal (SID = Semadata)
;

             mov    AX,DATA
             mov    DS,AX
             call   GETERROR
             or     AX,AX             ;timeout occur?
             jz     CHKERRS2          ;no

XFERROR:     call   PUTERROR
             mov    reinit,TRUE
             pop    ES
             pop    DS
             pop    AX                ;make stack right
             jmp    STUBRET          ;end of routine

CHKERRS2:    mov    AX,SignalErr      ;get error from CpSig
             or     AX,AX             ;jmp if not zero
             jnz    XFERROR
             call   RSTgpibINT        ;reset gpib int
             mov    AX,GPiBioSEG
             mov    ES,AX
             mov    AH,ES:Byte Ptr INT0 ;get status
             mov    AL,ES:Byte Ptr INT1
             test   AL,ERR            ;bus error?
             jz     CHKERRS3          ;no
             mov    AX,eGPiBnotResp
             jmp    XFERROR

CHKERRS3:    test   AL,SRQ            ;service request?
             jz     CHKERRS4          ;no, must be data i/o
             mov    Service,TRUE
                                      ;flag that got SRQ

CHKERRS4:    pop    ES
             pop    DS
             ret                      ;return to call

XFERCHAR     ENDP

;
; CHKBOUT is a short routine to check for the BOUT bit of
; the 9914 interrupt mask
;

CHKBOUT      PROC   NEAR

             xor    AX,AX
             mov    CX,0ffffh         ;sort of a timeout
CHKBOUT2:    mov    BL,ES:Byte Ptr INT0 ;BO set?
             test   BL,BOUT
             jnz    CHKBOUT3          ;BO int occurred, jump
             dec    CX                ;small timeout
             jnz    CHKBOUT2          ;not done
             mov    AX,eGPiBtimeout   ;make error a timeout

CHKBOUT3:    ret

CHKBOUT      ENDP

;
; Subroutine to set the watchdog timer chip
;

SETwatchdog  PROC  NEAR

             push  AX
             push  ES
             push  BX
             mov   AX,WDinterval
             push  AX
             mov   AX,WDtimeout
             push  AX
             call  CpCatchAll
             mov   AX,WDenable
             push  AX
             mov   AX,1
             push  AX
             call  CpCatchAll
             pop   BX
             pop   ES
             pop   AX
             ret

SETwatchdog  ENDP

;
; Subroutine to reset the watchdog timer
;

RSTwatchdog  PROC  NEAR

             push  ES
             push  AX
             push  BX
             mov   AX,WDdisable
             push  AX
             xor   AX,AX
             push  AX
             call  CpCatchAll
             pop   BX
             pop   AX
             pop   ES
             ret

RSTwatchdog  ENDP

;
; Routine to handle the timeout during a dma read or write
;

DMAtimeout   PROC  FAR

             mov   AX,DATA
             mov   DS,AX
             call  RSTwatchdog     ;reset timer right away
             mov   AX,eGPiBtimeout
             call  PUTERROR        ;put timeout error away
             mov   eoiReceived,TRUEW ;tell dma that its done
             mov   AX,SEG SMCmove  ;get segment of movsb
             mov   SI,Offset SMCmove ;get offset of movsb
             mov   DS,AX
             mov   Byte Ptr[SI],90h ;self-modify the code
             mov   Byte Ptr[SI+1],90h ;so that it falls thru
                                    ;and doesn't do movsb
                                    ;(do nops instead)
             ret

DMAtimeout   ENDP

;
; Subroutine to set up for interrupt driven mode
;

SETUPINTS    PROC  NEAR

             mov    DS:Byte Ptr INTdone,TRUE               
             mov    BX,GPiBioSEG
             mov    ES,BX
             mov    ES:Byte Ptr INTM0,DL
             mov    ES:Byte Ptr INTM1,DH

SETINTR      PROC   NEAR

             mov    BL,DS:Byte Ptr INTdone
             or     BL,BL
             jz     SETINTR2            
             ;jmp if ints not turned on following signal in
             ;interrupt routine
             mov    DS:Byte Ptr INTdone,FALSE          
             call   SETgpibINT
SETINTR2:    ret                      ;return from call

SETINTR      ENDP
SETUPINTS    ENDP

;
; the following routine are used to close the 
; semaphores for the driver
;

SIGNALSEMA   PROC   NEAR

             push   BX               ;SID
             push   CX               ;Mode
             push   AX               ;note
             les    BX,ErrorPtr
             push   ES
             push   BX
             call   CpSignal
             call   GETERROR
             mov    SignalErr,AX     ;save it
             ret

SIGNALSEMA   ENDP

;
; the following routine is to end the read and write rou-
; tines.
;

RDWTEND      PROC   NEAR

             call   PUTERROR
             mov    asyncSRQ,TRUE    ;flag for asynchronous
                                     ;service requests
             mov    DL,00h           ;no BI,BO
             mov    DH,SRQ           ;int for SRQ only
             call   SETUPINTS        ;go enable ints
             ret

RDWTEND      ENDP

;
; this routine turns off talk mode and turns on listen mode
;

RSTCTRL      PROC   NEAR

             mov    AX,GPiBioSEG
             mov    ES,AX
             mov    DI,AUXCMD         ;9914 reg to talk to
             mov    ES:Byte Ptr[DI],diston ;turn off talk
             mov    ES:Byte Ptr[DI],lon    ;turn on listen
             mov    ES:Byte Ptr[DI],gts    ;controller stdby
             ret

RSTCTRL      ENDP

;
; this routine calls the os routine to set gpib ints on
;

SETgpibINT   PROC   NEAR

             push   ES
             push   AX
             push   BX
             push   CX
             push   DX
             push   SI
             mov    AX,INTGPiBid
             push   AX
             mov    AX,INTGPiBmode
             push   AX
             call   CpEnableInterrupt
             pop    SI
             pop    DX
             pop    CX
             pop    BX
             pop    AX
             pop    ES
             ret

SETgpibINT   ENDP

;
; this routine calls the os routine to reset the gpib int
;

RSTgpibINT   PROC   NEAR

             push   AX
             push   ES
             push   BX
             mov    AX,INTGPiBid
             push   AX
             call   CpDisableInterrupt
             pop    BX
             pop    ES
             pop    AX
             ret

RSTgpibINT   ENDP


;
; this routine gets the pointer for where the errorcode goes
;

GETERROR     PROC   NEAR

             les    DI,ErrorPtr
             mov    AX,ES:[DI]
             ret

GETERROR     ENDP

;
; this routine puts the errorcode in AX into the pointer
;

PUTERROR     PROC   NEAR

             push   AX
             call   GETERROR          ;already got error?
             or     AX,AX
             pop    AX
             jnz    PUTERROR2         ;yes
             les    DI,ErrorPtr
             mov    ES:[DI],AX
PUTERROR2:   ret

PUTERROR     ENDP
$EJ
;**********************************************************
;*** GPiBSETSTAT MODULE ***********************************
;*** The OS call, ddSetStatus, is implemented in this module
;*** and consists of just two mode calls: Reset (Mode=0) and
;*** Micro-command (Mode=2).  Reset jumps to GPiBinit.  Mi-
;*** cro-command addresses a read or write register of the
;*** 9914 and inputs/outputs data to/from these ports.
;***
;*** Inputs : pCB
;***
;*** Outputs : pError
;***
;**********************************************************

GPiBSETSTAT  LABEL  NEAR

             push   DS
             lds    BX,pCBlock        ;point to paramlist
             les    DI,[BX].pOverflow ;point to mode bytes
             mov    AL,ES:Byte Ptr[DI] ;get mode descriptor
             or     AL,AL
             jnz    SETSTAT2          ;not reset
             mov    DX,GPiBioSEG
             mov    ES,DX
             mov    ES:Byte Ptr AUXCMD,rst
             mov    ES:Byte Ptr AUXCMD,clrrst ;reset interf
             mov    ES:Byte Ptr AUXCMD,ton  ;talk on
             mov    DL,[BX].intAddr   ;get device addr
             and    DL,01fh           ;mask out extrans bits
             or     DL,20h            ;make listen addr
             pop    DS
             call   CHKBOUT           ;ready to send?
             or     AX,AX             ;error?
             jnz    nobout            ;yes
             mov    ES:Byte Ptr DATAOUT,DL ;send addr
             call   CHKBOUT           ;ready to send
             or     AX,AX             ;error?
             jnz    nobout
             mov    ES:Byte Ptr DATAOUT,SELDEVCLR
             mov    AX,1f4h           ;selective device clr
             push   AX                ;timeout for clear
             call   CpDelay           ;for about .5 sec
             jmp    STUBRET           ;put error and ret

SETSTAT2:    cmp    AL,MODE1          ;Micro-command?
             je     SETSTAT3          ;yes, go implement
             cmp    AL,MODE2          ;set SRQ?
             je     SETSTAT5          ;yes, go implement
             pop    DS
             mov    AX,eNotSupport
nobout:      call   PUTERROR
             jmp    STUBRET           ;return

SETSTAT3:    inc    DI
             xor    BX,BX
             mov    BL,ES:Byte Ptr[DI] ;get reg
             inc    DI
             mov    CL,ES:Byte Ptr[DI] ;get data
             rol    BL,1               ;reg addr x 2
             cmp    CL,TRUE            ;read or write?
             mov    AX,GPiBioSEG
             mov    DS,AX
             je     READREG            ;read it
             mov    Byte Ptr[BX],AL    ;write it out
SETSTAT4:    pop    DS
             jmp    STUBRET

READREG:     mov    AL,Byte Ptr[BX] ;get reg contents
             dec    DI
             dec    DI
             mov    ES:Byte Ptr[DI],AL ;put in pBuffer
             jmp    SETSTAT4

SETSTAT5     PROC   NEAR

             mov    AL,[BX].intAddr ;address of device
             dec    AL
             pop    DS
             xor    AH,AH
             push   AX              ;save address
             add    AL,AL           ;double it
             mov    BX,Offset DeviceSID ;table of srq SIDs
             add    BX,AX           ;point into table
             mov    CX,ES:[DI+1]    ;SID code
             mov    AX,request      ;is this deactivate?
             cmp    AX,ddDeactivate ;
             jne    putSIDcode      ;no, put sid into table
             xor    CX,CX           ;yes, zero out sid code
putSIDcode:  mov    [BX],CX         ;put in table
             mov    BX,Offset DevSIDenb ;bit map of srq addr
             pop    CX              ;address into CX
             mov    AX,1
             cmp    CL,10h          ;more than a word?
             jl     SETSTAT6        ;no
             sub    CX,10h          ;subtract word from it
             inc    BX
             inc    BX              ;point to second bit map
SETSTAT6:    clc                    ;clear carry
             rol    AX,CL           ;rotate bit to addr bit
             mov    CX,request      ;is this deactivate
             cmp    CX,ddDeactivate ;
             jne    setSIDflag      ;no
             xor    AX,0ffffh       ;reset bit
             and    [BX],AX         ;by anding it out
             jmp    STUBRET         ;return

setSIDflag:  or     [BX],AX         ;or it into map
             jmp    STUBRET         ;return

SETSTAT5     ENDP
$EJ
;**********************************************************
;*** GPiBSPOLL MODULE *************************************
;*** Poll each device enabled for service requests on the
;*** bus in turn to see who issued the asynchronous int-
;*** errupt.  When found, signal stub and return.
;*** 
;*** Inputs : DS=DATA, ES=GPiBioSEG
;*** 
;*** Outputs : None
;***
;**********************************************************

GPiBSPOLL    PROC   NEAR

             mov    AL,service        ;srq occurred?
             or     AL,AL
             jnz    GPiBSPOLL2        ;yes
             xor    AX,AX             ;spoll ok
             ret                      ;return

GPiBSPOLL2   PROC   NEAR

             mov    AX,GPiBioSEG
             mov    ES,AX
             mov    ES:Byte Ptr DATAOUT,SPE ;enable ser poll
             mov    BX,Offset DevSIDenb
             mov    CX,DS:[BX]        ;bit map of enab devs
             xor    DX,DX
SPOLL1:      mov    BX,Offset DevSIDenb
             mov    AX,DX             ;done for the loop
SPOLL2:      cmp    AL,10h            ;done w/gpib addrs?
             jne    SPOLL3            ;no
             mov    CX,DS:[BX+2]      ;get upper addrs
SPOLL3:      cmp    AL,20h            ;done w/upper addrs?
             jne    SPOLL3A           ;yes
             jmp    SPOLL5A           ;ECO 6/6/83 was spoll5
SPOLL3A:     inc    AL
             rcr    CX,1
             jnc    SPOLL2
             mov    DX,AX             ;DX=gpib addr
             push   DX
             push   CX
             or     DL,40h            ;make talk address
             push   BX
             call   CHKBOUT           ;send out address 
             pop    BX                ;gpib addr
             or     AX,AX             ;any error?
             jz     SPOLL3B           ;no
             jmp    SPOLL5            ;yes
SPOLL3B:     mov    ES:Byte Ptr DATAOUT,DL
             call   RSTCTRL           ;make ctrlr listen
             mov    CX,0ffffh         ;timeout
CHKBIN:      mov    AL,ES:Byte Ptr INT0 ;BIN set?
             test   AL,BIN
             jnz    CHKBIN2           ;yes
             dec    CX                ;timeout
             jnz    CHKBIN            ;not yes
             jmp    SPOLL5
CHKBIN2:     mov    ES:Byte Ptr[DI],tcs ;take control
             mov    BL,ES:Byte Ptr DATAIN ;input spoll byte
             mov    ES:Byte Ptr[DI],dislon ;listen off
             mov    ES:Byte Ptr[DI],ton    ;talk on
             pop    CX
             pop    DX
             test   BL,40h            ;spoll bit on?
             jz     SPOLL1            ;if zero, poll again
             and    BL,0bfh           ;get rid of 6th bit
             xor    BH,BH
             mov    AX,BX             ;ax = srqnote
             mov    BX,Offset DeviceSID ;start of list
             dec    DX                ;addr - 1
             clc
             rol    DX,1              ;addr*2
             mov    SI,DX
             mov    BX,DS:[BX][SI]    ;get sid code for addr
             push   BX
             push   AX
             call   CHKBOUT
             or     AX,AX             ;any error
             jnz    SPOLL5            ;ECO 6/6/83 was
                                      ;spoll5a
             mov    ES:Byte Ptr DATAOUT,SPD
             call   CHKBOUT
             or     AX,AX
             jnz    SPOLL5            ;ECO 6/6/83 was
                                      ;spoll5a
             mov    ES:Byte Ptr DATAOUT,UNT
             call   CHKBOUT
             or     AX,AX
             jnz    SPOLL5            ;ECO 6/6/83 was
                                      ;spoll5a
             pop    AX                ;srqnote
             pop    BX                ;sidcode
             mov    CX,LATER          ;mode
             call   SIGNALSEMA        ;signal plm program
             xor    AX,AX             ;errCode= ok
SPOLL4:      mov    service,FALSE     ;reset flags
             ret

SPOLL5:      pop    AX
             pop    BX
SPOLL5A:     mov    AX,eGPiBnotResp
             jmp    SPOLL4

GPiBSPOLL2   ENDP
GPiBSPOLL    ENDP
$EJ
;**********************************************************
;*** GPiBint MODULE ***************************************
;*** Procedure that is vectored to upon a GPIB interrupt.
;***
;*** Inputs : None
;***
;*** Outputs : None
;***
;**********************************************************

GPiBint      PROC   FAR

             push   ES                ;save environment
             push   DS
             push   BP
             push   SI
             push   DI
             push   DX
             push   BX
             push   AX
             push   CX
             mov    AX,DATA
             mov    DS,AX
             mov    AX,INTGPiBid
             push   AX
             call   CpEndOfInterrupt
             call   RSTgpibINT

; reset 8259 interrupt controller after interrupt

             mov    AL,asyncSRQ          ;enabled for async?
             or     AL,AL
             jz     nosrq                ;no
             push   DS
             call   GPiBSPOLL2
             pop    DS
             mov    AX,GPiBioSeg
             mov    ES,AX
             mov    AL,ES:Byte Ptr INT0
             mov    AH,ES:Byte ptr INT1
             jmp    doneSRQ              ;done with poll

nosrq:       mov    AX,DMAeoiORerr       ;possible eoi?
             or     AX,AX
             jz     nodmaread            ;no read
             push   DS
             mov    AX,SEG SMCmove       ;cs
             mov    SI,Offset SMCmove    ;ip
             mov    DS,AX
             mov    Byte Ptr[SI],90h    ;change the instruc
             mov    Byte Ptr[SI+1],90h  ;to nops and fall
                                         ;thru. Don't do the
                                         ;rep movsb anymore.
             mov    eoiReceived,TRUEW    ;set flag
             pop    DS
             mov    DS:Byte Ptr INTdone,TRUE
             jmp    nointson             ;don't reset ints

nodmaread:   mov    BX,SEMAdata          ;sid code
             mov    CX,LATER             ;mode
             xor    AX,AX                ;note
             call   SIGNALSEMA

doneSRQ:     call   SETgpibINT
             mov    DS:Byte Ptr INTdone,TRUE
             xor    AX,AX
             push   AX
             call   CpDelay              ;reschedule now

;allow ints for gpib again and flag that theyre on

nointson:    pop    CX
             pop    AX
             pop    BX
             pop    DX
             pop    DI
             pop    SI
             pop    BP
             pop    DS
             pop    ES                   ;restore enviroment
             iret                        ;return from int

GPiBint      ENDP
;**********************************************************
;*** End of GPiBdriver Proc *******************************

GPiBdriver   ENDP

;**********************************************************
;**********************************************************
;*** END of CODE SEGMENT **********************************
;
CODE         ENDS
             END
