Files

1024 lines
36 KiB
NASM
Raw Permalink Normal View History

2026-07-06 18:28:16 +01:00
title AS5PDD Epoc Serial physical device driver for the 16550
subttl Copyright Psion PLC 1993
name SYS$AS5
; VERSION DATE DESCRIPTION
; ------- -------- ---------------
; 1.0 08/12/94 Initial version
; Written by Jason December 1994
; Serial Driver for Epoc based around ASIC5
Sr5S3 = 0
Sr5S3a = 1
ifdef BUILDS3
Sr5S3 = 1
Sr5S3a = 0
BUILDHH equ 1
endif
if Sr5S3a
BUILDSB equ 1
endif
include ..\inc\epoc.inc
include ..\inc\epocser.inc
include ..\inc\epoclib.inc
include ..\inc\epocsibo.inc
include ..\srcs\ossibo.inc
include ..\srcs\ospack.inc
Sr5ChannelStruct struc
Sr5Open db ? ; Is the channel open
Sr5Ctrl db ? ; State of control lines
Sr5IntVector db ? ; The Vector number
Sr5Channel db ? ; Which channel are we
Sr5Mask db ? ; InterruptMask
Sr5Running db ? ; Are we running
Sr5IntRoutineVec dw ? ; Vector to Interrupt
Sr5Baud dw ? ; The baud rate
Sr5LddData dw ? ; Info from Ldd above
Sr5StatusInt dd ? ; Vectors in serial
Sr5RecvInt dd ? ; Above to be called
Sr5XmitInt dd ? ; On input/output
Sr5ClockEnable db ? ; Reason to stop
Sr5TheLines db ? ; State of the modem lines
Sr5ChannelStruct ends
A5Ent struc ; ASIC5 Read/Write
A5PortA db ? ; Port A R/W
A5PortB db ? ; Port B R/W
A5PortBMode db ? ; Inc/Mode
A5PortD db ? ; Port CD Write only
A5Swipe1 db ?
A5Swipe2 db ?
A5IntMask db ? ; Interrupt mask R/W
A5CtrlReg db ? ; IntType/Ctrl register
A5USR db ? ; UART Status/Ctrl
A5RHR db ? ; Receive/Transmit
A5BDLSB db ? ; Baud Rate write only
A5BDMSB db ? ; Baud Rate write only
A5MCR1Eoi db ? ; MCR shift register
A5MCRPresentEoi db ? ; Barcode data&ints
A5MCR2Eoi db ?
A5DUMMYF db ?
A5Ent ends
if Consumer
NumberOfChannels equ 1 ; S3 Single Channel
else
NumberOfChannels equ 3 ; HC,S3C Three Channel
endif
OsActivityMeter equ 158ch ; Activity Channel
StopTimeOut equ 1000 ; ~1s (1000ms) wait
S_RS232ON equ 00000001b ; RS232 on
S_RSTTLON equ 00000100b ; Line drivers on
S_CENTON equ 00010000b ; Line drivers enable
S_RXENB equ 00000001b ; Receive interrupt on
S_TXENB equ 00000010b ; Transmit interrupt on
S_TXEMPTY equ 00010000b ; transmit buffer empty
S_RXINT equ 00000001b ; Receive interrupt?
S_TXINT equ 00000010b ; transmit interrupt?
S_MDINT equ 00000100b ; Modem status interrupt
S_CTS equ 00000001b ; CTS
S_RTS equ 00000010b ; RTS
S_DCD equ 00000100b ; DCD
S_DSR equ 00000010b ; DCR
S_DTR equ 00000100b ; DTR
OVERRUN_ERROR equ 01000000b ; Character overrun
PARITY_ERROR equ 10000000b ; Parity error
S_PERIPHERALMODE equ 00000011b ; ASIC5 RS232 mode
S_UART_OFF equ 00000010b ; ASIC5 peripheral mode
dgroup group stack
assume ds:dgroup,es:dgroup,ss:dgroup
CodeSeg
ProcBegin@ OsAS5PDD
; ====================
dw PDDSignature
db 'TTY.SR5',0
dw (VectorEnd-Vector)/2
Vector:
dw OsAS5Install
dw OsAS5Remove
dw OsAS5Open
dw OsAS5Strategy
VectorEnd:
BaudRateTable dw -077fh,-04ffh,-0368h,-02cch,-027fh,-013fh
dw -009fh,-004fh,-0035h,-0030h,-0027h,-0019h
dw -0013h,-000ch,-0009h,-0004h
DataBitsTable db 0,2,4,6 ; 5,6,7,8 bits per char frame
ParityTable db 08h,18h,0h,0h ; Even,Odd,Mark,Space parity
Chan0 Sr5ChannelStruct <>
Chan1 Sr5ChannelStruct <>
Chan2 Sr5ChannelStruct <>
if Consumer
if Asic9
SetupTable dw offset AS5Int1
db HwIrq2Revector,mask A9MSlave
db SelectChannel5,(mask A9MClockEnable5 shr 8)
else
SetupTable dw offset AS5Int1
db HwIrq4Revector,mask Asic2Int
db SelectChannel7,(mask ClockEnable7 shr 8)
endif
else
if Asic9
SetupTable dw offset AS5Int1
db HwIrq4Revector,mask A9MExpIntA
db SelectChannel3,(mask A9MClockEnable3 shr 8)
dw offset AS5Int2
db HwIrq5Revector,mask A9MExpIntB
db SelectChannel4,(mask A9MClockEnable4 shr 8)
dw offset AS5Int3
db HwIrq2Revector,mask A9MSlave
db SelectChannel5,(mask A9MClockEnable5 shr 8)
else
SetupTable dw offset AS5Int1
db HwIrq3Revector,mask ExpIntLeftA
db ExpChannelLeftA,(mask ClockEnable6 shr 8)
dw offset AS5Int2
db HwIrq2Revector,mask ExpIntRightB
db ExpChannelRightB,(mask ClockEnable5 shr 8)
dw offset AS5Int3
db HwIrq4Revector,mask Asic2Int
db SelectChannel7,(mask ClockEnable7 shr 8)
endif
endif
ProcEnd noret
ProcBegin@ OsAS5Install,far
; ============================
; Install the device driver
; Out: Carry clear -happy to install
cld ; Clear the channels
mov cx, NumberOfChannels ; and set up fixed
mov di, offset Chan0 ; parameters such
mov si, offset SetupTable ; as the interrupt
pushf ; vectors and masks
cli ; for each channel
push ds
mov ax, cs
mov ds, ax
ResetAllChannelsLoop:
mov [di].Sr5Open, 0 ; Channel not open
lodsw
mov [di].Sr5IntRoutineVec, ax ; Set the interrupt
lodsb ; handler to call
mov [di].Sr5IntVector, al ; Which Interrupt
lodsb
mov [di].Sr5Mask, al ; Mask for that
lodsb ; interrupt
mov [di].Sr5Channel, al ; Which Psion serial
lodsb ; channel
mov [di].Sr5ClockEnable, al ; Baud rate clocking
add di, size Sr5ChannelStruct ; enable
loop ResetAllChannelsLoop
pop ds
popf
AllChannelsOkay:
clc ; Returns with
ret ; Carry clear
ProcEnd noret
ProcBegin@ OsAS5Remove,far
; ==========================
; Remove the device driver
; Out: Carry clear -happy to remove
; Carry set -we have an open channel and cant be removed.
xor ax, ax ; If we have a
or al, Chan0.Sr5Open ; channel Still open
or al, Chan1.Sr5Open ; then return a can't
or al, Chan2.Sr5Open ; do error else
jz AllChannelsOkay ; complete okay
mov ax, InUseErr
stc
ret
ProcEnd noret
ProcBegin@ OsAS5Open,far
; ========================
; Open a serial channel
; In: SS:SI is a pointer to the open Ent Structure
; Out: Carry clear, control block in BX
; Carry set, error in AX
cld
mov si, [si].OpenNamePtr ; Open the channel
mov al, [si+1] ; Get the channel
CharToFoldedChar ; Make Upper Case
cmp al, 'A' ; Indicator which is
jb ErrorInOpen ; Part of the name
sub al, 'A' ; Should be A,B,C
cmp al, NumberOfChannels
jae ErrorInOpen
xor ah, ah
mov bx, offset Chan0 ; What Channel are
cmp al, 1 ; We Openning
jb GotChan ; Pointer to Control
mov bx, offset Chan2 ; Block in bx
ja GotChan
mov bx, offset Chan1
GotChan:
mov al, 1
xchg al, cs:[bx].Sr5Open
cmp al, 0 ; Now try to Open
je OkayToOpen ; That channel
CantOpen:
mov ax, InUseErr
CantOpenDiffErr:
stc
ret
ErrorInOpen:
mov ax, NameErr
stc
ret
OkayToOpen:
xor al, al
mov cs:[bx].Sr5Running, al
mov cs:[bx].Sr5TheLines, al
mov cs:[bx].Sr5Ctrl, al
mov al, cs:[bx].Sr5Mask
HwGetChannel
jc CantOpenSoClose ; Check that we have
call CheckHardwarePresent ; The right Hardware
jnc OpenedOkay
mov al, cs:[bx].Sr5Mask
HwFreeChannel
CantOpenSoClose:
mov cs:[bx].Sr5Open, 0
mov ax, DeviceErr
jmp short CantOpenDiffErr ; Return with the
OpenedOkay: ; Offset of our
xor ax, ax ; Control Block
ret ; In bx
ProcEnd noret
AS5StrategyJumpTable label word
dw offset AS5Open ; Load Handler offsets
dw offset AS5Close ; Close the channel
dw offset AS5Start ; Start the channel
dw offset AS5Stop ; Stop the channel
dw offset AS5Set ; Does nothing
dw offset AS5Sense ; Returns chan status
dw offset AS5Control ; Drive the lines
dw offset AS5Enquire ; Returns baud rate
dw offset AS5Enable ; Begin Output
dw offset AS5SetHandlerCS ; Get Handler segments
ProcBegin@ OsAS5Strategy,far
; =============================
; Strategy functions entry point
; Warning! This can be called from within Interrupt
; In: vector number in AX + various data in other registers
; DS is OsDataGroup (and MUST be preserved)
; Out: DI is pointer to control block
; Old channel and flags on stack
cld
mov bx, sp
mov bx, ss:[bx+4]
mov bl, cs:[bx].Sr5Channel ; Select the correct
xchg bx, ax ; Output channel
pushf ; Then Call the right
cli ; Function to deal
HwSelectChannel ; With the strategy
mov ah, bh ; request
xor bh, bh
push ax ; Interrupts off
mov ax, di ; and flags are on
mov di, sp ; the stack
mov di, ss:[di+8]
jmp AS5StrategyJumpTable[bx]
ProcEnd noret
ProcBegin@ AS5Open,far
; ======================
; Old channel and flags on the stack, interrupts off
mov cs:[di].Sr5LddData, cx ; Load the offsets of
mov word ptr cs:[di].Sr5StatusInt, ax ; the data send and
mov word ptr cs:[di].Sr5RecvInt, si ; recieve routines in
mov word ptr cs:[di].Sr5XmitInt, dx ; the Ldd above us
xor dx, dx ; DX=0 -We don't support
pop ax ; power management
HwSelectChannel ; Return the old
popf ; channel
ret
ProcEnd noret
ProcBegin@ AS5Close,far
; =======================
; Old channel and flags on the stack, interrupts off
and cs:[di].Sr5Open, 0 ; Close the Channel
mov al, cs:[di].Sr5Mask ; Free up our channel
HwFreeChannel ; And the Hardware
pop ax ; Channel
HwSelectChannel ; Return the old
popf ; channel
ret
ProcEnd noret
ProcBegin@ AS5Start,far
; =======================
; Old channel and flags on the stack, interrupts off
call CheckHardwareFromStart
mov dx, 0
jc CantStartSomethingWhichIsntThere
if Asic9
in ax, A9WControlExtraRW ; Start the S3s clock
or ah, cs:[di].Sr5ClockEnable ; Generator
out A9WControlExtraRW, ax
else
mov al, cs:[di].Sr5ClockEnable
HwSetA2Control2Bits
endif
mov al, SerialWriteSingle or A5USR ; Set the baud rate
SBUSY ; and other
SCONTOUT ; characteristics
mov al, cs:[di].Sr5Ctrl
SBUSY
SDATAOUT
mov al, SerialWriteSingle or A5BDLSB
SBUSY
SCONTOUT
mov al, byte ptr cs:[di].Sr5Baud
SBUSY
SDATAOUT
mov al, SerialWriteSingle or A5BDMSB
SBUSY
SCONTOUT
mov al, byte ptr cs:[di+1].Sr5Baud
SBUSY
SDATAOUT
call GetTheInterrupt ; Get the interrupt
xor cx, cx ; and clear down
call DriveRts ; the RTS line (DTR
; stays at the state
mov al, SerialWriteSingle or A5CtrlReg ; it was set)
SBUSY
SCONTOUT
mov al, (S_CENTON or S_RS232ON or S_RSTTLON)
SBUSY
SDATAOUT ; Switch on the line
mov cx, 8 ; 8 ms ; drivers and wait
pop dx ; for them to power up
call WaitTimer
push dx
mov ah, (S_RXENB or S_TXENB or S_MDINT) ; Start all interrupts
call EnableTheInterrupt
mov cs:[di].Sr5Running, 1
mov bx, Asic5SerialCurrent
HwSetPCurrent
call Status
CantStartSomethingWhichIsntThere:
pop ax ; Return the old
HwSelectChannel ; channel
popf
ret
ProcEnd noret
ProcBegin@ AS5Stop,far
; =======================
; Old channel and flags on the stack, interrupts off
xor cx, cx ; Clear the state of
call DriveRts ; the modem lines
mov al, SerialReadSingle or A5IntMask ; Stop all of the
SBUSY ; interrupts
SCONTOUT
XNOP
SBUSY
SDATAIN
and al, not (S_TXENB or S_RXENB or S_MDINT)
mov ah, al
mov al, SerialWriteSingle or A5IntMask
SBUSY
SCONTOUT
mov al, ah
SBUSY
SDATAOUT
pop dx
cmp dh, DevHoldPowerFail
je DontStopHardware
cmp cs:[di].Sr5Running, 1
jne DontWait
mov cx, StopTimeOut
jmp short CompareNow
WaitForEmpty:
call TickTimer
CompareNow:
mov al, SerialReadSingle or A5USR
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
test al, S_TXEMPTY
loopne WaitForEmpty
DontWait:
cmp bh,DevHoldNormal
je DontStopHardware
if Asic9
mov cl, cs:[di].Sr5ClockEnable ; Turn off baud rate
not cl ; clocking from the
in ax, A9WControlExtraRW ; S3/3a
and ah, cl
out A9WControlExtraRW, ax
else
mov al, cs:[di].Sr5ClockEnable
HwClearA2Control2Bits
endif
mov al, SerialWriteSingle or A5CtrlReg ; Stop the drivers
SBUSY ; and stuff
SCONTOUT
sub al, al ; clear S_CENTON,
SBUSY ; S_RS232ON, S_RSTTLON
SDATAOUT
DontStopHardware:
mov al, dl ; Return the old
HwSelectChannel ; channel
popf
xor bx, bx
HwSetPCurrent
ret
ProcEnd noret
ProcBegin@ AS5Set,far
; =====================
; Old channel and flags on the stack, interrupts off
; In: Information required is on the stack
pop ax ; Return the old
HwSelectChannel ; channel
popf
mov ah, ss:[si].SerialCharTbaud ; Set the Recieve,
cmp ah, ss:[si].SerialCharRbaud ; Transmit characteristics
jnz ErrorInSet ; First set the Baud
cmp ah, P_BAUD_50 ; Rate
jb ErrorInSet
cmp ah, P_BAUD_19200
ja ErrorInSet
GotTheSpecialBaud:
dec ah
mov cl, ss:[si].SerialCharFrame ; Then the number of
mov al, ss:[si].SerialCharParity ; Stop bits
dec al
xor ch, ch
push bx
test cl, P_TWOSTOP
jz OnlyOneStopBit
or ch, 020h
OnlyOneStopBit:
test cl, P_PARITY ; The Parity
jz NoParity
mov bx, offset ParityTable
xlat cs:[ParityTable]
or ch, al
NoParity:
mov bx, offset DataBitsTable ; And finally the
and cl, P_DATA_FRM ; Number of data bits
mov al, cl ; Per frame
xlat cs:[DataBitsTable]
or ch, al
mov bx, offset BaudRateTable
mov al, ah
xor ah, ah
shl ax, 1
add bx, ax
mov ax, cs:[bx]
pop bx
mov cs:[di].Sr5Ctrl, ch
mov cs:[di].Sr5Baud, ax
xor al, al
ret
ErrorInSet:
mov al, NotSupportedErr
stc
ret
ProcEnd noret
ProcBegin@ AS5Sense,far
; =======================
; Old channel and flags on the stack, interrupts off
; Out: The state of the DCD,CTS,DSR lines returned in DX
call Status
pop ax ; Return the old
HwSelectChannel ; channel
popf
ret
ProcEnd noret
ProcBegin@ Status
; =================
; Out: State of modem lines in DX
mov al, SerialReadSingle or A5USR ; Get the current
SBUSY ; Modem status
SCONTOUT ; Lines and return
XNOP ; With the result
SBUSY ; In dx
SDATAIN
and al, (S_CTS or S_DSR or S_DCD) ; Get the lines we want
xor al, (S_CTS or S_DSR or S_DCD) ; Invert signals
xor ah, ah
mov dx, ax
ret
ProcEnd noret
ProcBegin@ AS5Control,far
; =========================
; Old channel and flags on the stack, interrupts off
; In: Lines to drive and state to drive them in DX
mov cl, dl ; Set the state of one
test dh, P_SRCTRL_DTR ; of the modem Lines
jz DriveRtsNow ; DH is the line to
call DriveDtr ; Drive and DL is the
pop ax ; State to drive it to
HwSelectChannel ; Return the old
popf ; channel
ret
DriveRtsNow:
call DriveRts
pop ax ; Return the old
HwSelectChannel ; channel
popf
ret
ProcEnd noret
ProcBegin@ DriveDtr
; ===================
mov ah, S_DTR ; Set/Reset the DTR
jmp short DriveTheLine ; Line
ProcEnd noret
ProcBegin@ DriveRts
; ===================
mov ah, S_RTS ; Set/Reset RTS
DriveTheLine:
mov al, SerialWriteSingle or A5PortD ; Common code to set
SBUSY ; and reset either
SCONTOUT ; line while
mov al, cs:[di].Sr5TheLines ; preserving the
test cl, cl ; states of the other
jz ClearLine ; lines
or al, ah
jmp DoTheOutput
ClearLine:
not ah
and al, ah
DoTheOutput:
mov cs:[di].Sr5TheLines, al
SBUSY
SDATAOUT
ret
ProcEnd noret
ProcBegin@ AS5Enquire,far
; =========================
; Old channel and flags on the stack, interrupts off
; Out: DX,AX are the supported baud rates AX for 50 to 19200 DX for above
; CX says what data bits, parity, etc we support
pop ax ; Return the old
HwSelectChannel ; channel
popf
if Asic9
mov ax, -1
else
mov ax, 07fffh
endif
xor dx, dx
mov cx, (0ffffh AND (NOT (P_SRINQ_SPLIT OR P_SRINQ_PARSPACE OR P_SRINQ_PARMARK)))
ret
ProcEnd noret
ProcBegin@ AS5Enable,far
; ========================
; Old channel and flags on the stack, interrupts off
mov ah, S_TXENB ; Begin Output by
call EnableTheInterrupt ; enabling transmit
pop ax ; interrupts
HwSelectChannel ; Return the old
popf ; channel
ret
ProcEnd noret
ProcBegin@ AS5SetHandlerCS,far
; ==============================
; Old channel and flags on the stack, interrupts off
; CX is CS of above LDD
mov word ptr cs:[di].(Sr5StatusInt+2), cx ; Load the Segment
mov word ptr cs:[di].(Sr5RecvInt+2), cx ; Within which the
mov word ptr cs:[di].(Sr5XmitInt+2), cx ; The Ldd above us
pop ax ; Return the old
HwSelectChannel ; channel
popf ; Resides
ret
ProcEnd noret
ProcBegin@ AS5Int3,far
; ======================
mov di, offset Chan2 ; Channel 3 interrupt
mov ax, PortCActive ; vector
jmp ComInt ; Jumps to Comint
ProcEnd noret
ProcBegin@ AS5Int2,far
; ======================
mov di, offset Chan1 ; Channel 2 interrupt
mov ax, PortBActive ; vector
jmp ComInt ; Jumps to Comint
ProcEnd noret
ProcBegin@ AS5Int1,far
; ======================
mov di,offset Chan0 ; Channel 1 interrupt
mov ax,PortAActive ; vector
; FALL THROUGH ; Falls through
ProcEnd noret ; to Comint
ProcBegin@ ComInt,far
; =====================
; The common interrupt handler
; DS points to OS data space
; DI is our control block
; AX is the Active channel
if S3b or S3c
or ds:[OsActivityMeter], ax ; Set active state
endif
mov al, cs:[di].Sr5Channel ; Select our
HwSelectChannel ; channel
push ax
mov bx, cs:[di].Sr5LddData ; Data for LDD above
TheInterruptLoop: ; in bx
mov al, SerialReadSingle or A5CtrlReg ; Find out what
SBUSY ; caused the
SCONTOUT ; interrupt
XNOP
SBUSY
SDATAIN
test al, al
je NothingToDo
HaveWeGotAModemStatusLineInterrupt:
test al, S_MDINT
jz HaveWeGotARecieveInterrupt
mov al, SerialReadSingle or A5USR
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
test al, (OVERRUN_ERROR or PARITY_ERROR)
jz ModemStatusInterruptOnly
push ax ; Something has been
mov ah, SERPARITY_ERR ; recieved in error
test al, PARITY_ERROR
jnz IsAParityError ; Establish the error
mov ah, SEROVERRUN_ERR
IsAParityError:
mov al, SerialReadSingle or A5RHR ; Get the character
SBUSY ; in question
SCONTOUT
XNOP
SBUSY
SDATAIN
push di
call dword ptr cs:[di].Sr5RecvInt
pop di
pop ax
ModemStatusInterruptOnly:
and ax, (S_CTS or S_DSR or S_DCD)
xor al, (S_CTS or S_DSR or S_DCD) ; invert signals
mov dx, ax
push di
call dword ptr cs:[di].Sr5StatusInt
pop di
jmp short TheInterruptLoop
HaveWeGotARecieveInterrupt:
test al, S_RXINT
jz HaveWeGotATransmitInterrupt
mov al, SerialReadSingle or A5RHR
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
xor ah, ah ; AX has character received
push di
call dword ptr cs:[di].Sr5RecvInt
pop di
jmp short TheInterruptLoop
HaveWeGotATransmitInterrupt:
test al, S_TXINT
jz NothingToDo
push di
call dword ptr cs:[di].Sr5XmitInt
pop di
test ax, ax ; -1 if disable
js DisableTransmitInts
mov ah, al
mov al, SerialWriteSingle or A5RHR
SBUSY
SCONTOUT
mov al, ah
SBUSY
SDATAOUT
jmp TheInterruptLoop
NothingToDo:
if Asic9
out A9BNonSpecificEoiW,al
else
out A1NonSpecificEoi, al
endif
pop ax
HwSelectChannel
clc ; Resced if neccessary
ret
DisableTransmitInts: ; disable TX interrupts
mov al, SerialReadSingle or A5IntMask
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
and al, not S_TXENB
mov ah, al
mov al, SerialWriteSingle or A5IntMask
SBUSY
SCONTOUT
mov al, ah
SBUSY
SDATAOUT
jmp TheInterruptLoop
ProcEnd noret
ProcBegin@ GetTheInterrupt
; ==========================
mov al, cs:[di].Sr5IntVector ; Load the address of
mov cx, cs ; the appropriate
mov bx, cs:[di].Sr5IntRoutineVec ; interrupt routine
GenSetRevector ; into the correct
ret ; vector
ProcEnd noret
ProcBegin@ EnableTheInterrupt
; =============================
mov al, SerialReadSingle or A5IntMask
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
or ah, al
mov al, SerialWriteSingle or A5IntMask
SBUSY
SCONTOUT
mov al, ah
SBUSY
SDATAOUT
if Asic9
in al,A9BInterruptMaskRW ; Set the mask
or al, cs:[di].Sr5Mask ; to enable Interrupts
out A9BInterruptMaskRW,al
else
in al, A1InterruptMask
or al, cs:[di].Sr5Mask
out A1InterruptMask, al
endif
ret
ProcEnd noret
ProcBegin@ StopInterrupts
; =========================
mov al, SerialReadSingle or A5IntMask ; Stop interrupts
SBUSY ; from Asic5
SCONTOUT
XNOP
SBUSY
SDATAIN
and al, not (S_RXENB or S_TXENB or S_MDINT)
mov ah, al
mov al, SerialWriteSingle or A5IntMask
SBUSY
SCONTOUT
mov al, ah
SBUSY
SDATAOUT
mov ah, cs:[di].Sr5Mask
not ah
if Asic9
in al,A9BInterruptMaskRW ; Stop Interrupts
and al,ah ; By clearing the
out A9BInterruptMaskRW,al ; Mask and resetting
else ; The Vector
in al, A1InterruptMask
and al,ah
out A1InterruptMask, al
endif
mov al, cs:[di].Sr5IntVector
GenResetRevector
ret
ProcEnd noret
ProcBegin@ CheckHardwarePresent
; ===============================
pushf
cli
mov al, cs:[bx].Sr5Channel ; Check that the
HwSelectChannel ; Harware is there
HwNullFrame ; And that it is what
mov al,(SerialSelect or Asic5NormalId) ; It should be
SBUSY ; First look for An
SCONTOUT ; ASIC4 at the other
XNOP ; End of the link
SBUSY
SDATAIN
test al,al
je ConnectionFailed
GotConnection:
popf
clc
ret
ConnectionFailed:
mov al, SerialSelect or Asic4Id ; Asic4 Id
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
test al, al
jne ConnectionFailedExit
mov al, SerialSelect or Asic8Id ; Modem chip Id
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
test al, al
jne ConnectionFailedExit
mov al, SerialSelect or Asic5PackId ; Asic5pack Id
SBUSY
SCONTOUT
XNOP
SBUSY
SDATAIN
ConnectionFailedExit:
popf
stc
ret
ProcEnd noret
ProcBegin@ CheckHardwareFromStart
; =================================
pushf
HwNullFrame ; Check that the
mov al,(SerialSelect or Asic5NormalId) ; Harware is there
SBUSY ; First look for An
SCONTOUT ; ASIC5 at the other
XNOP ; End of the link
SBUSY
SDATAIN
test al,al
je ConnectionFailed ; If not a 3link or
test al, mask A5MultiDrop ; if in multidrop
jne ConnectionFailedExit ; mode then we are
popf ; in trouble
mov al, SerialWriteSingle or A5PortBMode
SBUSY
SCONTOUT ; Put the 3Link in
mov al, S_PERIPHERALMODE ; peripheral mode
SBUSY
SDATAOUT
clc
ret
ProcEnd noret
ProcBegin@ WaitTimer
; ====================
; In: CX number of ms to wait for
; Channel store in DL
; Out: Channel store in DL
inc cx ; Wait for a given
WaitTickLoop: ; Number of ms
call TickTimer ; Plus one to guarantee
loop WaitTickLoop ; That at least cx ms
ret ; Go by
ProcEnd
;
ProcBegin@ TickTimer
; ====================
; Uses writes down our channel to simulate tick timer waits
; Must allow interrupts so other things can run -we will be here
; for 1/1000 of a second and may be called many times
; ChannelStore in/out in DL
mov al, dl ; Return the old
HwSelectChannel ; channel
mov ah, al
pushf
sti
push cx
mov cx, 12 ; 1ms
WaiterLoop: ; 128 frames =1ms
pushf ; about 12 times
cli ; round the loop
out ResetWatchDog,al
mov al, ah
HwSelectChannel
mov dl, al ; Get Correct channel
mov al, (SerialWriteSingle or 0) ; Do a write to
SBUSY ; nowhere and
SCONTOUT ; waste some time
SBUSY
SCONTOUT ; Do it eight times
SBUSY
SCONTOUT
SBUSY
SCONTOUT
SBUSY
SCONTOUT
SBUSY
SCONTOUT
SBUSY
SCONTOUT
SBUSY
SCONTOUT
SBUSY
mov al, dl ; Return the old
HwSelectChannel ; channel
mov ah, al
popf
loop WaiterLoop
pop cx
popf
mov al, ah
HwSelectChannel
mov dl, al
ret
ProcEnd
EndCodeSeg
stack segment stack para 'data'
stack ends
end OsAS5PDD