**
*
* OPEN APPEND and OPEN UPDATE
*
* This procedure checks to see if a file exists.  If it does
* not, it just transfers control to OPENOU to create the file.
* If the file exists, it checks to make sure the file is not
* protected, and its attributes match.
*
* If the file is being opened in append mode, it reads the sector
* that contains the end of file marker and points to the end
* of file.
*
* If the file is being opened in update mode, then file pointer
* is set to the beginning of the file and no data is read in.
*
**

OPENUP
OPENAP
       BL   @GETFDR
       CI   R5,0
       JNE  OAP1
       B    @OOU20            File doesn't exist - create it

OAP1   LDCR @ZERO,4           Select RAM bank 0
       MOVB @12(R5),R1        Get file flags
       CZC  @PROBIT,R1        Check protection bit
       JEQ  OAP2
       BL   @DSRERR           File protected - error
       DATA >0100

OAP2
       ANDI R1,>0100          Check for Data/Program
       JEQ  OAP3
OAPBAD BL   @DSRERR
       DATA >0200             Bad open attribute

OAP3   MOVB @12(R5),R1        Check Fixed/variable
       ANDI R1,>8000
       MOVB @PABBUF+1,R2
       ANDI R2,>1000
       SLA  R2,3
       C    R1,R2
       JNE  OAPBAD

       MOVB @12(R5),R1        Check Display/Internal
       ANDI R1,>0200
       MOVB @PABBUF+1,R2
       ANDI R2,>0800
       SRL  R2,2
       C    R1,R2
       JNE  OAPBAD

* Now compare record length.  If a value of 0 is specified, we
* will write the actual record length in the caller's PAB
*
       MOVB @PABBUF+4,R1
       JEQ  OAP4
       CB   R1,@17(R5)
       JNE  OAPBAD
       JMP  OAP5
OAP4
       MOV  @PABADR,R0        Write out actual record length
       AI   R0,4
       ORI  R0,>4000          into caller's PAB
       SWPB R0
       MOVB R0,@VDPWA
       SWPB R0
       MOVB R0,@VDPWA
       NOP
       MOVB @17(R5),@VDPWD

* Set up the open file cache entry
OAP5
       BL   @OSCASH

* Lets copy the FDR to it's buffer in bank 5
*
       LI   R0,256
       MOV  @4(R4),R3        Get FDR address
       MOVB @2(R4),R2        Get FDR bank
OAP6   LDCR @ZERO,4
       MOV  *R5+,R1
       LDCR R2,4
       MOV  R1,*R3+
       DECT R0
       JNE  OAP6
       AI   R3,-256          Restore pointer to FDR

* If we're opening the file for UPDATE mode, we can end
* here.  Otherwise we have to read in the last sector and
* adjust the file pointers accordingly.
*
* Now we have to compute what AU contains the end of file,
* read it into the buffer and set some pointers.
*
       LDCR @ZERO,4
       MOVB @PABBUF+1,R1     Get file flags
       ANDI R1,>0600         Mask out Mode of Operation
       JNE  OAP8A

       B    @DSRRT           UPDATE access - we're done!

OAP8A  LDCR R2,4
       MOV  @18(R3),R11      Get last record read or last sector written
       JNE  OAP8B            If file is empty, we're done!
       LDCR @ZERO,4
       B    @DSRRT
OAP8B
       SWPB R11
       DEC  R11
       CLR  R10

* If it is a fixed length record file, we have to divide by the
* number of records per sector to get sectors
*
       MOVB @12(R3),R1       Get file flags
       ANDI R1,>8000
       JNE  OAP9

       MOVB @13(R3),R1       Get # of records/sector
       SRL  R1,8
       DIV  R1,R10
       MOV  R10,R11
       CLR  R10
OAP9
       LDCR @B04,4
       MOVB R6,R1
       SRL  R1,8
       SLA  R1,1
       DIV  @SAUTBL(R1),R10  Divide by sectors per AU

* Now R10 contains the AU that has the end of file.  Traverse
* through the file's data chain to find the physical AU
*

       AI   R3,40
       LDCR R2,4

OAP10  MOV  *R3+,R7
OAP11  CI   R10,0
       JEQ  OAP13
OAP11A C    R7,*R3
       JNE  OAP12
       INCT R3
       DEC  R10
       JMP  OAP10

OAP12  INC  R7
       DEC  R10
       JNE  OAP11A

OAP13

* Save the AU and sector within AU in the cache entry
*
       LDCR @B02,4
       MOV  R7,@50(R4)       Save current AU
       MOV  R11,@52(R4)      Save sector within AU

* Now that we have the AU, add in the sector within AU (R11)
* and read it from disk.
*

       LDCR @B04,4
       MOV  R6,R1
       SRL  R1,8
       SLA  R1,1
       MPY  @SAUTBL(R1),R7
       A    R11,R8
       JNC  OAP14
       INC  R7
OAP14
       LI   R1,SECBUF
       SRL  R8,1
       JNC  OAP15
       AI   R1,>100
OAP15  SRL  R7,1
       JNC  OAP16
       AI   R8,>8000
OAP16
       LDCR @ZERO,4
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  OAP17

       BL   @DSRERR
       DATA >0600            Device Error

OAP17

* Copy the data from the SCSI buffer to the file buffer
*
       LDCR @B02,4
       MOV  @6(R4),R5        Get buffer pointer
       MOVB @3(R4),R2        Get buffer bank

* Set the pointer in buffer to the base plus the end of
* file offset.

       MOV  R5,@54(R4)       Reset pointer within buffer
       MOV  @4(R4),R3        Get FDR address
       LDCR @2(R4),4
       MOV  @18(R3),R8       Get # of level 3
       SWPB R8
       MOVB @16(R3),R0       Get end of file offset
       SRL  R0,8
       LDCR @B02,4
       A    R0,@54(R4)
       MOV  R8,@62(R4)

* Now for a fixed length file we need to add one more.

       LDCR @2(R4),4
       MOVB @12(R3),R0       Get file flags
       ANDI R0,>8000
       JNE  OAP17A
       LDCR @B02,4
       INC  @54(R4)
OAP17A

* See if we can use a 512 byte buffer

       CI   R1,SECBUF
       JNE  OAP18
       LDCR @B04,4
       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       MOV  @SAUTBL(R3),R3
       CI   R3,2
       JL   OAP18

       LDCR @B02,4
       SETO @58(R4)          Set buffer size to 512

OAP18  LDCR @ZERO,4
       MOV  *R1+,R0
       LDCR R2,4
       MOV  R0,*R5+
       CI   R1,SECBUF+512
       JNE  OAP18
OAP50
       LDCR @ZERO,4
       B    @DSRRT
