1190 lines
49 KiB
NASM
1190 lines
49 KiB
NASM
title A4EXIF -- Example ASIC4 Interface device driver
|
|||
|
|
subttl Copyright (c) Psion PLC (1994)
|
||
|
|
name A4EXIF
|
||
|
|
;
|
||
|
|
; VER DATE BY DESCRIPTION
|
||
|
|
; ----------------------------------------
|
||
|
|
; 1.00F 26/1/95 Mal Working Version
|
||
|
|
|
||
|
|
|
||
|
|
;BUILDSB=1 ;S3a build environment (channels=1)
|
||
|
|
S3c=0 ;Need to specify no s3c
|
||
|
|
;BUILDSC=1 ;S3c build environment (channels=3)
|
||
|
|
BUILDCH=1 ;HC build environment (channels=3)
|
||
|
|
;BUILDHH=1 ;S3 build environment (channels=1)
|
||
|
|
|
||
|
|
include ..\inc\epoc.inc
|
||
|
|
include ..\inc\epoclib.inc
|
||
|
|
include ..\inc\epocsibo.inc
|
||
|
|
include ossibo.inc
|
||
|
|
include ospack.inc
|
||
|
|
|
||
|
|
; Example Logical Device Driver for prototype LED-ASIC4 Interface
|
||
|
|
; circuit for Corporate/S3C/Consumer serial port.
|
||
|
|
; Written by Mal Dec 1994/Jan 1995.
|
||
|
|
|
||
|
|
; A4EXIF CONSTANTS AND TYPES
|
||
|
|
; ==========================
|
||
|
|
; The following constants and type definitions
|
||
|
|
; are compiler directives used by the TCEP assembler
|
||
|
|
; when it is creating the LDD.
|
||
|
|
|
||
|
|
if Consumer
|
||
|
|
numberofchannels equ 1
|
||
|
|
else
|
||
|
|
if Corporate or S3c
|
||
|
|
numberofchannels equ 3
|
||
|
|
else
|
||
|
|
numberofchannels equ 2
|
||
|
|
endif
|
||
|
|
endif
|
||
|
|
|
||
|
|
;Channel StatusEnt block accessed through CS:DI
|
||
|
|
A4ExifStatusEnt struc
|
||
|
|
A4ExifCSProcessId dw ? ;Channel parent process id
|
||
|
|
A4ExifCSChannelOpen db ? ;Channel open flag
|
||
|
|
A4ExifCSChannelRunning db ? ;Channel hardware running flag
|
||
|
|
A4ExifCSChanReadCompleted db ? ;Channel request completed flag
|
||
|
|
A4ExifCSChannelIntMask db ? ;Channel interrupt mask
|
||
|
|
A4ExifCSChannelIntNum db ? ;Channel interrupt number
|
||
|
|
A4ExifCSChannelSelect db ? ;SIBO Channel select
|
||
|
|
A4ExifCSChannelIntVec dw ? ;Channel int vector number
|
||
|
|
A4ExifCSTickHandle dw ? ;TCK channel handle
|
||
|
|
A4ExifCSA1Value db ? ;Channel strategy A1 parameter
|
||
|
|
A4ExifCSA2Value db ? ;Channel strategy A2 parameter
|
||
|
|
A4ExifStatusEnt ends
|
||
|
|
|
||
|
|
;Open Channel Control block accessed through DS:BX
|
||
|
|
A4ExifEnt struc
|
||
|
|
A4ExifDSIo ChanEnt <> ;Open channel control block Ent
|
||
|
|
A4ExifDSHandlerPtr dw ? ;Cant touch when under
|
||
|
|
A4ExifDSStatusPtr dw ? ;Hold, Resume, Reset or
|
||
|
|
A4ExifDSA1Ptr dw ? ;interrupt routine
|
||
|
|
A4ExifDSA2Ptr dw ?
|
||
|
|
A4ExifDSStatusEntPtr dw ?
|
||
|
|
A4ExifEnt ends
|
||
|
|
|
||
|
|
|
||
|
|
A4PERIPH_MASK equ 0f0h ;11110000b
|
||
|
|
EXTENDED_INFO_BYTE equ 090h ;10010000b
|
||
|
|
U5_ENABLE_ON equ 080h ;Sets LBO for latch U5
|
||
|
|
U5_ENABLE_OFF equ 000h ;Deselects LBO for U5
|
||
|
|
|
||
|
|
;Latch addresses for reading/writing
|
||
|
|
U5OUTPUT_LATCH equ 00000000b ;Selects A0 for writing
|
||
|
|
U3INPUT_BUFFER equ 00000000b ;Selects A0 for reading
|
||
|
|
U4STATUS_BUFFER equ 00000001b ;Selects cs:[di].A4ExifCsA1Valuefor reading
|
||
|
|
INTERRUPT_LATCH equ 00000001b ;Selects A1 for writing
|
||
|
|
|
||
|
|
;Status byte masks
|
||
|
|
S2S3_ON equ 00000011b
|
||
|
|
S2S3_OFF equ 00000000b
|
||
|
|
S2_ONLY equ 00000001b
|
||
|
|
S3_ONLY equ 00000010b
|
||
|
|
INTERRUPT_STATUS_MASK equ 00000011b
|
||
|
|
|
||
|
|
;LED bytes
|
||
|
|
SOME_LEDS_ON equ 01010101b
|
||
|
|
SOME_LEDS_OFF equ 10101010b
|
||
|
|
TOP_LEDS_ON equ 11110000b
|
||
|
|
BOTTOM_LEDS_ON equ 00001111b
|
||
|
|
ZERO_BYTE equ 00h
|
||
|
|
|
||
|
|
dgroup group stack
|
||
|
|
assume ds:dgroup,es:dgroup,ss:dgroup
|
||
|
|
|
||
|
|
CodeSeg
|
||
|
|
|
||
|
|
; A4EXIF ENTRY TABLE
|
||
|
|
; ==================
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifLDD
|
||
|
|
; =========
|
||
|
|
|
||
|
|
dw LDDSignature
|
||
|
|
db 'LED',0,0,0,0,0
|
||
|
|
dw (VectorEnd-Vector)/2
|
||
|
|
Vector:
|
||
|
|
dw A4ExifInstall
|
||
|
|
dw A4ExifRemove
|
||
|
|
dw A4ExifHold
|
||
|
|
dw A4ExifResume
|
||
|
|
dw A4ExifReset
|
||
|
|
dw A4ExifUnits
|
||
|
|
dw A4ExifOpen
|
||
|
|
dw A4ExifStrategy
|
||
|
|
VectorHandler:
|
||
|
|
dw A4ExifHandler
|
||
|
|
if Asic9
|
||
|
|
InterruptVectors:
|
||
|
|
dw A4ExifTickInt
|
||
|
|
endif
|
||
|
|
VectorEnd:
|
||
|
|
|
||
|
|
|
||
|
|
; A4EXIF INTERNAL DATA SPACE
|
||
|
|
; ==========================
|
||
|
|
; Device Driver global variables follow.
|
||
|
|
; These variables reside in the code segment
|
||
|
|
; and as such can always be accessed with
|
||
|
|
; the 'cs:' prefix.
|
||
|
|
|
||
|
|
if Asic9
|
||
|
|
if Consumer
|
||
|
|
Channel0 A4ExifStatusEnt<0,0,0,0,mask A9MSlave,HwIrq2Revector,SelectChannel5,IntVec0,0,0>
|
||
|
|
else
|
||
|
|
if Corporate or S3c
|
||
|
|
Channel0 A4ExifStatusEnt<0,0,0,0,mask A9MExpIntA,HwIrq4Revector,SelectChannel3,IntVec0,0,0>
|
||
|
|
Channel1 A4ExifStatusEnt<0,0,0,0,mask A9MExpIntB,HwIrq5Revector,SelectChannel4,IntVec1,0,0>
|
||
|
|
Channel2 A4ExifStatusEnt<0,0,0,0,mask A9MSlave,HwIrq2Revector,SelectChannel5,IntVec2,0,0>
|
||
|
|
else
|
||
|
|
Channel0 A4ExifStatusEnt<0,0,0,0,mask A9MExpIntA,HwIrq4Revector,SelectChannel3,IntVec0,0,0>
|
||
|
|
Channel1 A4ExifStatusEnt<0,0,0,0,mask A9MExpIntB,HwIrq5Revector,SelectChannel4,IntVec1,0,0>
|
||
|
|
endif
|
||
|
|
endif
|
||
|
|
else
|
||
|
|
if Consumer
|
||
|
|
Channel0 A4ExifStatusEnt<0,0,0,0,mask Asic2Int,HwIrq4Revector,SelectChannel7,IntVec0,0,0>
|
||
|
|
else
|
||
|
|
if Corporate
|
||
|
|
Channel0 A4ExifStatusEnt<0,0,0,0,mask ExpIntLeftA,HwIrq3Revector,ExpChannelLeftA,IntVec0,0,0>
|
||
|
|
Channel1 A4ExifStatusEnt<0,0,0,0,mask ExpIntRightB,HwIrq2Revector,ExpChannelRightB,IntVec1,0,0>
|
||
|
|
Channel2 A4ExifStatusEnt<0,0,0,0,mask Asic2Int,HwIrq4Revector,SelectChannel7,IntVec2,0,0>
|
||
|
|
else
|
||
|
|
Channel0 A4ExifStatusEnt<0,0,0,0,mask ExpIntLeftA,HwIrq3Revector,ExpChannelLeftA,IntVec0,0,0>
|
||
|
|
Channel1 A4ExifStatusEnt<0,0,0,0,mask ExpIntRightB,HwIrq2Revector,ExpChannelRightB,IntVec1,0,0>
|
||
|
|
endif
|
||
|
|
endif
|
||
|
|
endif
|
||
|
|
|
||
|
|
HoldFlag db 0 ;Hold/Resume flag
|
||
|
|
SwitchStatus db ? ;Holds the masked status byte from U4 after interrupt
|
||
|
|
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifInstall,far
|
||
|
|
; =============
|
||
|
|
; Installs the device driver.
|
||
|
|
; Invoked after a PLIB 'p_loadldd("A4EXIF.LDD")' call to load the LDD
|
||
|
|
; All of the fields inside the CS control blocks are preloaded
|
||
|
|
; with the correct values at install time. Install therefore does
|
||
|
|
; not do any work.
|
||
|
|
; IN:
|
||
|
|
; Nothing
|
||
|
|
; OUT:
|
||
|
|
; Carry Clear - driver successfully installed
|
||
|
|
;
|
||
|
|
clc ;The ChannelOpen fields are set to zero
|
||
|
|
ret ;in the relevant ChannelStatusEnt headers
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifRemove,far
|
||
|
|
; ============
|
||
|
|
; Removes the device driver.
|
||
|
|
; Invoked after a PLIB 'p_devdel("LED",E_LDD)'call to unload the
|
||
|
|
; device driver.
|
||
|
|
; A device driver cannot be removed if any of its channels
|
||
|
|
; are still open.
|
||
|
|
; IN:
|
||
|
|
; Nothing
|
||
|
|
; OUT:
|
||
|
|
; Carry clear - successfully removed
|
||
|
|
; Carry set - remove failed, error number in AL
|
||
|
|
;
|
||
|
|
mov cx, numberofchannels ;Check that each
|
||
|
|
mov di, offset Channel0 ;channel is closed
|
||
|
|
xor ax, ax
|
||
|
|
CheckAllChannelsClosedLoop:
|
||
|
|
cmp cs:[di].A4ExifCSChannelOpen, al ;Closed channels will
|
||
|
|
jne WeHaveAChannelOpenSoFail ;have the value 0 in
|
||
|
|
add di, (size A4ExifStatusEnt) ;their ChannelOpen
|
||
|
|
loop CheckAllChannelsClosedLoop ;flags
|
||
|
|
jmp FinishedOkay
|
||
|
|
WeHaveAChannelOpenSoFail:
|
||
|
|
mov al, InUseErr ;Fail if not all
|
||
|
|
stc ;closed
|
||
|
|
ret
|
||
|
|
FinishedOkay:
|
||
|
|
clc
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifHold,far
|
||
|
|
; ==========
|
||
|
|
; Called by the operating system whenever the device driver is
|
||
|
|
; being moved or the machine is powering down.
|
||
|
|
; This will also be called by our pack door polling function when
|
||
|
|
; it sees that the doors have been opened and our peripheral has
|
||
|
|
; lost power.
|
||
|
|
; IN:
|
||
|
|
; Reason for the hold in AH
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
mov cx, 1 ;Hold can be called
|
||
|
|
xchg cl, HoldFlag ;when the driver is
|
||
|
|
cmp cl, 0 ;under a hold so
|
||
|
|
jne AlreadyHeld ;re-entrancy blocking
|
||
|
|
A4HoldFromTick: ;is required
|
||
|
|
mov cx, numberofchannels
|
||
|
|
mov di, offset Channel0 ;Loop because Hold
|
||
|
|
HoldAllTheChannelsLoop: ;must stop all the
|
||
|
|
cmp cs:[di].A4ExifCSChannelOpen, 0 ;channels
|
||
|
|
je DontHoldBecauseNotOpen ;Is the channel open?
|
||
|
|
push cx ;If it is then stop
|
||
|
|
call StopTheChannelRunning ;all interrupts
|
||
|
|
pop cx
|
||
|
|
DontHoldBecauseNotOpen:
|
||
|
|
add di, (size A4ExifStatusEnt)
|
||
|
|
loop HoldAllTheChannelsLoop
|
||
|
|
AlreadyHeld:
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifResume,far
|
||
|
|
; ============
|
||
|
|
; Called by the operating system when it has finished moving the
|
||
|
|
; device driver in memory or when the machine is switching back on.
|
||
|
|
; Also called by our door polling routine when it sees that the doors
|
||
|
|
; have been closed and we can resume communication with our peripheral.
|
||
|
|
; IN:
|
||
|
|
; Nothing
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
xor cx, cx ;Block in case of re-entrancy
|
||
|
|
xchg cl, HoldFlag
|
||
|
|
cmp cl, 0
|
||
|
|
je AlreadyResumed
|
||
|
|
if Asic9
|
||
|
|
GenDataSegment ;Check to see if the pack
|
||
|
|
HwGetSsdData ;doors are still closed
|
||
|
|
mov bx, ax
|
||
|
|
cmp es:[bx].SsdDoorStatus, DoorOpen
|
||
|
|
je DoorsAreOpen
|
||
|
|
endif
|
||
|
|
A4ResumeFromTick:
|
||
|
|
mov cx, numberofchannels ;Loop because resume must
|
||
|
|
mov di, offset Channel0 ;restart each open channel
|
||
|
|
ResumeAllTheChannelsLoop:
|
||
|
|
cmp cs:[di].A4ExifCSChannelOpen, 0 ;Is the channel open?
|
||
|
|
je DontResumeBecauseNotOpen
|
||
|
|
push cx
|
||
|
|
call StartTheChannelRunning
|
||
|
|
pop cx
|
||
|
|
DontResumeBecauseNotOpen:
|
||
|
|
add di, (size A4ExifStatusEnt)
|
||
|
|
loop ResumeAllTheChannelsLoop
|
||
|
|
AlreadyResumed:
|
||
|
|
ret
|
||
|
|
DoorsAreOpen:
|
||
|
|
mov HoldFlag, 2
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifReset,far
|
||
|
|
; ===========
|
||
|
|
; Called when an application which opened a channel terminates without
|
||
|
|
; closing the device driver.
|
||
|
|
; A device driver, for each open channel, has to request that the
|
||
|
|
; operating system calls this function when the application
|
||
|
|
; terminates abnormally (ie without closing an open channel).
|
||
|
|
; Reset can supply one piece of identifying data which will be
|
||
|
|
; passed in CX. This would usually be the channel's number or CS
|
||
|
|
; control block pointer.
|
||
|
|
; Reset just needs to clear interrupts, hardware reservations, and free
|
||
|
|
; the channel. Any allocated space will be cleaned up for you by the OS.
|
||
|
|
; IN:
|
||
|
|
; The device driver's handle in BX
|
||
|
|
; The address of the status struc identifying the channel in CX
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
mov di, cx
|
||
|
|
cmp cs:[di].A4ExifCSChannelOpen, 0
|
||
|
|
je NotOpenToReset
|
||
|
|
call StopTheChannelRunning ;Stop interrupts
|
||
|
|
mov al, cs:[di].A4ExifCSChannelIntMask ;Free the reserved
|
||
|
|
HwFreeChannel ;hardware
|
||
|
|
mov cs:[di].A4ExifCSChannelOpen, 0 ;The channel is now
|
||
|
|
NotOpenToReset: ;free
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifUnits,far
|
||
|
|
; ===========
|
||
|
|
; Called to find how many open channels the driver will support
|
||
|
|
; In:
|
||
|
|
; Nothing
|
||
|
|
; Out:
|
||
|
|
; The total number of channels supported in AX
|
||
|
|
;
|
||
|
|
mov ax, numberofchannels
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifOpen,far
|
||
|
|
; ==========
|
||
|
|
; Opens a device driver channel.
|
||
|
|
; Invoked after the PLIB call 'p_open(&appHandle,"LED:*",-1)'to open a
|
||
|
|
; channel to the device driver.
|
||
|
|
; In:
|
||
|
|
; OS device handle of the device driver in DX
|
||
|
|
; Pointer to the OpenEnt struc in SI
|
||
|
|
; Pointer to the IntEnt struc in BP
|
||
|
|
; DS,ES,SS point to the applications data space
|
||
|
|
; Out:
|
||
|
|
; Carry clear - BX holds the address of the open channel
|
||
|
|
; Carry set - AL holds the error number
|
||
|
|
;
|
||
|
|
cld ;Interrupts off to
|
||
|
|
pushf ;prevent multiple apps
|
||
|
|
cli ;calling open
|
||
|
|
mov si, [si].OpenNamePtr ;simultaneously
|
||
|
|
mov al, [si+1]
|
||
|
|
CharToFoldedChar ;Read the unit no.
|
||
|
|
cmp al, 'A' ;part of device name
|
||
|
|
jb OpenNameErr ;to find which channel
|
||
|
|
sub al, 'A' ;to open. eg "LED:A"
|
||
|
|
cmp al, numberofchannels
|
||
|
|
jae OpenNameErr
|
||
|
|
xor ah, ah
|
||
|
|
push dx ;Map the channel no.
|
||
|
|
mov dx, (size A4ExifStatusEnt) ;to a channel control
|
||
|
|
mul dx ;block in our CS
|
||
|
|
pop dx ;space
|
||
|
|
mov di, ax
|
||
|
|
add di, offset Channel0 ;Offset in DI
|
||
|
|
cmp cs:[di].A4ExifCSChannelOpen, 0
|
||
|
|
je GetATickChannel ;Check to see if
|
||
|
|
popf ;channel is already
|
||
|
|
mov ax, AlreadyOpenErr ;open
|
||
|
|
jmp ChannelAlreadyOpen
|
||
|
|
GetATickChannel:
|
||
|
|
mov cs:[di].A4ExifCSChannelOpen, 1 ;Obtain a TCK channel so
|
||
|
|
mov cs:[di].A4ExifCSChannelRunning,0 ;we can poll the door state
|
||
|
|
popf
|
||
|
|
ife Asic9
|
||
|
|
jmp GetHardwareChannel ;If HC, we don't need
|
||
|
|
else ;to set up the TCK
|
||
|
|
push ax ;routine
|
||
|
|
mov ax, ((':' shl 8)+'K')
|
||
|
|
push ax
|
||
|
|
mov ax, (('C' shl 8)+'T') ;Try to open "TCK:"
|
||
|
|
push ax ;channel with "TCK:"
|
||
|
|
mov bx, sp ;string on stack
|
||
|
|
IoOpen
|
||
|
|
jnc GotATickChannel ;TCK will call our
|
||
|
|
add sp, 6 ;door-polling function
|
||
|
|
mov ax, LockedErr ;32 times a second
|
||
|
|
jmp OpenFailed
|
||
|
|
GotATickChannel:
|
||
|
|
add sp, 6
|
||
|
|
mov cs:[di].A4ExifCSTickHandle, ax ;Start our
|
||
|
|
push dx ;door-polling function
|
||
|
|
mov bx, ax ;running by starting
|
||
|
|
mov ax, IoFuncStart ;the "TCK:" channel
|
||
|
|
mov cx, 1
|
||
|
|
push cx ;Frequency 1 tick
|
||
|
|
push cx ;Data irrelevant
|
||
|
|
push dx ;Handle to driver
|
||
|
|
mov cx, (InterruptVectors-Vector)/2 ;TCK function to call
|
||
|
|
push cx
|
||
|
|
mov cx, sp
|
||
|
|
IoWithWait
|
||
|
|
add sp, 8
|
||
|
|
pop dx
|
||
|
|
jmp GetHardwareChannel
|
||
|
|
endif
|
||
|
|
OpenNameErr:
|
||
|
|
popf
|
||
|
|
mov ax, NameErr
|
||
|
|
jmp ChannelAlreadyOpen
|
||
|
|
GetHardwareChannel: ;Check the hardware
|
||
|
|
mov al, cs:[di].A4ExifCSChannelIntMask ;is available then
|
||
|
|
HwGetChannel ;reserve it
|
||
|
|
jnc CheckHardwareNowThatSIBOChannelIsOpen ;Returns with carry
|
||
|
|
mov ax, InUseErr ;clear if OK
|
||
|
|
jmp FreeTckAndExit
|
||
|
|
FreeTckAndChannelHardware:
|
||
|
|
mov al, cs:[di].A4ExifCSChannelIntMask
|
||
|
|
HwFreeChannel
|
||
|
|
mov ax, DeviceErr
|
||
|
|
FreeTckAndExit:
|
||
|
|
if Asic9
|
||
|
|
push ax
|
||
|
|
mov bx, cs:[di].A4ExifCSTickHandle
|
||
|
|
IoClose
|
||
|
|
pop ax
|
||
|
|
endif
|
||
|
|
OpenFailed:
|
||
|
|
mov cs:[di].A4ExifCSChannelOpen, 0
|
||
|
|
ChannelAlreadyOpen:
|
||
|
|
stc
|
||
|
|
OpenExit:
|
||
|
|
ret
|
||
|
|
CheckHardwareNowThatSIBOChannelIsOpen:
|
||
|
|
ProcId ;Set up the calling
|
||
|
|
mov cs:[di].A4ExifCSProcessId, ax ;process ID
|
||
|
|
mov cs:[di].A4ExifCSChanReadCompleted, 0
|
||
|
|
call CheckHardwarePresent ;Returns with carry
|
||
|
|
jc FreeTckAndChannelHardware ;clear if successful
|
||
|
|
mov cx, (size A4ExifEnt) ;Allocate a control
|
||
|
|
HeapAllocateCell ;block in our app's
|
||
|
|
jc FreeTckAndChannelHardware ;data space
|
||
|
|
mov bx, ax
|
||
|
|
push bx ;IoAddHandler trashes BX
|
||
|
|
mov al, (VectorHandler-Vector)/2 ;Set up our wait handler
|
||
|
|
IoAddHandler ;Leaves the address of
|
||
|
|
pop bx ;handler in AX
|
||
|
|
jnc GotHandler
|
||
|
|
push ax ;If no handler, open fails
|
||
|
|
HeapFreeCell
|
||
|
|
pop ax
|
||
|
|
jmp FreeTckAndChannelHardware
|
||
|
|
GotHandler:
|
||
|
|
mov [bx].A4ExifDSStatusEntPtr, di
|
||
|
|
mov [bx].A4ExifDSHandlerPtr, ax
|
||
|
|
mov [bx].A4ExifDSStatusPtr, 0
|
||
|
|
mov [bx].A4ExifDSIo.ChanNext, bx
|
||
|
|
mov [bx].A4ExifDSIo.ChanSignature, IoChanSignature
|
||
|
|
mov [bx].A4ExifDSIo.ChanLibHandle, dx
|
||
|
|
mov cx, di ;IoRequestReset takes
|
||
|
|
xchg bx, dx ;the device handle in
|
||
|
|
IoRequestReset ;BX and the channel
|
||
|
|
xchg bx, dx ;handle in CX
|
||
|
|
xor ax, ax
|
||
|
|
call StartTheChannelRunning
|
||
|
|
ReturnCLC:
|
||
|
|
clc
|
||
|
|
ret
|
||
|
|
ProcEnd
|
||
|
|
|
||
|
|
|
||
|
|
if Asic9
|
||
|
|
ProcBegin@ A4ExifTickInt,far
|
||
|
|
; =============
|
||
|
|
; This function is called by the tick handler on every tick of
|
||
|
|
; the system clock. This happens 32 times a second.
|
||
|
|
; The operating system will call a device driver to hold when memory is
|
||
|
|
; being moved and when the machine is being powered down. It will not
|
||
|
|
; call the device driver when the pack doors are opened.
|
||
|
|
; Opening the pack doors will cause power to the peripheral to be cut,
|
||
|
|
; and therefore the driver needs to be held in the way it would be if
|
||
|
|
; the machine powered down. Only for Asic9 based machines.
|
||
|
|
; This function checks the state of the doors on every tick and calls
|
||
|
|
; Hold and resume when it sees the status of the doors change.
|
||
|
|
; IN:
|
||
|
|
; The state of the door in SI
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
cmp si, DoorOpen ;Is the door open
|
||
|
|
je TheDoorIsOpen ;or closed?
|
||
|
|
cmp HoldFlag, 2 ;Closed Door, HoldFlag=2
|
||
|
|
je NeedToDoTheResume ;means we do a resume
|
||
|
|
ret ;Closed Door, HoldFlag!=2
|
||
|
|
NeedToDoTheHold:
|
||
|
|
mov HoldFlag, 2
|
||
|
|
jmp A4HoldFromTick
|
||
|
|
NeedToDoTheResume:
|
||
|
|
mov HoldFlag, 0
|
||
|
|
jmp A4ResumeFromTick
|
||
|
|
TheDoorIsOpen:
|
||
|
|
xor ax, ax
|
||
|
|
cmp HoldFlag, al
|
||
|
|
je NeedToDoTheHold
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
endif
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifHandler,far
|
||
|
|
; =============
|
||
|
|
; When an application is waiting within an iowait and a signal is
|
||
|
|
; generated then before passing that signal to the application the
|
||
|
|
; OS first runs any wait handlers belonging to the device driver
|
||
|
|
; channels that the application has open.
|
||
|
|
; The interrupt routine can generate a signal but cannot fill in any
|
||
|
|
; status words or pass values back to the application because the
|
||
|
|
; applications DS space is not available. The handler can consume a
|
||
|
|
; signal generated by an interrupt and then fill any status words
|
||
|
|
; before re-signalling the application. A handler always has access
|
||
|
|
; to the application's DS space. The wait handler can consume the
|
||
|
|
; signal which is then no longer passed back to the application.
|
||
|
|
; IN:
|
||
|
|
; Pointer to our control block in applications DS space in BX
|
||
|
|
; DS,ES,SS point at application's data space
|
||
|
|
; OUT:
|
||
|
|
; Carry clear - do not consume the signal, signal not for us
|
||
|
|
; Carry set - consume the signal, re-enable handler if AL
|
||
|
|
; non-zero else don't re-enable handler if AL=0.
|
||
|
|
;
|
||
|
|
cld
|
||
|
|
pushf
|
||
|
|
cli
|
||
|
|
mov di, [bx].A4ExifDSStatusEntPtr ;Is the signal for us?
|
||
|
|
cmp cs:[di].A4ExifCSChanReadCompleted, 1
|
||
|
|
jne ExitHandlerSignalNotForUs ;If it is, copy
|
||
|
|
mov cs:[di].A4ExifCSChanReadCompleted, 0 ;the values read in
|
||
|
|
mov al, cs:[di].A4ExifCSA1Value ;the interrupt
|
||
|
|
mov ah, cs:[di].A4ExifCSA2Value ;routine back to
|
||
|
|
mov di, [bx].A4ExifDSA1Ptr ;the application
|
||
|
|
mov [di], al ;Asynchronous read
|
||
|
|
mov di, [bx].A4ExifDSA2Ptr ;has been completed
|
||
|
|
mov [di], ah
|
||
|
|
xor di, di
|
||
|
|
xchg [bx].A4ExifDSStatusPtr, di ;Clear the status
|
||
|
|
mov word ptr [di], 0 ;word
|
||
|
|
popf
|
||
|
|
IoSignal
|
||
|
|
xor ax, ax
|
||
|
|
stc ;STC and AL!=0 =>
|
||
|
|
ret ;consume signal and
|
||
|
|
ExitHandlerSignalNotForUs: ;don't re-enable
|
||
|
|
popf ;handler
|
||
|
|
clc
|
||
|
|
ret
|
||
|
|
ProcEnd
|
||
|
|
|
||
|
|
|
||
|
|
StrategyVectorTable label word
|
||
|
|
dw offset A4ExifDefault ;StrategyPanic
|
||
|
|
dw offset A4ExifRead ;StrategyRead ie P_FREAD
|
||
|
|
dw offset A4ExifWrite ;StrategyWrite ie P_FWRITE
|
||
|
|
dw offset A4ExifClose ;StrategyClose ie P_FCLOSE
|
||
|
|
dw offset A4ExifCancel ;StrategyCancel ie P_FCANCEL
|
||
|
|
dw offset A4ExifDefault ;StrategyAttach
|
||
|
|
dw offset A4ExifDefault ;StrategyDetach
|
||
|
|
dw offset A4ExifSet ;StrategySet ie P_FSET
|
||
|
|
dw offset A4ExifSense ;StrategySense ie P_FSENSE
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifStrategy,far
|
||
|
|
; ==============
|
||
|
|
; Called by the operating system when an I/O request is made on
|
||
|
|
; the device driver.
|
||
|
|
; Calls to this funcion from an owning application will usually take
|
||
|
|
; the form p_ioc(pcb,func,&Stat,&A1,&A2);
|
||
|
|
; The strategy function is called with a function number specifying
|
||
|
|
; the action which the driver is to take, a status word to fill when
|
||
|
|
; the action is complete, and two arguments A1 and A2.
|
||
|
|
; All strategy functions must complete with a signal to the application.
|
||
|
|
; Functions can be asynchronous and need not complete immediately.
|
||
|
|
; IN:
|
||
|
|
; Pointer to our control block in the applications DS in BX
|
||
|
|
; Device driver handle in DX
|
||
|
|
; Pointer to the RqEnt struct in SI
|
||
|
|
; Pointer to a IntEnt struct in BP
|
||
|
|
; DS,ES,SS point at the applications data space
|
||
|
|
; OUT:
|
||
|
|
; Returned value in AX
|
||
|
|
; Must call IoSignal somewhere to signal completion
|
||
|
|
; of the I/O request.
|
||
|
|
;
|
||
|
|
mov ax, [si].RqFunction ;Get the function number
|
||
|
|
mov dx, [si].RqA1Ptr ;DX holds the first argument
|
||
|
|
mov di, [si].RqStatusPtr ;for convenience
|
||
|
|
mov word ptr [di], PendingErr ;Status word holds
|
||
|
|
shl ax, 1 ;E_FILE_PENDING
|
||
|
|
mov di, ax
|
||
|
|
push StrategyVectorTable[di] ;Jump to required function
|
||
|
|
mov di, [bx].A4ExifDSStatusEntPtr ;with our CS control block
|
||
|
|
retn ;pointer in DI
|
||
|
|
A4ExifDefault:
|
||
|
|
IoRoot
|
||
|
|
ret
|
||
|
|
ExitWithCompletionStatusZero:
|
||
|
|
xor ax, ax ;Common exit points
|
||
|
|
ExitWithOtherCompletionStatus:
|
||
|
|
mov di, [si].RqStatusPtr
|
||
|
|
mov word ptr [di], ax
|
||
|
|
IoSignal
|
||
|
|
ExitStillPending:
|
||
|
|
xor ax, ax
|
||
|
|
clc
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
; STRATEGY VECTOR TABLE FUNCTIONS
|
||
|
|
; ===============================
|
||
|
|
;IN:
|
||
|
|
; DX holds the pointer to the first argument in 'p_iow(...)' call
|
||
|
|
; BX holds the address of the open channel control block
|
||
|
|
; CS:DI holds the address of status struc identifying the open channel
|
||
|
|
;
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifRead,far
|
||
|
|
; ==========
|
||
|
|
; Strategy vector table function that handles asynchronous byte reads
|
||
|
|
; from the LEDs and switches.
|
||
|
|
; The corresponding PLIB call is p_ioc(pcb,P_FREAD,&Stat,&Arg1,&Arg2);
|
||
|
|
; The request is completed when the interrupt routine signals the
|
||
|
|
; handler which in turn signals the application passing back the values
|
||
|
|
; read at the time of the interrupt through the A1Ptr and A2Ptr.
|
||
|
|
; IN:
|
||
|
|
; Pointer to control block in applications data space in BX
|
||
|
|
; Pointer to control block in our CS space in DI
|
||
|
|
; A1 (pointer to Arg1) in DX
|
||
|
|
; OUT:
|
||
|
|
; Jumps to common exit point
|
||
|
|
; Panics if multiple requests
|
||
|
|
;
|
||
|
|
cmp [bx].A4ExifDSStatusPtr, 0 ;Panic if we already
|
||
|
|
jne PanicPending ;have an I/O read request
|
||
|
|
pushf ;pending on the channel
|
||
|
|
cli ;Disable interrupts
|
||
|
|
mov cs:[di].A4ExifCSChanReadCompleted, 2
|
||
|
|
mov ax, [si].RqA1Ptr
|
||
|
|
mov [bx].A4ExifDSA1Ptr, ax ;Store the locations to
|
||
|
|
mov ax, [si].RqA2Ptr ;put the data when we get it
|
||
|
|
mov [bx].A4ExifDSA2Ptr, ax
|
||
|
|
mov di, [si].RqStatusPtr
|
||
|
|
mov [bx].A4ExifDSStatusPtr, di ;DI holds the address
|
||
|
|
mov word ptr [di], PendingErr ;of status word and we
|
||
|
|
popf ;signal that we are waiting
|
||
|
|
mov bx, [bx].A4ExifDSHandlerPtr ;for completion of read
|
||
|
|
mov cl, 1
|
||
|
|
IoEnableHandler ;Enable Wait Handler
|
||
|
|
jmp short ExitStillPending ;No IoSignal because
|
||
|
|
PanicPending: ;we are still waiting
|
||
|
|
mov al, PanicIoPending
|
||
|
|
ProcPanic
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifWrite,far
|
||
|
|
; ===========
|
||
|
|
; This function sets the state of the LEDs.
|
||
|
|
; It completes immediately after setting the state as it has nothing
|
||
|
|
; to wait for.
|
||
|
|
; Write is the same as set.
|
||
|
|
; IN:
|
||
|
|
; Pointer to control block in applications data space in BX
|
||
|
|
; Pointer to control block in our CS space in DI
|
||
|
|
; A1 in DX
|
||
|
|
; OUT:
|
||
|
|
; Jumps to Set
|
||
|
|
;
|
||
|
|
jmp WriteAndSetAreTheSame
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifClose,far
|
||
|
|
; ===========
|
||
|
|
; Handles the request to close a channel.
|
||
|
|
; called by the PLIB call p_iow(pcb,P_FCLOSE) or p_close(pcb)
|
||
|
|
; IN:
|
||
|
|
; Pointer to control block in applications data space in BX
|
||
|
|
; Pointer to control block in our CS space in DI
|
||
|
|
; OUT:
|
||
|
|
; Jumps to common exit point
|
||
|
|
;
|
||
|
|
call StopTheChannelRunning ;Stop interrupts
|
||
|
|
if Asic9
|
||
|
|
push bx ;Close down the
|
||
|
|
mov bx, cs:[di].A4ExifCSTickHandle ;"TCK:" channel
|
||
|
|
IoClose
|
||
|
|
pop bx
|
||
|
|
endif
|
||
|
|
push bx
|
||
|
|
mov ax, [bx].A4ExifDSIo.ChanLibHandle ;Remove the wait
|
||
|
|
push ax ;handler
|
||
|
|
mov bx, [bx].A4ExifDSHandlerPtr
|
||
|
|
IoRemoveHandler
|
||
|
|
cmp cs:[di].A4ExifCSChanReadCompleted, 0 ;If the interrupt
|
||
|
|
je NoSignalToConsumeFromInterrupt ;has signalled the
|
||
|
|
IoWaitForSignal ;handler we need to
|
||
|
|
NoSignalToConsumeFromInterrupt: ;consume its signal
|
||
|
|
pop bx ;now the handler
|
||
|
|
mov cx, di ;has been removed
|
||
|
|
IoRequestResetCancel
|
||
|
|
pop bx ;No longer need reset
|
||
|
|
HeapFreeCell ;Free our control
|
||
|
|
mov al, cs:[di].A4ExifCSChannelIntMask ;block in app's DS
|
||
|
|
HwFreeChannel
|
||
|
|
mov cs:[di].A4ExifCSChannelOpen, 0
|
||
|
|
jmp ExitWithCompletionStatusZero ;To signal completion
|
||
|
|
ProcEnd noret ;of close request
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifCancel,far
|
||
|
|
; ============
|
||
|
|
; Cancel any pending asynchronous read.
|
||
|
|
; Called by the PLIB function p_iow(pcb,P_FCANCEL);
|
||
|
|
; In:
|
||
|
|
; Pointer to control block in applications data space in BX
|
||
|
|
; Pointer to control block in our CS space in DI
|
||
|
|
; Out:
|
||
|
|
; Jumps to common exit point
|
||
|
|
;
|
||
|
|
pushf
|
||
|
|
cli
|
||
|
|
cmp [bx].A4ExifDSStatusPtr, 0 ;Check that there is
|
||
|
|
je NothingToCancel ;a request pending
|
||
|
|
push bx
|
||
|
|
mov bx, [bx].A4ExifDSHandlerPtr
|
||
|
|
sub cl, cl
|
||
|
|
IoEnableHandler ;Disable Wait Handler
|
||
|
|
pop bx
|
||
|
|
cmp cs:[di].A4ExifCSChanReadCompleted, 1
|
||
|
|
jne NoSignalFromInterrupt ;To consume any stray
|
||
|
|
IoWaitForSignal ;signal from the
|
||
|
|
NoSignalFromInterrupt: ;interrupt routine
|
||
|
|
mov cs:[di].A4ExifCSChanReadCompleted, 0
|
||
|
|
xor di, di ;To signal completion
|
||
|
|
xchg di, [bx].A4ExifDSStatusPtr ;of the outstanding
|
||
|
|
mov word ptr [di], CancelErr ;async read request
|
||
|
|
IoSignal ;Signal to p_waitstat
|
||
|
|
NothingToCancel:
|
||
|
|
popf
|
||
|
|
jmp ExitWithCompletionStatusZero ;To signal completion
|
||
|
|
ProcEnd noret ;of the cancel request
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifSet,far
|
||
|
|
; =========
|
||
|
|
; Write a value to the LED latch.
|
||
|
|
; Can be called by the PLIB call p_iow(pcb,P_FSET,&Arg1); where A1
|
||
|
|
; is an unsigned byte.
|
||
|
|
; Write is the same as set.
|
||
|
|
; IN:
|
||
|
|
; Pointer to control block in applications data space in BX
|
||
|
|
; Pointer to control block in our CS space in DI
|
||
|
|
; A1 (pointer to Arg1) in DX
|
||
|
|
; OUT:
|
||
|
|
; Jumps to common exit point
|
||
|
|
;
|
||
|
|
WriteAndSetAreTheSame:
|
||
|
|
pushf
|
||
|
|
cli
|
||
|
|
mov al, cs:[di].A4ExifCSChannelSelect ;Select our SIBO
|
||
|
|
HwSelectChannel ;serial channel
|
||
|
|
push ax ;Store old channel
|
||
|
|
mov bx, dx
|
||
|
|
mov dl, U5OUTPUT_LATCH ;DX (now BX) points
|
||
|
|
mov al, [bx] ;to the value to
|
||
|
|
call OutputByte ;output to our
|
||
|
|
pop ax ;peripheral
|
||
|
|
HwSelectChannel ;Return old channel
|
||
|
|
popf
|
||
|
|
jmp ExitWithCompletionStatusZero ;To signal completion
|
||
|
|
ProcEnd noret ;of set request
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ A4ExifSense,far
|
||
|
|
; ===========
|
||
|
|
; Reads the state of the LEDS and Switches.
|
||
|
|
; Can be called from PLIB using p_iow(pcb,P_FSENSE,&Arg1,&Arg2)
|
||
|
|
; Where Arg1 and Arg2 are unsigned bytes.
|
||
|
|
; In:
|
||
|
|
; Pointer to control block in applications data space in BX
|
||
|
|
; Pointer to control block in our CS space in DI
|
||
|
|
; A1 (pointer to Arg1) in DX
|
||
|
|
; Out:
|
||
|
|
; Jumps to common exit point
|
||
|
|
;
|
||
|
|
pushf
|
||
|
|
cli ;Select our SIBO
|
||
|
|
mov al, cs:[di].A4ExifCSChannelSelect ;serial channel
|
||
|
|
HwSelectChannel ;Store old channel
|
||
|
|
push ax
|
||
|
|
mov bx, dx ;DX (now BX) points
|
||
|
|
mov dl, U4STATUS_BUFFER ;to the variable in
|
||
|
|
call InputByte ;which to place the
|
||
|
|
mov [bx], al ;value read from U4.
|
||
|
|
mov bx, [si].RqA2Ptr ;BX now points to
|
||
|
|
mov dl, U3INPUT_BUFFER ;the variable in
|
||
|
|
call InputByte ;which to place the
|
||
|
|
mov [bx], al ;value read from U3.
|
||
|
|
pop ax
|
||
|
|
HwSelectChannel ;Return old channel
|
||
|
|
popf
|
||
|
|
jmp ExitWithCompletionStatusZero ;To signal completion
|
||
|
|
ProcEnd noret ;of a sense request
|
||
|
|
|
||
|
|
|
||
|
|
; LOCAL DEVICE DRIVER FUNCTIONS
|
||
|
|
; =============================
|
||
|
|
|
||
|
|
ProcBegin@ InputByte
|
||
|
|
; =========
|
||
|
|
; Interrupts must be off prior to the call to this function.
|
||
|
|
; IN:
|
||
|
|
; DL has address to which Asic4 is to write
|
||
|
|
; AL holds the value to output
|
||
|
|
;
|
||
|
|
mov al, (SerialWriteSingle or A4Address)
|
||
|
|
SBUSY
|
||
|
|
SCONTOUT
|
||
|
|
mov al, dl
|
||
|
|
SBUSY
|
||
|
|
SDATAOUT
|
||
|
|
mov al, (SerialReadSingle or A4Data)
|
||
|
|
SBUSY
|
||
|
|
SCONTOUT
|
||
|
|
SBUSY
|
||
|
|
SDATAIN
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ OutputByte
|
||
|
|
; ==========
|
||
|
|
; Interrupts must be off prior to the call to this function.
|
||
|
|
; IN:
|
||
|
|
; DL has address to which Asic4 is to write
|
||
|
|
; AL has the value to output
|
||
|
|
;
|
||
|
|
push ax
|
||
|
|
mov al, (SerialWriteSingle or A4Address)
|
||
|
|
SBUSY
|
||
|
|
SCONTOUT
|
||
|
|
mov al, dl
|
||
|
|
SBUSY
|
||
|
|
SDATAOUT
|
||
|
|
mov al, (SerialWriteSingle or A4Data)
|
||
|
|
SBUSY
|
||
|
|
SCONTOUT
|
||
|
|
SBUSY
|
||
|
|
XNOP
|
||
|
|
pop ax
|
||
|
|
SDATAOUT
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ IntVec0,far
|
||
|
|
; ===========
|
||
|
|
; Interrupt on serial channel0
|
||
|
|
; Calls Comint with channel control block pointer in DI
|
||
|
|
;
|
||
|
|
mov di, offset Channel0
|
||
|
|
jmp ComInt
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
if Corporate or S3c
|
||
|
|
ProcBegin@ IntVec1,far
|
||
|
|
; ===========
|
||
|
|
; Interrupt on serial channel1
|
||
|
|
; Calls Comint with channel control block pointer in DI
|
||
|
|
;
|
||
|
|
mov di, offset Channel1
|
||
|
|
jmp ComInt
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ IntVec2,far
|
||
|
|
; ===========
|
||
|
|
; Interrupt on serial channel2
|
||
|
|
; Calls Comint with channel control block pointer in DI
|
||
|
|
;
|
||
|
|
mov di, offset Channel2
|
||
|
|
; FALL THROUGH
|
||
|
|
ProcEnd noret
|
||
|
|
endif
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ ComInt,far
|
||
|
|
; ==========
|
||
|
|
; The common interrupt service routine code.
|
||
|
|
; When an interrupt occurs, the first task is to read the status
|
||
|
|
; buffer of latch U4. The subsequent action is dependent on the
|
||
|
|
; postion of switches S1 and S2. For the purposes of this example,
|
||
|
|
; the four posibilities for the switch values correspond somewhat
|
||
|
|
; arbitrarily to four different byte values that are written to U5.
|
||
|
|
; in the 8086, interrupts cannot occur while in an interrupt routine.
|
||
|
|
; If an asynchronous read is pending then the handler is signalled.
|
||
|
|
; IN:
|
||
|
|
; Channel's CS based control block pointer in DI
|
||
|
|
;
|
||
|
|
cmp cs:[di].A4ExifCSChanReadCompleted, 2 ;Only if 2 do we have
|
||
|
|
jne NotAsynchronousRead ;asynch read completed
|
||
|
|
mov cs:[di].A4ExifCSChanReadCompleted, 1
|
||
|
|
mov bx, cs:[di].A4ExifCSProcessId ;Signals completion
|
||
|
|
IoSignalByPidNoReSched ;of read to OS so as
|
||
|
|
NotAsynchronousRead: ;to invoke handler
|
||
|
|
mov al, cs:[di].A4ExifCSChannelSelect
|
||
|
|
HwSelectChannel
|
||
|
|
push ax
|
||
|
|
mov dl, U3INPUT_BUFFER
|
||
|
|
call InputByte
|
||
|
|
mov cs:[di].A4ExifCSA2Value, al ;LED byte
|
||
|
|
mov dl, U4STATUS_BUFFER
|
||
|
|
call InputByte
|
||
|
|
mov cs:[di].A4ExifCSA1Value, al ;Status byte
|
||
|
|
and al, INTERRUPT_STATUS_MASK
|
||
|
|
xchg al, SwitchStatus
|
||
|
|
cmp SwitchStatus, S2S3_ON ;S2 and S3 on => turn
|
||
|
|
je AllLEDsOn ;on alternate LEDs
|
||
|
|
cmp SwitchStatus, S2S3_OFF ;S2 and S3 off => not
|
||
|
|
je AllLEDsOff ;the alternate LEDs
|
||
|
|
cmp SwitchStatus, S2_ONLY ;S2 on, S3 off => turn
|
||
|
|
je TopLEDsOn ;on top four LEDs
|
||
|
|
cmp SwitchStatus, S3_ONLY ;S3 on, S2 off => turn
|
||
|
|
je BottomLEDsOn ;on bottom four LEDs
|
||
|
|
ErrorInSwitchStatusByte:
|
||
|
|
jmp ClearInterruptAndReschedule
|
||
|
|
AllLEDsOn:
|
||
|
|
mov al, SOME_LEDS_ON
|
||
|
|
jmp OutputLEDByte
|
||
|
|
AllLEDsOff:
|
||
|
|
mov al, SOME_LEDS_OFF
|
||
|
|
jmp OutputLEDByte
|
||
|
|
TopLEDsOn:
|
||
|
|
mov al, TOP_LEDS_ON
|
||
|
|
jmp OutputLEDByte
|
||
|
|
BottomLEDsOn:
|
||
|
|
mov al, BOTTOM_LEDS_ON
|
||
|
|
OutputLEDByte:
|
||
|
|
mov dl, U5OUTPUT_LATCH
|
||
|
|
call OutputByte
|
||
|
|
ClearInterruptAndReschedule:
|
||
|
|
mov dl, INTERRUPT_LATCH
|
||
|
|
call OutputByte
|
||
|
|
if Asic9 ;A write to this location
|
||
|
|
out A9BNonSpecificEoiW, al ;informs the interrupt
|
||
|
|
else ;controller that the
|
||
|
|
out A1NonSpecificEoi, al ;installed interrupt
|
||
|
|
endif ;service routine has
|
||
|
|
pop ax ;finished
|
||
|
|
HwSelectChannel
|
||
|
|
clc ;Reschedule if necessary
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ StartInterrupts
|
||
|
|
; ===============
|
||
|
|
; Start interrupts assuming interrupts are
|
||
|
|
; off prior to call.
|
||
|
|
; The EPOC GenSetRevector service loads in
|
||
|
|
; a user-specified interrupt service routine
|
||
|
|
; located at the address given in cx:bx
|
||
|
|
; (segment cx, offset bx) for the interrupt
|
||
|
|
; vector number given in AL. Note that the
|
||
|
|
; variable A4ExifCSChannelIntVec holds the
|
||
|
|
; name of the appropriate required interrupt
|
||
|
|
; vector routine for the channel.
|
||
|
|
; IN:
|
||
|
|
; Our CS control block pointer in DI
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
mov al, cs:[di].A4ExifCSChannelIntNum ;Get the OS to call
|
||
|
|
mov cx, cs ;the function in
|
||
|
|
push bx ;CS:BX every time
|
||
|
|
mov bx, cs:[di].A4ExifCSChannelIntVec ;that the interrupt
|
||
|
|
GenSetRevector ;whose number is in
|
||
|
|
pop bx ;AL occurs
|
||
|
|
ife Asic9
|
||
|
|
in al, A1InterruptMask
|
||
|
|
or al, cs:[di].A4ExifCSChannelIntMask ;Set the mask
|
||
|
|
out A1InterruptMask, al ;location so as ;interrupt
|
||
|
|
else ;to enable that
|
||
|
|
in al, A9BInterruptMaskRW ;interrupt
|
||
|
|
or al, cs:[di].A4ExifCSChannelIntMask
|
||
|
|
out A9BInterruptMaskRW, al
|
||
|
|
|
||
|
|
endif
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ StopInterrupts
|
||
|
|
; ==============
|
||
|
|
; Stop interrupts assuming that interrupts are off
|
||
|
|
; The EPOC GenResetRevector OS service
|
||
|
|
; replaces the previously loaded user-specified
|
||
|
|
; interrupt service routine with the original
|
||
|
|
; routine and interrupt mask for the vector
|
||
|
|
; given in AL.
|
||
|
|
; IN:
|
||
|
|
; Our CS control block pointer in DI
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
ife Asic9
|
||
|
|
in al, A1InterruptMask ;Disable the
|
||
|
|
mov ah, cs:[di].A4ExifCSChannelIntMask ;interrupt
|
||
|
|
not ah
|
||
|
|
and al, ah
|
||
|
|
out A1InterruptMask, al
|
||
|
|
else
|
||
|
|
in al, A9BInterruptMaskRW
|
||
|
|
mov ah, cs:[di].A4ExifCSChannelIntMask
|
||
|
|
not ah
|
||
|
|
and al, ah
|
||
|
|
out A9BInterruptMaskRW, al
|
||
|
|
endif
|
||
|
|
mov al, cs:[di].A4ExifCSChannelIntNum ;Return the interrupt
|
||
|
|
GenResetRevector ;vector to the OS
|
||
|
|
ret ;default
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ StartTheChannelRunning
|
||
|
|
; ======================
|
||
|
|
; Starts the hardware and interrupts going
|
||
|
|
; If the hardware is aready running then there is nothing to do
|
||
|
|
; Must check that the hardware has not vanished before restarting it
|
||
|
|
; IN:
|
||
|
|
; Our CS control block pointer in DI
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
pushf
|
||
|
|
cli
|
||
|
|
cmp byte ptr cs:[di].A4ExifCSChannelRunning, 0
|
||
|
|
jne ChannelAlreadyRunning
|
||
|
|
call CheckHardwarePresent
|
||
|
|
jc HardwareNotPresent
|
||
|
|
mov al, cs:[di].A4ExifCSChannelSelect
|
||
|
|
HwSelectChannel
|
||
|
|
push ax
|
||
|
|
mov al, (SerialWriteSingle or A4Control) ;Switch on the
|
||
|
|
SBUSY ;output latch U5
|
||
|
|
SCONTOUT ;by asserting
|
||
|
|
mov al, U5_ENABLE_ON ;the ASIC4 LBO line
|
||
|
|
SBUSY ;(LBO is inverted)
|
||
|
|
SDATAOUT
|
||
|
|
xor ax,ax
|
||
|
|
mov dl, INTERRUPT_LATCH ;Clear any pending
|
||
|
|
call OutputByte ;interrupt on the
|
||
|
|
mov dl, U5OUTPUT_LATCH ;peripheral
|
||
|
|
call OutputByte ;Preset the LEDs
|
||
|
|
pop ax ;to all off
|
||
|
|
HwSelectChannel
|
||
|
|
call StartInterrupts
|
||
|
|
mov cs:[di].A4ExifCSChannelRunning, 1
|
||
|
|
ChannelAlreadyRunning:
|
||
|
|
popf
|
||
|
|
clc
|
||
|
|
ret
|
||
|
|
HardwareNotPresent:
|
||
|
|
popf
|
||
|
|
stc
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ StopTheChannelRunning
|
||
|
|
; =====================
|
||
|
|
; Stops the hardware and interrupts
|
||
|
|
; Checks to see if the hardware is really running to start with
|
||
|
|
; IN:
|
||
|
|
; Our CS control block pointer in DI
|
||
|
|
; OUT:
|
||
|
|
; Nothing
|
||
|
|
;
|
||
|
|
pushf
|
||
|
|
cli
|
||
|
|
cmp byte ptr cs:[di].A4ExifCSChannelRunning, 0
|
||
|
|
je ChannelNotRunning
|
||
|
|
mov al, cs:[di].A4ExifCSChannelSelect
|
||
|
|
HwSelectChannel
|
||
|
|
push ax
|
||
|
|
mov al, (SerialWriteSingle or A4Control)
|
||
|
|
SBUSY
|
||
|
|
SCONTOUT
|
||
|
|
mov al, U5_ENABLE_OFF
|
||
|
|
SBUSY
|
||
|
|
SDATAOUT
|
||
|
|
xor ax, ax
|
||
|
|
mov dl, U5OUTPUT_LATCH
|
||
|
|
call OutputByte
|
||
|
|
pop ax
|
||
|
|
HwSelectChannel
|
||
|
|
call StopInterrupts
|
||
|
|
mov cs:[di].A4ExifCSChannelRunning, 0
|
||
|
|
ChannelNotRunning:
|
||
|
|
popf
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
|
||
|
|
ProcBegin@ CheckHardwarePresent
|
||
|
|
; ====================
|
||
|
|
; Used to determine whether the correct hardware is present
|
||
|
|
; on the successfully procured serial channel.
|
||
|
|
; IN:
|
||
|
|
; CS control block pointer in DI
|
||
|
|
; OUT:
|
||
|
|
; Carry clear - correct hardware is there
|
||
|
|
; Carry set - wrong or no hardware
|
||
|
|
;
|
||
|
|
pushf
|
||
|
|
cli ;Select the correct
|
||
|
|
mov al, cs:[di].A4ExifCSChannelSelect ;SIBO channel that
|
||
|
|
HwSelectChannel ;the peripheral is
|
||
|
|
push ax ;attached to
|
||
|
|
HwNullFrame
|
||
|
|
mov al,(SerialSelect or Asic4Id)
|
||
|
|
SBUSY ;First look for an
|
||
|
|
SCONTOUT ;ASIC4 at the other
|
||
|
|
XNOP ;end of the link
|
||
|
|
SBUSY
|
||
|
|
SDATAIN ;If the returned
|
||
|
|
test al,al ;value is non-zero
|
||
|
|
je ConnectionFailedA4NotPresent ;we have an ASIC4
|
||
|
|
mov al,(SerialReadSingle or A4InfoR)
|
||
|
|
SBUSY ;Now see if we have
|
||
|
|
SCONTOUT ;the right peripheral
|
||
|
|
XNOP ;XNOP allows the busy
|
||
|
|
SBUSY ;signal to come
|
||
|
|
SDATAIN ;through for the wait
|
||
|
|
and al, A4PERIPH_MASK
|
||
|
|
cmp al, EXTENDED_INFO_BYTE ;Mask out the bottom
|
||
|
|
jne ConnectionFailed ;four bits as the
|
||
|
|
pop ax ;upper four contain
|
||
|
|
HwSelectChannel ;the peripheral ID
|
||
|
|
popf
|
||
|
|
clc ;If it is our hardware
|
||
|
|
ret ;exit with carry clear
|
||
|
|
ConnectionFailedA4NotPresent:
|
||
|
|
mov al,(SerialSelect or Asic5NormalId) ;Its not an ASIC4
|
||
|
|
SBUSY ;peripheral
|
||
|
|
SCONTOUT ;By selecting a non
|
||
|
|
XNOP ;ASIC4 as an ASIC4,
|
||
|
|
SDATAIN ;we effectively
|
||
|
|
test al,al ;disable whatever is
|
||
|
|
jne ConnectionFailed ;out there so we do
|
||
|
|
mov al,(SerialSelect or Asic5PackId) ;a select for all
|
||
|
|
SBUSY ;possibilities so
|
||
|
|
SCONTOUT ;that we don't end
|
||
|
|
XNOP ;up disabling
|
||
|
|
SDATAIN ;anything that we
|
||
|
|
test al,al ;can't control.
|
||
|
|
jne ConnectionFailed
|
||
|
|
mov al,(SerialSelect or Asic8Id) ;Modem chip id
|
||
|
|
SBUSY
|
||
|
|
SCONTOUT
|
||
|
|
XNOP
|
||
|
|
SDATAIN
|
||
|
|
ConnectionFailed:
|
||
|
|
pop ax
|
||
|
|
HwSelectChannel
|
||
|
|
popf
|
||
|
|
stc
|
||
|
|
ret
|
||
|
|
ProcEnd noret
|
||
|
|
|
||
|
|
EndCodeSeg
|
||
|
|
stack segment stack para 'data'
|
||
|
|
stack ends
|
||
|
|
end A4ExifLDD
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|