;*************************** AMUS Program Label ******************************
; Filename: DISKIO.SBR                                      Date: 06/12/89
; Category: DISK         Hash Code: 054-144-267-402      Version: 1.0(103)
; Initials: AMI          Name: AMI BAR-YADIN
; Company: UNITED FASHIONS OF TEXAS                Telephone #: 5126312277
; Related Files:
; Min. Op. Sys.: NA                            Expertise Level: BEG
; Special:
; Description: Read and write any disk block from basic.  (Note that writing
;       has to enabled by the basic program AFTER the Init call)
;
;*****************************************************************************
;* Updated on 12-Jun-89 at 9:01 PM by ; edit time: 1:31:26 *;
; DISKIO.SBR
; do disk block I/O from basic
; (C)1989 By Ami Bar-Yadin.     AMUS ID: AMI/AM
;
; usage:
;       xcall diskio,func,ddb...
;
; where:
;       func,f          function number (see below)
;       ddb,x,104       ddb to use
;                       error codes are returned in the first byte of ddb.
;
; function 0-Init
;       xcall diskio,0,ddb,buff{,devnam}
;       sets ddb in input-only mode.  Writing must be enabled manually
;       by clearing the D.OPN byte.  (DDB[&H1E;1]=0.)
;       buff    must be large enough to hold standard block of device
;               this buffer will be used in input and output calls later.
;       devnam  (OPTIONAL) device name (ie "dsk0" or "dsk0:" etc)
;               defaults to logged in device.
;
; function 1-Input
;       xcall diskio,1,ddb{,blk{,tmp-buf}}
;       data read is placed in buff as set in Init call or in tmp-buf if
;       provided.
;       blk,f   (OPTIONAL) block number to read
;               if not present the block number in the ddb is used
;       tmp-buf (OPTIONAL) if present this one input will be done into
;               this buffer
;
; function 2-Output
;       xcall diskio,2,ddb{,blk,{tmp-buf}}
;       data is written from buff as set in Init call.
;       if D.OPN is set (non-zero) writing is trapped by a fatal error.
;       blk,f   (OPTIONAL) block number to read
;               if not present the block number in the ddb is used
;       tmp-buf (OPTIONAL) if present this one output will be done from
;               this buffer
;
; function 3-Error message
;       xcall diskio,3,ddb,errmsg
;       return a string corresponsing to the error number in the ddb.
;       errmsg,s  MUST be large enough to hold null-terminated string.
;
;
;
;-All commercial rights reserved, etc.
;-No warranties and/or guarranties of any kind, etc.
;-Not responsible for damages resulting from the use of this program, etc.
;-My employer (United Fashions) has nothing to do with this program and
; should not be blamed for it.
;
; I can be reached at:
;               United Fashions of Texas, Inc.
;               200 Ash Ave.
;               McAllen, TX  78501
;               (512) 631-2277
;               8am-6pm
;
VMAJOR=1
VMINOR=0
VEDIT=103.

       SYM
       MAYCREF
       OBJNAM  .SBR
       SEARCH  SYS
       SEARCH  SYSSYM
       RADIX   16.
       DEFAULT VEDIT,1
       DEFAULT $$MFLG,PV$RSM
       DEFAULT $$SFLG,PH$REE!PH$REU
       PHDR    -1,$$MFLG,$$SFLG


       DEFINE  BTYPE N,DEST
1$$     =       2+^D10*<N-1>
       CLR     DEST
       MOVW    1$$(A3),DEST
       ENDM

       DEFINE  BADRS N,DEST
1$$     =       4+^D10*<N-1>
       MOVL    1$$(A3),DEST
       ENDM

       DEFINE  BSIZE N,DEST
1$$     =       8+^D10*<N-1>
       MOVL    1$$(A3),DEST
       ENDM

;
;=======
;
DISKIO:
       CMPW    @A3,#2                  ; check for at least two parameters
       JLO     ERR1
       BADRS   1,A6
       FFTOL   @A6,D6
       CMP     D6,#MAXFUN
       JHI     ERR2

       BADRS   2,A0            ; get ddb address (common to all functions)

       ASL     D6,#1                   ; convert to word offset
       ADDW    JMPTBL[~D6],D6
       JMP     JMPTBL[~D6]

JMPTBL: OFFSET  FUNC0
       OFFSET  FUNC1
       OFFSET  FUNC2
       OFFSET  FUNC3
MAXFUN=<.-JMPTBL>/2


;-------
; function 0-Init
;       xcall diskio,0,ddb,buff{,devnam}
;       buff    must be large enough to hold standard block of device
;               this buffer will be used in input and output calls later.
;       devnam  (OPTIONAL) device name (ie "dsk0" or "dsk0:" etc)
FUNC0:
       CMPW    @A3,#3                  ; check for at least three parameters
       JLO     ERR1
       BSIZE   2,D0
       CMP     D0,#D.DDB
       JLO     ERR3

       MOV     A0,A6                   ; clear ddb
       MOV     D0,D6
       DEC     D6
5$:     CLRB    (A6)+
       DBF     D6,5$

       MOVB    #D$INI!D$ERC!D$BYP,D.FLG(A0) ; set ddb flags

       BADRS   3,A5
       BSIZE   3,D5
       MOV     A5,D.BUF(A0)            ; set buffer pointer

       CMPW    @A3,#4                  ; is there a device name?
       BLO     10$

       BADRS   4,A2                    ; index device name
       LEA     A1,D.DEV(A0)            ; pack into ddb
       PACK
       GTDEC                           ; get unit number
       MOVW    D1,D.DRV(A0)            ; put in ddb
10$:
       INIT    @A0                     ; set drive address

       MOVB    #D$OPNI,D.OPN(A0)       ; set write-protect

       LEA     A1,-DC.SIZ(SP)          ; temp area on user stack
       DEVCHR  @A0,@A1

       MOV     DC.BUF(A1),D6           ; get standard buffer size
       MOV     D6,D.SIZ(A0)            ; set buffer size
       CMP     D6,D5
       JLO     ERR4

       RTN


;-------
; function 1-Input
;       xcall diskio,1,ddb{,blk,{tmp-buf}}
;       data read is placed in buff as set in Init call.
;       blk,f   (OPTIONAL) block number to read
;               if not present the block number in the ddb is used
;       tmp-buf (OPTIONAL) if present this one output will be done from
;               this buffer
;
FUNC1:
       BTST    #D%INI,D.FLG(A0)        ; ddb init'd?
       JEQ     ERR5
       CMPW    @A3,#3                  ; block number present?
       BLO     10$
       BADRS   3,A6
       FFTOL   @A6,D6
       MOV     D6,D.REC(A0)            ; set block number
10$:    CMPW    @A3,#4                  ; tmp-buf present?
       BLO     50$                     ; no
       BADRS   4,A1                    ; index tmp-buf
       BSIZE   4,D1                    ; get size of tmp-buf
       CMP     D1,D.SIZ(A0)            ; is it big enough, baby?
       JLO     ERR4                    ; no.
       PUSH    D.BUF(A0)               ; save buffer address
       MOV     A1,D.BUF(A0)            ; set ddb pointer
       CALL    50$
       POP     D.BUF(A0)
       RTN
50$:    READ    @A0
       RTN


;-------
; function 2-Output
;       xcall diskio,2,ddb{,blk,{tmp-buf}}
;       data is written from buff as set in Init call.
;       blk,f   (OPTIONAL) block number to read
;               if not present the block number in the ddb is used
;       tmp-buf (OPTIONAL) if present this one output will be done from
;               this buffer
;
FUNC2:
       BTST    #D%INI,D.FLG(A0)        ; ddb init'd?
       JEQ     ERR5
       TSTB    D.OPN(A0)               ; write allowed?
       JNE     ERR6                    ; no.
       CMPW    @A3,#3                  ; block number present?
       BLO     10$
       BADRS   3,A6
       FFTOL   @A6,D6
       MOV     D6,D.REC(A0)            ; set block number
10$:
       CMPW    @A3,#4                  ; tmp-buf present?
       BLO     50$                     ; no
       BADRS   4,A1                    ; index tmp-buf
       BSIZE   4,D1                    ; get size of tmp-buf
       CMP     D1,D.SIZ(A0)            ; is it big enough, baby?
       JLO     ERR4                    ; no.
       PUSH    D.BUF(A0)               ; save buffer address
       MOV     A1,D.BUF(A0)            ; set ddb pointer
       CALL    50$
       POP     D.BUF(A0)
       RTN
50$:    WRITE   @A0
;       TYPE    <\* output>
;       MOV     D.REC(A0),D1
;       DCVT    0,OT$TRM!OT$LSP!OT$TSP
;       TYPECR  <*\>
       RTN


;-------
; function 3-Error message
;       xcall diskio,3,ddb,errmsg
;       return a string corresponsing to the error number in the ddb.
;       errmsg,s  MUST be large enough to hold null-terminated string.
;
FUNC3:
       CMPW    @A3,#3
       JLO     ERR1
       BADRS   3,A2
       ERRMSG  D.ERR(A0),OT$MEM!OT$LDQ
       CLRB    @A2
       RTN


;-------
; fatal error routines
;
ERR1:   TYPE    <?Bad args for >
       BR      ERRY
ERR2:   TYPE    <?Bad function for >
       BR      ERRX
ERR3:   TYPE    <?DDB too small for >
       BR      ERRX
ERR4:   TYPE    <?Buffer too small for >
ERRY:   BR      ERRX
ERR5:   TYPE    <?DDB not init'd before access by >
       BR      ERRX
ERR6:   TYPE    <?Output attempted on DDB by >
;       BR      ERRX
ERRX:   TYPECR  <XCALL DISKIO>
       EXIT
;
;
       END