build: add the SIBO SDK
This commit is contained in:
@@ -0,0 +1,395 @@
|
||||
title SNDDVR -- Epoc/Os Sound Device Driver Example
|
||||
subttl Copyright (c) Psion PLC 1992
|
||||
name SNDDVR
|
||||
;
|
||||
; VER DATE BY DESCRIPTION
|
||||
; ----- -------- ---- -----------
|
||||
; 1.00A 21/04/92 JH Alpha release
|
||||
;
|
||||
TURBOC equ 1
|
||||
;
|
||||
include epocdef.inc
|
||||
include epocmac.inc
|
||||
include epoclib.inc
|
||||
include epocser.inc
|
||||
include ossibo.inc
|
||||
|
||||
HandlerDisable equ 000h ; the hnadler should not be called
|
||||
HandlerEnable equ 001h ; the handler should be called
|
||||
|
||||
CodeSeg
|
||||
|
||||
ProcBegin@ SnddvrLDD
|
||||
; ==========
|
||||
; The externally loadable device table
|
||||
dw LDDSignature
|
||||
db 'MUS',0,0,0,0,0
|
||||
dw (VectorEnd-Vector)/2
|
||||
Vector:
|
||||
dw SnddvrInstall
|
||||
dw SnddvrRemove
|
||||
dw SnddvrHold
|
||||
dw SnddvrResume
|
||||
dw SnddvrReset
|
||||
dw SnddvrUnits
|
||||
dw SnddvrOpen
|
||||
dw SnddvrStrategy
|
||||
VectorHandler:
|
||||
dw SnddvrHandler
|
||||
VectorEnd:
|
||||
ProcEnd noret
|
||||
|
||||
SoundChanOpen db ?
|
||||
|
||||
ProcBegin@ CancelWrite
|
||||
; ===========
|
||||
; Cancel any outstanding I/O write request.
|
||||
; Set the completion status word to E_FILE_CANCEL and signal the I/O
|
||||
; semaphore.
|
||||
; In:
|
||||
; BX - sound control block ptr
|
||||
; Out:
|
||||
; NONE
|
||||
;
|
||||
mov dl, CancelErr
|
||||
IoSerSignalUserWrite ; complete any write with E_FILE_CANCEL
|
||||
IoSerTimerCancel ; harmless if nothing queued
|
||||
mov al, HandlerDisable
|
||||
IoSerSetHandler ; make SnddvrHandler non callable
|
||||
; FALL THROUGH to StopSound
|
||||
ProcEnd noret
|
||||
;
|
||||
|
||||
ProcBegin@ StopSound
|
||||
; =========
|
||||
; Stop the sound by turning off the sound chip and shuting down the
|
||||
; amplifier.
|
||||
; In:
|
||||
; BX - sound control block ptr
|
||||
; Out:
|
||||
; NONE
|
||||
;
|
||||
mov dx, PSoundControl
|
||||
mov al, 1
|
||||
out dx, al ; stop sound chip
|
||||
HwComboOff ; stop amplifier
|
||||
ret
|
||||
ProcEnd noret
|
||||
;
|
||||
|
||||
ProcBegin@ PlaySounds
|
||||
; ==========
|
||||
; Play any more sounds available.
|
||||
; Set the note volume from bits 6 and 7 of the first byte.
|
||||
; Write the note to the chip from bits 0-5 of the first byte.
|
||||
; Queue the timer to expire on timeout specified in 2nd byte.
|
||||
; In:
|
||||
; BX - channel control blk
|
||||
; Out:
|
||||
; AL as required by SnddvrHandler routine
|
||||
;
|
||||
cmp [bx].IoRequestRqWrite.RqA2Ptr, 0
|
||||
je finishedAllNotes
|
||||
cld
|
||||
dec [bx].IoRequestRqWrite.RqA2Ptr ; one less note to play
|
||||
mov si, [bx].IoRequestRqWrite.RqA1Ptr
|
||||
lodsw ; note+volume to AL, duration to AH
|
||||
mov [bx].IoRequestRqWrite.RqA1Ptr, si
|
||||
xor cx, cx
|
||||
mov cl, ah ; the duration (in 1/10ths)
|
||||
push ax
|
||||
shr ax, 1 ; factor out the volume bits
|
||||
and al, 60h ; into bits 5+6 for the hardware
|
||||
mov ah, al
|
||||
mov al, A2IWrite
|
||||
out A2Index, al
|
||||
mov al, ah
|
||||
out A2Control, al ; set the volume for that note
|
||||
pop ax
|
||||
mov dx, PSoundControl
|
||||
and al, 3fh ; bottom 6 bits are note info
|
||||
out dx, al ; and play the note
|
||||
xor dx, dx
|
||||
IoSerQueueTimer ; DX:CX is timeout in 1/10ths
|
||||
mov al, 1 ; enable handler
|
||||
ret
|
||||
finishedAllNotes:
|
||||
call StopSound ; stop sound activity
|
||||
IoSerSignalUserWriteOk ; write request completed ok
|
||||
xor ax, ax ; disable handler
|
||||
ret
|
||||
ProcEnd noret
|
||||
;
|
||||
|
||||
ProcBegin@ SnddvrInstall,far
|
||||
; =============
|
||||
; Install vector called when application calls p_loadldd()
|
||||
; In:
|
||||
; NONE
|
||||
; Out:
|
||||
; Carry clear if installed ok
|
||||
; Carry set if failed to install
|
||||
;
|
||||
and SoundChanOpen, 0 ; no channel open yet
|
||||
clc ; installed OK
|
||||
ret
|
||||
ProcEnd noret
|
||||
;
|
||||
|
||||
ProcBegin@ SnddvrRemove,far
|
||||
; ============
|
||||
; Remove vector called when application calls p_devdel()
|
||||
; In:
|
||||
; NONE
|
||||
; Out:
|
||||
; Carry clear if removed ok
|
||||
; Carry set if failed to remove
|
||||
;
|
||||
cmp SoundChanOpen, 0
|
||||
je soundRemoved ; dont do anything if not open
|
||||
mov al, InUseErr
|
||||
stc ; channel open, fail to remove
|
||||
ret
|
||||
ProcEnd noret
|
||||
;
|
||||
|
||||
ProcBegin@ SnddvrReset,far
|
||||
; ===========
|
||||
; Reset vector called if the client terminated.
|
||||
; We can only get a reset if weve got channel open and client died
|
||||
; since we cancel the reset request when the channel is closed.
|
||||
; NOTE: The clients data space no longer exists thus all data required to
|
||||
; close down the channel must be avaliable in the drivers space.
|
||||
; In:
|
||||
; NONE
|
||||
; Out:
|
||||
; NONE
|
||||
;
|
||||
call StopSound
|
||||
HwFreeCombo ; allow other sound components to work.
|
||||
and SoundChanOpen, 0 ; no channel open now
|
||||
soundRemoved:
|
||||
clc ; removed OK.
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ SnddvrHold,far
|
||||
; ==========
|
||||
; Hold called when another driver loaded or switched off/power fail.
|
||||
; In:
|
||||
; AH - reason.
|
||||
; Out:
|
||||
; NONE
|
||||
|
||||
cmp SoundChanOpen, 0
|
||||
je soundHeld ; dont do anything if not open
|
||||
call StopSound ; stop any current sounds.
|
||||
soundHeld:
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ SnddvrResume,far
|
||||
; ============
|
||||
; Resume called after a Hold to allow the driver to continue.
|
||||
; If we were running the outstanding timer request will complete at some
|
||||
; in the future at which point we will play the next note.
|
||||
; Note - we dont immediatly start playing the note that was being played
|
||||
; when the hold was called - this may be a bug for some applications.
|
||||
; In:
|
||||
; NONE
|
||||
; Out:
|
||||
; NONE
|
||||
|
||||
cmp SoundChanOpen, 0
|
||||
je soundResumed ; dont do anything if not open
|
||||
HwComboOn ; waithandler will run eventually
|
||||
soundResumed:
|
||||
ret ; when the timer expires if we were active.
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ SnddvrUnits,far
|
||||
; ===========
|
||||
; We can only handle 1 sound channel at a time.
|
||||
;
|
||||
mov ax, 1 ; support 1 unit at a time
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ SnddvrOpen,far
|
||||
; ==========
|
||||
; Open the sound device driver.
|
||||
; This runs is the context of the process that has called p_open("MUS:").
|
||||
;
|
||||
; In:
|
||||
; DS=ES=SS - Process data space.
|
||||
; DX - OS device handle
|
||||
; SI - ptr to OpenEnt struct
|
||||
; Out:
|
||||
; DX - OS device handle
|
||||
; Carry Clear
|
||||
; BX - channel, DX is as passed (device handle)
|
||||
; Carry Set
|
||||
; AL - error number
|
||||
;
|
||||
; All device drivers MUST have a ChanEnt as first item at returned BX
|
||||
;
|
||||
HwGetCombo ; see if already in use, if not grab it
|
||||
jc sndAlreadyInUse
|
||||
|
||||
; allocate in clients heap the I/O control block, add vector 9 as a
|
||||
; waithandler and open a timer channel. Tidies up all resources if there
|
||||
; are any errors.
|
||||
mov cx, (size IoRequestEnt)
|
||||
IoSerOpenTimerHandler
|
||||
jc endOpenNoMemory ; sets up ChanEnt, returns BX
|
||||
|
||||
; request reset vector be called if client terminates before closing channel
|
||||
xchg bx, dx
|
||||
xor cx, cx
|
||||
IoRequestReset ; BX=device handle, CX= channel indicator
|
||||
xchg bx, dx
|
||||
mov SoundChanOpen, 1
|
||||
clc ; Opened Ok, BX=channel, DX=device
|
||||
ret
|
||||
;
|
||||
endOpenNoMemory:
|
||||
push ax
|
||||
HwFreeCombo ; free up as failed
|
||||
pop ax
|
||||
stc
|
||||
sndAlreadyInUse:
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
ProcBegin@ SnddvrHandler,far
|
||||
; ==============
|
||||
; Called when an I/O signal is generated, it may be our timer to indicate
|
||||
; that we should play the next note if any.
|
||||
; In:
|
||||
; DS,ES,SS == Process data space
|
||||
; BX = the open sound channel
|
||||
; Out:
|
||||
; Carry clear
|
||||
; Did not consume signal
|
||||
; Carry set
|
||||
; al = 0 - Leave handler disabled
|
||||
; al = non 0 - Enable handler
|
||||
;
|
||||
|
||||
; check that were not currently in any StategyVector code, (anti nesting)
|
||||
test [bx].IoRequestFlags, RQ_DISABLE_HANDLER
|
||||
jnz signalNotForUs
|
||||
|
||||
; see if we currently have a timer request outstanding
|
||||
test [bx].IoRequestFlags, RQ_TIMER
|
||||
jz signalNotForUs ; timer not queued
|
||||
|
||||
; see if the outstanding timer has completed
|
||||
cmp [bx].IoRequestTimerStat, PendingErr
|
||||
je signalNotForUs ; timer still pending
|
||||
|
||||
; timer completed, play next sound if any and re-queue timer
|
||||
and [bx].IoRequestFlags, NOT RQ_TIMER
|
||||
call PlaySounds ; returns AL as required
|
||||
stc
|
||||
ret
|
||||
signalNotForUs:
|
||||
clc ; we didnt use the signal
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
|
||||
ProcBegin@ SnddvrStrategy,far
|
||||
; ==============
|
||||
; Strategy vector called by an I/O request on the opened sound device driver
|
||||
; channel.
|
||||
; The wait handler may be called (when enabled ) unless we block it when we
|
||||
; call a sync I/O request. Allowing the waithandler to run whilst in the
|
||||
; strategy vector is generally not a good thing to do.
|
||||
; In this particular example there are synchronous calls to the I/O system
|
||||
; to cancel the outstanding timer (if queued) and use the signal generated
|
||||
; by the cancel.
|
||||
;
|
||||
; In:
|
||||
; DS,ES,SS == Process data space
|
||||
; BX == channel control block from open request
|
||||
; DX == device handle
|
||||
; SI == RqEnt pointer
|
||||
; Out:
|
||||
; Carry clear
|
||||
; - request queued sucessfully (may have completed)
|
||||
; Carry set
|
||||
; - error queuing the I/O request
|
||||
;
|
||||
cld
|
||||
|
||||
; Stop the WaitHandler from being called temporarily
|
||||
or [bx].IoRequestFlags, RQ_DISABLE_HANDLER
|
||||
|
||||
mov al, byte ptr [si].RqFunction
|
||||
cmp al, IoFuncWrite
|
||||
jne tryCancel
|
||||
|
||||
; P_FWRITE I/O function request
|
||||
mov di, [si].RqA2Ptr
|
||||
mov cx, [di] ; length to write
|
||||
mov di, [si].RqA1Ptr ; ptr to data to write
|
||||
mov si, [si].RqStatusPtr
|
||||
IoSerCheckWriteSI ; set *SI to Pending, PendingPanic's
|
||||
mov [bx].IoRequestRqWrite.RqA2Ptr, cx
|
||||
mov [bx].IoRequestRqWrite.RqA1Ptr, di
|
||||
mov al, HandlerEnable
|
||||
IoSerSetHandler ; make SnddvrHandler callable
|
||||
HwComboOn ; start the amplifier
|
||||
call PlaySounds ; start the sound
|
||||
and [bx].IoRequestFlags, NOT RQ_DISABLE_HANDLER
|
||||
ret
|
||||
tryCancel:
|
||||
cmp al, IoFuncCancel
|
||||
jne tryClose
|
||||
|
||||
; P_FCANCEL I/O function request
|
||||
call CancelWrite ; cancel any outstanding requests
|
||||
and [bx].IoRequestFlags, NOT RQ_DISABLE_HANDLER
|
||||
jmp short signalOk ; cancel completed ok.
|
||||
tryClose:
|
||||
cmp al, IoFuncClose
|
||||
jne notForUs
|
||||
|
||||
; P_FCLOSE I/O function request
|
||||
push bx
|
||||
push dx
|
||||
call CancelWrite ; cancel any outstanding requests
|
||||
|
||||
; cancel the request to call the Reset vector
|
||||
pop bx ; our I/O device handle
|
||||
xor cx, cx ; MUST be same as passed to IoRequestReset
|
||||
IoRequestResetCancel ; dont call reset vector now
|
||||
|
||||
; close timer, remove handler, free alloc
|
||||
pop bx
|
||||
IoSerCloseTimerHandler
|
||||
HwFreeCombo ; not in use any more
|
||||
and SoundChanOpen, 0 ; no channel open now
|
||||
signalOk:
|
||||
xor ax, ax
|
||||
mov di, [si].RqStatusPtr
|
||||
stosw ; set completion status word to zero
|
||||
IoSignal ; complete the I/O request
|
||||
xor ax, ax ; also clears carry
|
||||
ret
|
||||
notForUs:
|
||||
and [bx].IoRequestFlags, NOT RQ_DISABLE_HANDLER
|
||||
IoRoot ; pass on request as not for us
|
||||
ret
|
||||
ProcEnd noret
|
||||
|
||||
EndCodeSeg
|
||||
;
|
||||
stack segment stack para 'data'
|
||||
;
|
||||
stack ends
|
||||
;
|
||||
end SnddvrLDD
|
||||
|
||||
Reference in New Issue
Block a user