532 lines
13 KiB
NASM
532 lines
13 KiB
NASM
title NAME.LDD device driver for S3/S3a/S3c/S3../HC
|
|
subttl Copyright PSION PLC November 1995
|
|
name NAME
|
|
|
|
; VERSION DATE DESCRIPTION
|
|
; ------- -------- ---------------
|
|
; 1.0 12/01/95 Template LDD
|
|
|
|
; Written by Jason Robinson January 1995
|
|
|
|
BUILDSB equ 1
|
|
|
|
include ..\inc\epoc.inc
|
|
include ..\inc\epocser.inc
|
|
include ..\inc\epoclib.inc
|
|
include ..\inc\epocsibo.inc
|
|
include ..\srcs\ossibo.inc
|
|
include ..\srcs\ospack.inc
|
|
|
|
OpenSpecificChannel =0
|
|
MachineSpecific =0
|
|
PeripheralTypeDriver =0
|
|
TickRequired =0
|
|
|
|
NumberOfChannels equ 1
|
|
WeSupportS3Only equ Lcd240X80
|
|
WeSupportS3aOnly equ Lcd480X160
|
|
WeSupportS3cOnly equ Lcd240X100
|
|
WeSupportHCOnly equ Lcd160X80
|
|
TheMachineWeSupport equ WeSupportS3aOnly
|
|
|
|
TmpltEnt struc
|
|
TmpltEntOpen db ? ; Channel open flag
|
|
TmpltChannelStarted db ? ; Channel should be running
|
|
TmpltChannelRunning db ? ; Can channel really run
|
|
TmpltSpare db ?
|
|
TmpltHwChannel dw ? ; The harware we want
|
|
TmpltStructPtr dw ? ; Ptr to CB in Apps DS
|
|
if PeripheralTypeDriver or TickRequired
|
|
TmpltTckHandle dw ? ; Tick Handle
|
|
endif
|
|
TmpltEnt ends
|
|
|
|
TmpltStruct struc
|
|
Tmpltblk ChanEnt <> ; I/O control block
|
|
TmpltEntPtr dw ? ; Ptr to our CS CB
|
|
TmpltStruct ends
|
|
|
|
dgroup group stack
|
|
assume ds:dgroup,es:dgroup,ss:dgroup
|
|
|
|
CodeSeg
|
|
|
|
ProcBegin@ TmpltLDD
|
|
; ===================
|
|
|
|
dw LDDSignature
|
|
db 'HSB',0,0,0,0,0
|
|
dw (TableEnd-TableStart)/2
|
|
TableStart:
|
|
dw TmpltInstall
|
|
dw TmpltRemove
|
|
dw TmpltHold
|
|
dw TmpltResume
|
|
dw TmpltReset
|
|
dw TmpltUnits
|
|
dw TmpltOpen
|
|
dw TmpltStrategy
|
|
if PeripheralTypeDriver or TickRequired
|
|
MonitorVector:
|
|
dw MonitorInt
|
|
endif
|
|
TableEnd:
|
|
|
|
CsHeldFlag db 0 ; Ldd under a hold?
|
|
MachineType db 0
|
|
|
|
Channel0 TmpltEnt <>
|
|
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltInstall,far
|
|
; ===========================
|
|
|
|
; Install the driver
|
|
; Exit with carry clear for okay
|
|
|
|
if MachineSpecific
|
|
GenLcdType ; Do we only run on
|
|
mov MachineType,al ; particular machines?
|
|
cmp al,TheMachineWeSupport
|
|
jne CannotInstallOnThisMachine
|
|
endif
|
|
mov CsHeldFlag,0 ; Initialise all
|
|
mov cx,NumberOfChannels ; the variables
|
|
mov di,offset Channel0
|
|
xor ax,ax
|
|
ResetAllChannelsLoop:
|
|
mov cs:[di].TmpltEntOpen,al
|
|
add di,size TmpltEnt
|
|
loop ResetAllChannelsLoop
|
|
FinishedOkay:
|
|
clc
|
|
ret
|
|
CannotInstallOnThisMachine:
|
|
mov ax,NotSupportedErr
|
|
stc
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltRemove,far
|
|
; ==========================
|
|
|
|
; Remove the driver
|
|
; Exit with carry clear for okay
|
|
; Exit with carry set if channel still open
|
|
|
|
mov cx,NumberOfChannels
|
|
mov di,offset Channel0
|
|
xor ax,ax
|
|
CheckAllChannelsClosedLoop:
|
|
cmp cs:[di].TmpltEntOpen,al
|
|
jne WeHaveAnOpenChannelSoFail
|
|
add di,size TmpltEnt
|
|
loop CheckAllChannelsClosedLoop
|
|
jmp FinishedOkay
|
|
WeHaveAnOpenChannelSoFail:
|
|
mov ax,InUseErr
|
|
stc
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltUnits,far
|
|
; =========================
|
|
|
|
; Return the Number of channels that can be opened in AX
|
|
|
|
mov ax,NumberOfChannels ; We have ? channels
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltReset,far
|
|
; =========================
|
|
|
|
; Reset the open channel
|
|
|
|
mov di,cx
|
|
cmp cs:[di].TmpltEntOpen,0 ; Somethings gone
|
|
je NotOpenToReset ; wrong with the
|
|
mov ah,DevHoldPowerDown ; application that
|
|
call StopTheChannel ; opened us.
|
|
call FreeHardware ; Stop interupts and
|
|
mov cs:[di].TmpltEntOpen,0 ; free the channel
|
|
NotOpenToReset:
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltHold,far
|
|
; ========================
|
|
|
|
; Hold the channels
|
|
; Hold reason in AH
|
|
|
|
mov cx,1
|
|
xchg cl,CsHeldFlag ; Stop any interrupts
|
|
cmp cl,0 ; Mark channel as
|
|
jne AlreadyHeld ; under a normal hold
|
|
DoHold:
|
|
mov cx,NumberOfChannels
|
|
mov di,offset Channel0
|
|
HoldAllTheChannelsLoop:
|
|
cmp cs:[di].TmpltEntOpen,0
|
|
je DontHoldBecauseNotOpen
|
|
cmp cs:[di].TmpltChannelStarted,0
|
|
je DontHoldBecauseNotOpen
|
|
push ax
|
|
push cx
|
|
call StopTheChannel
|
|
pop cx
|
|
pop ax
|
|
DontHoldBecauseNotOpen:
|
|
add di,size TmpltEnt
|
|
loop HoldAllTheChannelsLoop
|
|
AlreadyHeld:
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltResume,far
|
|
; ==========================
|
|
|
|
; Resume the channel
|
|
|
|
xor cx,cx ; Be warned during an
|
|
xchg cl,CsHeldFlag ; on/off the power to
|
|
cmp cl,0 ; ASIC4 is not restored
|
|
je AlreadyResumed ; until after this
|
|
if PeripheralTypeDriver
|
|
GenDataSegment ; A resume is pointless
|
|
HwGetSsdData ; if there is still no
|
|
mov bx,ax ; power to the port
|
|
cmp es:[bx].SsdDoorStatus,DoorOpen ; Leave the resume
|
|
je DoorsAreOpen ; to the tick
|
|
endif
|
|
DoResume:
|
|
mov cx,NumberOfChannels
|
|
mov di,offset Channel0 ; Right hardware?
|
|
ResumeAllTheChannelsLoop: ; Else restart
|
|
cmp cs:[di].TmpltEntOpen,0 ; interrupts
|
|
je DontResumeBecauseNotOpen
|
|
cmp cs:[di].TmpltChannelStarted,0
|
|
je DontResumeBecauseNotOpen
|
|
push cx
|
|
call StartTheChannel
|
|
pop cx
|
|
DontResumeBecauseNotOpen:
|
|
add di,size TmpltEnt
|
|
loop ResumeAllTheChannelsLoop
|
|
AlreadyResumed:
|
|
ret
|
|
if PeripheralTypeDriver
|
|
DoorsAreOpen:
|
|
mov CsHeldFlag,2
|
|
ret
|
|
endif
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltOpen,far
|
|
; ========================
|
|
|
|
; Open the channel
|
|
; DS,ES,SS Applications data space
|
|
; Handle in DX
|
|
|
|
cld
|
|
pushf
|
|
cli
|
|
call FindFreeChannel
|
|
jnc GotFreeChannel
|
|
popf
|
|
LockedError:
|
|
mov ax,LockedErr
|
|
stc
|
|
ret
|
|
AllErrorsExitHere:
|
|
push ax
|
|
HeapFreeCell
|
|
pop ax
|
|
FreeTckAndChannel:
|
|
push ax
|
|
call FreeHardware
|
|
pop ax
|
|
FreeTckAndExit:
|
|
if PeripheralTypeDriver or TickRequired
|
|
push ax
|
|
mov bx,cs:[di].TmpltTckHandle
|
|
IoClose
|
|
pop ax
|
|
endif
|
|
CloseThenFree:
|
|
mov cs:[di].TmpltEntOpen,0
|
|
stc
|
|
ret
|
|
GotFreeChannel:
|
|
mov cs:[di].TmpltEntOpen,1
|
|
mov cs:[di].TmpltChannelStarted,0
|
|
mov cs:[di].TmpltChannelRunning,0
|
|
popf
|
|
if PeripheralTypeDriver or TickRequired
|
|
xor ax,ax
|
|
push ax
|
|
mov ax,((':' shl 8)+'K')
|
|
push ax
|
|
mov ax,(('C' shl 8)+'T')
|
|
push ax
|
|
mov bx,sp
|
|
IoOpen
|
|
jnc GotATickChannel
|
|
add sp,6
|
|
mov ax,LockedErr
|
|
jmp CloseThenFree
|
|
GotATickChannel:
|
|
add sp,6
|
|
mov cs:[di].TmpltTckHandle,ax
|
|
push dx
|
|
mov bx,ax
|
|
mov ax,IoFuncStart
|
|
mov cx,1
|
|
push cx ; Frequency 1 tick
|
|
push di ; Data is our CS CB
|
|
push dx ; Our device handle
|
|
mov cx,(MonitorVector-TableStart)/2 ; Vector to call
|
|
push cx
|
|
mov cx,sp
|
|
IoWithWait
|
|
add sp,8
|
|
pop dx
|
|
endif
|
|
call GetHardware
|
|
jc FreeTckAndExit
|
|
|
|
mov cx,(size TmpltStruct) ; Get ourselfs a CB
|
|
HeapAllocateCell ; In the applications
|
|
jc FreeTckAndChannel ; Data space
|
|
|
|
mov bx,ax
|
|
mov [bx].Tmpltblk.ChanNext,bx
|
|
mov [bx].Tmpltblk.ChanSignature,IoChanSignature
|
|
mov [bx].Tmpltblk.ChanLibHandle,dx
|
|
mov [bx].TmpltEntPtr,di
|
|
push bx
|
|
mov bx,dx
|
|
mov cx,di
|
|
IoRequestReset
|
|
pop bx
|
|
xor ax,ax
|
|
ret
|
|
ProcEnd noret
|
|
|
|
StrategyVectorTable label word
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset TmpltClose
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
dw offset StrategyDefault
|
|
|
|
ProcBegin@ TmpltStrategy,far
|
|
; ============================
|
|
|
|
; BX is our control block
|
|
; SI points to the parameters
|
|
; DS,ES Applications data space
|
|
|
|
mov ax,[si].RqFunction
|
|
mov dx,[si].RqA1Ptr
|
|
cmp ax,IoFuncSuperFrame
|
|
ja StrategyDefault
|
|
shl ax,1
|
|
mov di,ax
|
|
push StrategyVectorTable[di]
|
|
mov di,[bx].TmpltEntPtr
|
|
retn
|
|
StrategyDefault:
|
|
IoRoot
|
|
ret
|
|
ExitStrategyOkay:
|
|
xor ax,ax
|
|
ExitStrategy:
|
|
mov di,[si].RqStatusPtr
|
|
mov word ptr [di],ax
|
|
cmp ax,PendingErr
|
|
je JustExit
|
|
IoSignal
|
|
JustExit:
|
|
xor ax,ax
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ TmpltClose,far
|
|
; =========================
|
|
|
|
; Close a channel
|
|
; DI CS control block
|
|
; BX DS control block
|
|
; SI points to aurguments on stack
|
|
; DX Argument one pointer
|
|
|
|
mov ah,DevHoldPowerDown
|
|
call StopTheChannel
|
|
call FreeHardware
|
|
push bx
|
|
mov bx,[bx].Tmpltblk.ChanLibHandle
|
|
mov cx,di
|
|
IoRequestResetCancel
|
|
pop bx
|
|
HeapFreeCell
|
|
if PeripheralTypeDriver or TickRequired
|
|
mov bx,cs:[di].TmpltTckHandle
|
|
IoClose
|
|
endif
|
|
mov cs:[di].TmpltEntOpen,0
|
|
jmp short ExitStrategyOkay
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ StartTheChannel
|
|
; ==========================
|
|
|
|
; Start the Channel Running
|
|
|
|
cmp byte ptr cs:[di].TmpltChannelRunning,0
|
|
jne ChannelAlreadyRunning
|
|
|
|
mov cs:[di].TmpltChannelRunning,1
|
|
ChannelAlreadyRunning:
|
|
clc
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ StopTheChannel
|
|
; =========================
|
|
|
|
; Stop the Channel Running
|
|
|
|
cmp byte ptr cs:[di].TmpltChannelRunning,0
|
|
je ChannelAlreadyStopped
|
|
|
|
mov cs:[di].TmpltChannelRunning,0
|
|
ChannelAlreadyStopped:
|
|
clc
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ GetHardware
|
|
; ======================
|
|
|
|
clc
|
|
ret
|
|
ProcEnd noret
|
|
|
|
ProcBegin@ FreeHardware
|
|
; =======================
|
|
|
|
clc
|
|
ret
|
|
ProcEnd noret
|
|
|
|
If OpenSpecificChannel
|
|
ProcBegin@ FindFreeChannel
|
|
; ==========================
|
|
|
|
; Called from Open
|
|
; Must preserve DX,SI
|
|
; Channel out in DI or carry set if failure
|
|
|
|
mov si,[si].OpenNamePtr
|
|
mov al,[si+1]
|
|
CharToFoldedChar
|
|
cmp al,'A'
|
|
jb CantGetThatChannel
|
|
sub al,'A'
|
|
cmp al,NumberOfChannels
|
|
jae CantGetThatChannel
|
|
xor ah,ah
|
|
push dx
|
|
mov dx,size TmpltEnt
|
|
mul dx
|
|
pop dx
|
|
mov di,ax
|
|
add di,offset Channel0
|
|
cmp cs:[di].TmpltEntOpen,0
|
|
je FoundAFreeChannel
|
|
CantGetThatChannel:
|
|
stc
|
|
ret
|
|
FoundAFreeChannel:
|
|
clc
|
|
ret
|
|
ProcEnd noret
|
|
else
|
|
ProcBegin@ FindFreeChannel
|
|
; ==========================
|
|
|
|
mov cx,NumberOfChannels
|
|
mov di,offset Channel0
|
|
HuntAllChannelsLoop:
|
|
cmp cs:[di].TmpltEntOpen,0
|
|
je FoundAFreeChannel
|
|
add di,size TmpltEnt
|
|
loop HuntAllChannelsLoop
|
|
stc
|
|
ret
|
|
FoundAFreeChannel:
|
|
clc
|
|
ret
|
|
ProcEnd noret
|
|
endif
|
|
|
|
if PeripheralTypeDriver or TickRequired
|
|
ProcBegin@ MonitorInt,far
|
|
; =========================
|
|
|
|
if PeripheralTypeDriver
|
|
; Called on every tick
|
|
; Issues pack door hold and resumes
|
|
; In: Door state in SI
|
|
|
|
cmp si,DoorOpen
|
|
je TheDoorIsOpenSoCantDoAnything
|
|
cmp CsHeldFlag,2
|
|
je NeedToDoTheResume
|
|
ret
|
|
NeedToDoTheResume:
|
|
mov CsHeldFlag,0
|
|
jmp DoResume
|
|
TheDoorIsOpenSoCantDoAnything:
|
|
cmp CsHeldFlag,0
|
|
jne DontNeedToHold
|
|
mov CsHeldFlag,2
|
|
mov ah,DevHoldPowerFail
|
|
jmp DoHold
|
|
DontNeedToHold:
|
|
endif
|
|
ret
|
|
ProcEnd noret
|
|
endif
|
|
|
|
EndCodeSeg
|
|
stack segment stack para 'data'
|
|
stack ends
|
|
end TmpltLDD
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|