* Function GETDDR - GET Directory Descriptor Record
*
* This function will take the name of the file in the
* FCN (Filename Compare Buffer) and get the DDR of the
* directory the file is named in.  If it is already in
* memory, it will set R5 to point to the DDR.  If it
* is not already in memory, it will read it from the
* disk.  If it cannot read it from the disk for any reason,
* it will return a 0 in R5.
*
* Register Usage:
*   R5  - points to DDR in memory
*   R10 - Flag to indicate if we found the directory we
*         want or a higher level directory
*
* Output:
*   R5 - Points to the ddr in RAM bank 3
*        R5 = 0 if the DDR is not found
*   SAVEAU - contains the AU of the ddr
*

GETDDR CLR  R10              Set flag for directory
       ANDI R12,>FF00        Make sure R12 is base CRU address
       AI   R12,24
       LDCR @B04,4           Select RAM bank 4

       LI   R2,NCB+40        Search for last period '.'
GDDR2  DEC  R2
       CI   R2,NCB-1         If there are no periods,
       JEQ  GDDR3              then we have to read the VIB
       CB   *R2,@PERIOD
       JNE  GDDR2

* Now search all subdirectory names in the cache for a match
*
GDDR3
       BLWP @FDDR
       JEQ  GDDR10

* The directory name is not in cache.  We will have to try
* the next higher level directory.
*
       SETO R10
       CI   R2,NCB-1         See if we have to read the VIB
       JNE  GDDR2

* OK, we will have to read in the VIB.
*
       CLR  R7               Select sector #0
       CLR  R8
       LDCR @ZERO,4          Select RAM bank 0
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  GDDR4
       AI   R8,16            Try reading the copy
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  GDDR4
       CLR  R5               An error occurred
       RT

GDDR4  LDCR @B04,4           Select RAM bank 4
       BLWP @RESDCE          Reserve a Directory Cache Entry

* Now R4 points to DCE
*     R5 points to DDR

* Set up Directory cache entry
*
       MOVB R6,*R4+          Put in SCSI ID
       MOVB @B03,*R4+        Put in RAM bank of DDR
       MOV  R5,*R4+          Put in DDR address
       AI   R4,40            Blank out the name
       CLR  *R4+             Set AU to 0
       SETO *R4              Set age to -1 so it doesn't get swapped out

* Now copy the VIB to the DDR cache
*

       LI   R1,SECBUF        SCSI buffer address
       LI   R0,256
GDDR6  LDCR @ZERO,4          Select RAM bank 0
       MOV  *R1+,R2
       LDCR @B03,4           Select RAM bank 3
       MOV  R2,*R5+
       DECT R0
       JNE  GDDR6

       AI   R5,-256          Now get the Sectors/AU from the VIB
       MOV  @10(R5),R0       Get disk size
       MOV  @16(R5),R5
       SRL  R5,12
       INC  R5
       LDCR @B04,4           Select RAM bank 4
       MOV  R6,R4
       SRL  R4,8
       SLA  R4,1
       MOV  R5,@SAUTBL(R4)
       MOV  R0,@DSZTBL(R4)

       B    @GETDDR          Now try it again

************************************************************
*
* Here is where we have to look at subdirectory names to
* get the next DDR.  Unless of course, we have the DDR we
* want.
*

GDDR10 MOV  @44(R4),@SAVEAU
       MOV  @2(R4),R5        See if DDR is in memory
       JNE  GDDR16

       MOV  @44(R4),R7       OK, we need to read it into memory
       LI   R3,SECBUF        Pointer to SCSI buffer
       MOV  R6,R5            Get AU of DDR
       SRL  R5,8
       SLA  R5,1
       MPY  @SAUTBL(R5),R7   Multiply AU by Sectors/AU
       SRL  R8,1             Divide by 2
       JNC  GDDR11
       AI   R3,>100          We will use last 256 bytes
GDDR11 SRL  R7,1
       JNC  GDDR12
       AI   R8,>8000
GDDR12 BLWP @BANKIT          Read the DDR from the drive
       DATA SCSIRD
       JEQ  GDDR14
       CLR  R5               Error, return a zero
       RT

* Copy the 256 byte sector from the SCSI buffer to the
* DDR cache

GDDR14 LDCR @B04,4           Select RAM bank 4
       BLWP @FREDCE
       LI   R1,256
GDDR15 LDCR @ZERO,4          Select RAM bank 0
       MOV  *R3+,R7
       LDCR @B03,4           Select RAM bank 3
       MOV  R7,*R5+
       DECT R1
       JNE  GDDR15

       AI   R5,-256          Restore pointer

GDDR16 CI   R10,0            See if we are done
       JNE  GDDR17
       LDCR @B04,4           Update age if necessary
       C    @46(R4),@>5FFE
       JH   GDR16A
       JEQ  GDR16A
       INC  @>5FFE
       MOV  @>5FFE,@46(R4)
GDR16A
       RT

* Move the directory name to the file name compare buffer in bank 0.
*
GDDR17 INC  R2
       LI   R3,FNCB
GDDR18 LDCR @B04,4           Select RAM bank 4
       CB   *R2,@PERIOD
       JEQ  GDR18A
       MOVB *R2+,R4
       LDCR @ZERO,4          Select RAM bank 0
       MOVB R4,*R3+
       JMP  GDDR18

GDR18A LDCR @ZERO,4
GDDR19 CI   R3,FNCB+10       See if we need to pad with spaces
       JEQ  GDDR20
       MOVB @SPACE,*R3+
       JMP  GDDR19

* Now start reading directory names
*
* We do a binary search of the subdirectory names in the DDR
*
GDDR20 LDCR @B04,4           Select RAM bank 4
       MOV  R6,R3            Get the number of sectors/AU for this device
       SRL  R3,8
       SLA  R3,1
       MOV  @SAUTBL(R3),R3

       LDCR @B03,4           Select RAM bank 3
       CLR  R0               R0 points to lower bound of subdirectories
       MOVB @23(R5),R1       Get the number of subdirectories
       JNE  GDDR21           If this directory has no subdirectories,
GDDERR CLR  R5               then return a null pointer
       RT

GDDR21 SRL  R1,8
       DEC  R1

GDDR22 LDCR @B03,4           Select RAM bank 3
       MOV  R0,R10           Calculate the midpoint
       A    R1,R10
       ANDI R10,>FFFE
       A    R5,R10
       MOV  @28(R10),R7      Get AU of subdirectory we want to check
       LDCR @B04,4           Select RAM bank 4
       MOV  R7,@SAVEAU       Save the AU to put in the cache entry
       MPY  R3,R7            convert AU to SCSI sector
       LI   R4,SECBUF        R4 points to SCSI buffer
       SRL  R8,1
       JNC  GDDR23
       AI   R4,>0100         Read upper 256 bytes of 512 byte buffer
GDDR23 SRL  R7,1
       JNC  GDDR24
       AI   R8,>8000
GDDR24 LDCR @ZERO,4          Select ram bank 0
       BLWP @BANKIT          Read DDR from SCSI drive
       DATA SCSIRD
       JNE  GDDERR           Branch if there was a read error

* Now compare the directory name to the one in the FNCB
*
       LI   R7,FNCB
       LI   R9,10
GDDR25 C    *R4+,*R7+
       JH   GDDR28
       JL   GDDR29
       DECT R9
       JNE  GDDR25

* We have a match - reserve a DCE and copy the DDR
*
       AI   R4,-10           Restore pointer to DDR in SCSI buffer
       MOV  R4,R7            Save pointer
       LDCR @B04,4           Select RAM bank 4
       BLWP @RESDCE

* Now fill in the Directory Name Cache Entry
*
       MOVB R6,*R4+          Store SCSI ID
       MOVB @B03,*R4+        Put in RAM bank of the DDR
       MOV  R5,*R4+          Put in the DDR address

* Now fill in the name of the directory
*
       MOV  R4,R3
       LI   R1,NCB
GDDR26 MOVB *R1+,*R3+
       C    R1,R2
       JNE  GDDR26

* Put in the AU
*
       MOV  @SAVEAU,@40(R4)

* And finally put in the age to complete the entry
*
       INC  @>5FFE
       MOV  @>5FFE,@42(R4)

* Now copy the DDR
*
       LI   R1,256
GDDR27 LDCR @ZERO,4          Select RAM bank 0
       MOV  *R7+,R8
       LDCR @B03,4           Select RAM bank 3
       MOV  R8,*R5+
       DECT R1
       JNE  GDDR27

* Now since we've destroyed R5 and R10, just go back to
* the beginning of the subroutine.  We'll find this
* directory in cache, so it shouldn't take very long.
*
       B    @GETDDR


* If the names didn't match, select another directory name
* to search.  If there are none left, return a null pointer.
*
GDDR28 C    R0,R1
       JEQ  GDDERR
       MOV  R0,R10
       A    R1,R10
       SRL  R10,1
       C    R10,R0
       JEQ  GDDERR
       MOV  R10,R1
       DEC  R1
       JMP  GDDR22

GDDR29 C    R0,R1
       JEQ  GDDERR
       MOV  R0,R10
       A    R1,R10
       SRL  R10,1
       MOV  R10,R0
       INC  R0
       JMP  GDDR22


************************************************************
*
* Function GETFDR
*
* This function will try to get the File Descriptor Record
* of the file specified in the name compare buffer.  If it
* is successful, it will copy the FDR into the SCSI buffer
* and return a pointer to it.
*
* Output:
*    R5 points to FDR in RAM bank 0 if found
*       R5 = 0 if FDR not found
*    SAVEAU contains the AU of the FDR on disk
*
**********************************************************

GETFDR ANDI R12,>FF00
       AI   R12,24
       LDCR @B02,4       Select RAM bank 2
       MOV  R11,@GFDRRT  Save return address

       BL   @GETDDR      Get the DDR first

       CI   R5,0
       JEQ  GFDR98

* Check to make sure the number of files in the directory
* does not equal zero.

       LDCR @B03,4       Select RAM bank 3
       MOVB @22(R5),R1   Get the number of files
       JEQ  GFDR98

* Read the file index and store it in DFDR
*
       MOV  @24(R5),R7   Get AU of the file index
       LDCR @B04,4
       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       MPY  @SAUTBL(R3),R7

       LI   R5,SECBUF    Point to SCSI buffer
       SRL  R8,1
       JNC  GFDR1
       AI   R5,>100
GFDR1  SRL  R7,1
       JNC  GFDR2
       AI   R8,>8000
GFDR2  LDCR @ZERO,4
       BLWP @BANKIT      Read the index from disk
       DATA SCSIRD
       JNE  GFDR98

* Copy the filename to the filename compare buffer (FNCB)
*
       LDCR @B02,4       Select RAM bank 2
       LI   R2,NCB+39
GFDR3  CB   *R2,@PERIOD
       JEQ  GFDR4
       DEC  R2
       CI   R2,NCB-1
       JNE  GFDR3

GFDR4  INC  R2
       LI   R4,FNCB
GFDR5  CI   R2,NCB+40
       JEQ  GFDR6
       CB   *R2,@SPACE
       JEQ  GFDR6
       MOVB *R2+,R3
       LDCR @ZERO,4
       MOVB R3,*R4+
       LDCR @B02,4
       JMP  GFDR5

GFDR6  LDCR @ZERO,4      Pad the rest of the name with spaces
GFDR6A CI   R4,FNCB+10
       JEQ  GFDR7
       MOVB @SPACE,*R4+
       JMP  GFDR6A

* Here is where we return to the calling program
*
GFDR98 CLR  R5           We did not find the FDR
GFDR99 LDCR @B02,4       Select RAM bank 2
       MOV  @GFDRRT,R11  Get our return address
       RT

GFDR7

* set the bounds for our binary search
*
       SRL  R1,8
       CLR  R0

* Copy the file index from the SCSI buffer to DFDR
*
       LI   R2,DFDR
       MOV  R1,R3
       DEC  R1
GFDR8  LDCR @ZERO,4
       MOV  *R5+,R4
       LDCR @B02,4
       MOV  R4,*R2+
       DEC  R3
       JNE  GFDR8

GFDR9  LDCR @B02,4
       MOV  R0,R2        Calculate the midpoint for the
       A    R1,R2        binary search
       ANDI R2,>FFFE
       MOV  @DFDR(R2),R7 Get AU of FDR we want to check
       LDCR @B04,4       Select RAM bank 4
       MOV  R7,@SAVEAU   Save the AU in case this is the one
       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       MPY  @SAUTBL(R3),R7
       LDCR @ZERO,4
       LI   R5,SECBUF
       SRL  R8,1
       JNC  GFDR10
       AI   R5,>100
GFDR10 SRL  R7,1
       JNC  GFDR11
       AI   R8,>8000
GFDR11 BLWP @BANKIT      Read the FDR from disk
       DATA SCSIRD
       JNE  GFDR98

* Now compare the filename
*
       LI   R3,FNCB
GFDR12 C    *R5+,*R3+
       JL   GFDR13
       JH   GFDR14
       CI   R3,FNCB+10
       JNE  GFDR12

       AI   R5,-10       We found it!!!
       JMP  GFDR99

* The file name did not match.  Modify the bounds
* of our binary search
*
GFDR13 C    R0,R1        Is there anything left to check?
       JEQ  GFDR98       If not, error
       MOV  R0,R2        Recompute the midpoint
       A    R1,R2
       SRL  R2,1
       MOV  R2,R0        Modify lower bound of the search
       INC  R0
       JMP  GFDR9

GFDR14 C    R0,R1        Is there anything left to check?
       JEQ  GFDR98       If not, error
       MOV  R0,R2        Recompute the midpoint
       A    R1,R2
       SRL  R2,1
       C    R2,R0
       JEQ  GFDR98
       MOV  R2,R1        Modify the upper bound of the search
       DEC  R1
       JMP  GFDR9
