build: add the SIBO SDK
This commit is contained in:
@@ -0,0 +1,446 @@
|
||||
title ATIMDVR -- Attached timer device driver example
|
||||
subttl Copyright (c) Psion PLC 1991
|
||||
name ATIMDVR
|
||||
;
|
||||
; VER DATE BY DESCRIPTION
|
||||
; ----- -------- ---- -----------
|
||||
; 1.00A 01/02/92 JH Alpha release
|
||||
;
|
||||
TURBOC equ 1
|
||||
;
|
||||
include epocdef.inc
|
||||
include epocmac.inc
|
||||
include epocpan.inc
|
||||
include epoclib.inc
|
||||
include epocser.inc
|
||||
|
||||
HandlerDisable equ 000h ; the hnadler should not be called
|
||||
HandlerEnable equ 001h ; the handler should be called
|
||||
;
|
||||
TimerEnt struc
|
||||
TimerIo ChanEnt <> ; I/O device driver hdr
|
||||
ReadRq RqEnt <> ; read request info
|
||||
ReadStat dw ? ; read completion status
|
||||
InStrategy dw ? ; internal control
|
||||
WaitHandler dw ? ; wait handler handle
|
||||
TimerChan dw ? ; open timer channel handle
|
||||
Timeout dd ? ; read timout
|
||||
TimerStat dw ? ; timer completion status
|
||||
TimerEnt ends
|
||||
|
||||
CodeSeg
|
||||
|
||||
ProcBegin@ AttachedTimerLDD
|
||||
; =================
|
||||
; The externally loadable Attached timer device table
|
||||
dw LDDSignature
|
||||
db 'ATM',0,0,0,0,0
|
||||
dw (VectorEnd-Vector)/2
|
||||
Vector:
|
||||
dw AttachedTimerInstall
|
||||
dw AttachedTimerRemove
|
||||
dw AttachedTimerHold
|
||||
dw AttachedTimerResume
|
||||
dw AttachedTimerReset
|
||||
dw AttachedTimerUnits
|
||||
dw AttachedTimerOpen
|
||||
dw AttachedTimerStrategy
|
||||
VectorHandler:
|
||||
dw AttachedTimerHandler
|
||||
VectorEnd:
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ AttachedTimerInstall,far
|
||||
; =====================
|
||||
; Called on device installation by the operating system
|
||||
;
|
||||
clc ; installed OK
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ AttachedTimerRemove,far
|
||||
; ====================
|
||||
; Always allow to be removed.
|
||||
;
|
||||
clc ; removed ok.
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ AttachedTimerHold,far
|
||||
; ==================
|
||||
; This does not need to do anything.
|
||||
;
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ AttachedTimerResume,far
|
||||
; ====================
|
||||
; This does not need to do anything.
|
||||
;
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ AttachedTimerReset,far
|
||||
; ===================
|
||||
; This will never be called since we dont request it to be called.
|
||||
; The lower level driver and timer driver will handle the process
|
||||
; terminating abnormally.
|
||||
;
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ AttachedTimerUnits,far
|
||||
; ===================
|
||||
; Called by device query units operating system service
|
||||
;
|
||||
mov ax, -1 ; supports many open requests
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ AttachedTimerOpen,far
|
||||
; ==================
|
||||
; Called by the IoOpen system service
|
||||
;
|
||||
; In:
|
||||
; DX - device handle
|
||||
; SI - ptr to OpenEnt struct
|
||||
; Out:
|
||||
; Carry clear
|
||||
; BX - open channel handle
|
||||
; DX - device handle as passed
|
||||
; Carry set
|
||||
; AL - error number
|
||||
; DX - device handle as passed
|
||||
;
|
||||
cld
|
||||
mov cx, (size TimerEnt)
|
||||
HeapAllocateCell
|
||||
jc endOpen ; return that error
|
||||
mov bx, ax
|
||||
|
||||
; Initialise the allocated cell to zero.
|
||||
mov di, ax
|
||||
shr cx, 1 ; alloc cells should be even no of bytes.
|
||||
xor ax, ax
|
||||
rep stosw ; initialize all struct to zero
|
||||
|
||||
; Add the waithandler function
|
||||
mov al, (VectorHandler-Vector)/2
|
||||
IoAddHandler
|
||||
jc freeCellExit ; report the add handler error
|
||||
mov [bx].WaitHandler, ax ; handler handle
|
||||
|
||||
; Open a timer channel
|
||||
push bx ; save the alloc cell handle
|
||||
mov cx, sp ; save SP for now
|
||||
xor ax, ax
|
||||
push ax
|
||||
mov ax, ':' shl 8 + 'M'
|
||||
push ax
|
||||
mov ax, 'I' shl 8 + 'T'
|
||||
push ax
|
||||
mov bx, sp ; BX is pointer to name to 'TIM:'
|
||||
IoOpen ; CX and DX are irrelvant for a timer
|
||||
mov sp, cx
|
||||
pop bx
|
||||
jc freeHandlerExit ; report the timer open error.
|
||||
mov [bx].TimerChan, ax
|
||||
|
||||
; Set up the channel header
|
||||
mov [bx].ChanSignature, IoChanSignature
|
||||
mov [bx].ChanLibHandle, dx
|
||||
mov [bx].ChanNext, bx ; were a root driver for now
|
||||
|
||||
; Attach this driver to the currently open driver Hierarchy
|
||||
mov cx, bx ; channel were attaching
|
||||
mov al, IoFuncAttach
|
||||
mov bx, [si].OpenChan ; driver to attach to
|
||||
IoWithWait
|
||||
clc ; return BX (ie what attached to)
|
||||
|
||||
; Finished the open request
|
||||
endOpen:
|
||||
ret
|
||||
|
||||
; An error has occured, free the handler then cell in BX and return an error
|
||||
freeHandlerExit:
|
||||
push ax
|
||||
push bx
|
||||
mov bx, [bx].WaitHandler
|
||||
IoRemoveHandler
|
||||
pop bx
|
||||
pop ax
|
||||
|
||||
; An error has occured, free the cell in BX and return an error
|
||||
freeCellExit:
|
||||
push ax
|
||||
HeapFreeCell
|
||||
pop ax ; AL has the error code
|
||||
stc
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ StrategyVectorTable
|
||||
; ===================
|
||||
; The strategy vector jump table
|
||||
;
|
||||
dw StrategyDefault ; IoFuncPanic
|
||||
dw StrategyRead ; IoFuncRead
|
||||
dw StrategyDefault ; IoFuncWrite
|
||||
dw StrategyClose ; IoFuncClose
|
||||
dw StrategyCancel ; IoFuncCancel
|
||||
dw StrategyDefault ; IoFuncAttach
|
||||
dw StrategyDefault ; IoFuncDetach
|
||||
dw StrategySet ; IoFuncSet
|
||||
dw StrategySense ; IoFuncSense
|
||||
StrategyVectorEnd:
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ CancelTimer
|
||||
; ===========
|
||||
; Cancel the outstanding timer request
|
||||
; In:
|
||||
; BX = TimerEnt ptr
|
||||
; Out:
|
||||
; NONE
|
||||
;
|
||||
push bx
|
||||
mov bx, [bx].TimerChan
|
||||
mov al, IoFuncCancel ; cancel the queued timer
|
||||
IoWithWait
|
||||
pop bx
|
||||
lea di, [bx].TimerStat
|
||||
IoWaitForStatus ; use up completion signal
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ CancelRead
|
||||
; ==========
|
||||
; Cancel the outstanding read request on the lower driver
|
||||
; In:
|
||||
; BX = TimerEnt ptr
|
||||
; Out:
|
||||
; NONE
|
||||
;
|
||||
mov al, IoFuncCancel ; cancel the queued read
|
||||
IoWithWait
|
||||
lea di, [bx].ReadStat
|
||||
IoWaitForStatus ; use up completion signal
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ SignalReadAX
|
||||
; ============
|
||||
; Complete the orignal read request with the completion status in AX
|
||||
; In:
|
||||
; AX = completion status to report
|
||||
; BX = control block ptr as allocated by open
|
||||
; Out:
|
||||
; NONE
|
||||
;
|
||||
xor di, di ; complete the original read request
|
||||
xchg di, [bx].ReadRq.RqStatusPtr
|
||||
mov word ptr [di], ax
|
||||
IoSignal
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ CancelAnyRequests
|
||||
; =================
|
||||
; Cancel any outstanding attached driver and timer requests.
|
||||
; In:
|
||||
; BX = control block ptr as allocated by open
|
||||
; Out:
|
||||
; NONE
|
||||
;
|
||||
cmp [bx].ReadRq.RqStatusPtr, 0
|
||||
je noRequestsQueued
|
||||
call CancelRead
|
||||
call CancelTimer
|
||||
push bx
|
||||
mov bx, [bx].WaitHandler
|
||||
mov cl, HandlerDisable
|
||||
IoEnableHandler
|
||||
pop bx
|
||||
mov ax, CancelErr
|
||||
call SignalReadAX
|
||||
|
||||
noRequestsQueued:
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ AttachedTimerStrategy,far
|
||||
; =====================
|
||||
; Called by the applications I/O services.
|
||||
; In:
|
||||
; BX = control block ptr as allocated by open
|
||||
; SI = RqEnt pointer
|
||||
; Out:
|
||||
; Carry clear
|
||||
; The request was sucessfully queued, (may have completed)
|
||||
; Carry set
|
||||
; The request failed to start
|
||||
;
|
||||
cld
|
||||
mov [bx].InStrategy, 1 ; anti nesting
|
||||
mov di, [si].RqStatusPtr
|
||||
mov word ptr [di], PendingErr ; request now pending
|
||||
mov ax, di ; pre-load AX
|
||||
mov di, [si].RqFunction
|
||||
cmp di, (StrategyVectorEnd-StrategyVectorTable)/2
|
||||
ja StrategyDefault
|
||||
mov cx, [si].RqA1Ptr ; pre-load CX and DX
|
||||
mov dx, [si].RqA2Ptr
|
||||
shl di, 1 ; vector table entry
|
||||
jmp word ptr cs:StrategyVectorTable[di]
|
||||
|
||||
; This device driver does not handle this function, pass it up the driver
|
||||
; hierarchy to a driver that may support this function.
|
||||
StrategyDefault:
|
||||
mov [bx].InStrategy, 0
|
||||
IoSuper ; pass request to next dvr
|
||||
ret
|
||||
|
||||
StrategyRead:
|
||||
cmp [bx].ReadRq.RqStatusPtr, 0
|
||||
jne panicPending ; already a read queued
|
||||
mov [bx].ReadRq.RqStatusPtr, ax
|
||||
mov [bx].ReadRq.RqA1Ptr, cx
|
||||
mov [bx].ReadRq.RqA2Ptr, dx
|
||||
lea di, [bx].ReadStat ; Q an attached dvr read
|
||||
mov al, IoFuncRead
|
||||
IoAsynchronousNoError ; Queue a read on lower dvr
|
||||
lea di, [bx].TimerStat
|
||||
lea cx, [bx].Timeout
|
||||
push bx
|
||||
push [bx].WaitHandler
|
||||
mov bx, [bx].TimerChan
|
||||
mov al, IoFuncRead
|
||||
IoAsynchronousNoError ; Queue a read on the timer channel
|
||||
; now let the wait handler be callable
|
||||
pop bx
|
||||
mov cl, HandlerEnable
|
||||
IoEnableHandler
|
||||
pop bx
|
||||
and [bx].InStrategy, 0
|
||||
clc
|
||||
ret
|
||||
|
||||
; The process is making a 2nd call of a function that is already outstanding.
|
||||
panicPending:
|
||||
mov al, PanicIoPending
|
||||
ProcPanic ; stop calling process.
|
||||
|
||||
StrategyCancel:
|
||||
call CancelAnyRequests
|
||||
and [bx].InStrategy, 0
|
||||
jmp short completeRequestOk
|
||||
|
||||
; This driver defines the IoFuncSet function to set the read timout.
|
||||
StrategySet:
|
||||
mov di, cx ; RqA1Ptr is a pointer to a long
|
||||
mov ax, [di]
|
||||
mov word ptr [bx].Timeout, ax
|
||||
mov ax, [di+2]
|
||||
mov word ptr [bx+2].Timeout, ax
|
||||
and [bx].InStrategy, 0
|
||||
jmp short completeRequestOk
|
||||
|
||||
; This driver defines the IoFuncSense function to sense the read timout.
|
||||
StrategySense:
|
||||
mov di, cx ; RqA1Ptr is a pointer to a long
|
||||
mov ax, word ptr [bx].Timeout
|
||||
mov word ptr [di], ax
|
||||
mov ax, word ptr [bx+2].Timeout
|
||||
mov word ptr [di+2], ax
|
||||
completeRequestOk:
|
||||
mov di, [si].RqStatusPtr
|
||||
and word ptr [di], 0 ; complete request OK.
|
||||
IoSignal
|
||||
and [bx].InStrategy, 0
|
||||
clc
|
||||
ret
|
||||
|
||||
StrategyClose:
|
||||
call CancelAnyRequests
|
||||
push bx
|
||||
push [bx].WaitHandler
|
||||
mov bx, [bx].TimerChan
|
||||
IoClose ; close the timer
|
||||
pop bx
|
||||
IoRemoveHandler ; remove the waithandler
|
||||
pop bx
|
||||
mov al, IoFuncDetach ; detach from lower driver
|
||||
IoWithWait
|
||||
HeapFreeCell ; alloc cell freed !!!
|
||||
mov di, [si].RqStatusPtr
|
||||
and word ptr [di], 0 ; complete request OK.
|
||||
IoSignal
|
||||
clc
|
||||
ret
|
||||
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ AttachedTimerHandler,far
|
||||
; ====================
|
||||
; Called by the operating system when the applications I/O semaphore has
|
||||
; been signalled. See if its one of our requests that have been completed.
|
||||
; The operating system will automatically stop any nesting if it called this
|
||||
; handler, however we will get called if we are in the strategy vector and
|
||||
; use synchronous I/O requests. The driver has set itself up such that this
|
||||
; will only ever be called if there is an outstanding request by only
|
||||
; enabling the handler when a read request is received.
|
||||
;
|
||||
; In:
|
||||
; BX = as passed to IoAddHandler
|
||||
; Out:
|
||||
; Carry clear
|
||||
; The signal was not for us.
|
||||
; Carry set
|
||||
; AL = 0 - we used signal, allow handler to be disabled.
|
||||
; AL = 1 - we used signal, keep the handler enabled.
|
||||
;
|
||||
|
||||
cmp [bx].InStrategy, 1
|
||||
jne notInAttachedTimerStrategy
|
||||
signalNotForThisDriver:
|
||||
clc ; get out as fast as possible
|
||||
ret ; as event definatly not for us.
|
||||
|
||||
notInAttachedTimerStrategy:
|
||||
cmp [bx].ReadStat, PendingErr
|
||||
je readRequestNotComplete
|
||||
; The read request has completed.
|
||||
call CancelTimer
|
||||
mov ax, [bx].ReadStat ; read completion result
|
||||
jmp short signalAXdisableHandler
|
||||
|
||||
readRequestNotComplete:
|
||||
cmp [bx].TimerStat, PendingErr
|
||||
je signalNotForThisDriver
|
||||
; The timer request has completed.
|
||||
call CancelRead
|
||||
mov ax, InActivityErr ; read inactivity on timeout
|
||||
signalAXdisableHandler:
|
||||
call SignalReadAX
|
||||
xor al, al ; we used signal
|
||||
stc ; handler now disabled.
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
EndCodeSeg
|
||||
;
|
||||
stack segment stack para 'data'
|
||||
;
|
||||
stack ends
|
||||
;
|
||||
end AttachedTimerLDD
|
||||
Reference in New Issue
Block a user