************************************************************
*                                                          *
*  Procedure POSIT - POSITION                              *
*                                                          *
*  This procedure will take the record number speficied    *
*  in the PAB and position the file pointers at that       *
*  record.  If there is currently information in the       *
*  file buffer, it will call FLUSH before reading in       *
*  the new information.                                    *
*                                                          *
************************************************************

POSERR BL   @DSRERR
       DATA >0500            Attempt to read past EOF

POSIT
       LDCR @ZERO,4          Select RAM bank 0
       MOV  @PABBUF+6,R10    Get record number we want to read

       LDCR @B02,4           Select RAM bank 2
       MOV  R11,@POSIRT      Save return address
       BLWP @IFO
       MOV  @4(R5),R1        Get FDR address
       LDCR @2(R5),4         Select bank with FDR
       MOV  @18(R1),R0       Get # of records in file
       SWPB R0
       C    R10,R0
       JHE  POSERR

       LDCR @B02,4           Select RAM bank 2
       MOV  R10,@62(R5)      Save record number
       LDCR @2(R5),4         Select bank with FDR

* Now divide by number of records per sector to get the
* sector offset into the file.
*
       MOVB @13(R1),R0
       SRL  R0,8
       CLR  R9
       DIV  R0,R9

* Now R10 has the record number in the sector.
*     R9  has the sector in the file

* We now divide R9 by the number of sectors per
* AU to get an AU number and sector within AU

       CLR  R8
       LDCR @B04,4           Select RAM bank 4
       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       DIV  @SAUTBL(R3),R8

* Now R9 has the sector within AU.
*     R8 has the AU

* Now we have to go through the data chain and map
* the AU in the file to the AU on the disk.

       LDCR @B02,4           Select RAM bank 2
       LDCR @2(R5),4         Select BANK with FDR
       AI   R1,40            Point to data chain

POSIT1 MOV  *R1+,R2          Get AU from data chain
POSIT2 CI   R8,0             See if we're at the AU we want
       JEQ  POSIT4
       DEC  R8
       C    R2,*R1           See if we're at last AU in cluster
       JEQ  POSIT3
       INC  R2               If not, go to next one
       JMP  POSIT2

POSIT3 INCT R1               Point to next entry in chain
       JMP  POSIT1

* R2 has the AU we need.  If it's not in our buffer, we have
* to read it from the disk.

POSIT4 LDCR @B02,4           Select RAM bank 2
       MOV  @6(R5),@54(R5)   Reset pointer in buffer
       C    R2,@50(R5)       See what AU is in the buffer
       JNE  POSIT5
       C    R9,@52(R5)       See if right sector within AU
       JEQ  POSI13
       C    @58(R5),@ZERO    If we have a 512 byte buffer,
       JEQ  POSIT5           we may still be in luck

       AB   @B01,@54(R5)
       MOV  R9,R0
       DEC  R0
       C    R0,@52(R5)
       JEQ  POSI13

* We have to read the sector from the disk
*

POSIT5
       MOV  R2,@POSIAU       Save new AU
       MOV  R9,@POSISE       Save new sector in AU
       BL   @FLUSH
       LDCR @B02,4
       MOV  @POSIAU,R7       Restore AU
       MOV  @POSISE,R9       Restore sector within AU

       MOV  R7,@50(R5)       Save AU
       MOV  R9,@52(R5)       Save sector within AU
       MOV  @6(R5),@54(R5)   Reset pointer in buffer

       LI   R1,SECBUF
       LDCR @B04,4           Select RAM bank 4
       MOV  R6,R3
       SRL  R3,8
       SLA  R3,1
       MOV  @SAUTBL(R3),R3
       MPY  R3,R7
       A    R9,R8
       JNC  POSIT6
       INC  R7
POSIT6 SRL  R8,1
       JNC  POSIT7
       AI   R1,>100
POSIT7 SRL  R7,1
       JNC  POSIT8
       AI   R8,>8000
POSIT8 LDCR @ZERO,4
       BLWP @BANKIT
       DATA SCSIRD
       JEQ  POSIT9
       BL   @DSRERR
       DATA >0600            Device error

POSIT9 LDCR @B02,4
       CLR  @58(R5)          Set buffer size=256

* Now see if we can use a 512 byte buffer.  We can make
* this check a little more sophisticated by checking
* if R1 = SECBUF+256, we may be able to back it up
* to SECBUF and adjust pointer within sector and
* sector within AU accordingly
*
       MOV  @POSISE,R9
       CI   R1,SECBUF        Make sure we start out
       JNE  POSI14
       S    R9,R3
       CI   R3,1
       JEQ  POSI11
POSI10 SETO @58(R5)          Set buffer size=512
POSI11
       MOV  @6(R5),R3        Get buffer address
       MOVB @3(R5),R2        Get buffer bank
POSI12 LDCR @ZERO,4
       MOV  *R1+,R4
       MOV  *R1+,R7
       MOV  *R1+,R8
       MOV  *R1+,R9
       LDCR R2,4
       MOV  R4,*R3+
       MOV  R7,*R3+
       MOV  R8,*R3+
       MOV  R9,*R3+
       CI   R1,SECBUF+512
       JNE  POSI12

POSI13
* Compute a pointer into the buffer by multiplying
* the record within sector by the record size

       LDCR @B02,4
       MOV  @4(R5),R1        Get FDR address
       LDCR @2(R5),4         Select FDR bank
       MOVB @17(R1),R0       Get record length
       SRL  R0,8
       MPY  R0,R10

       LDCR @B02,4
       A    R11,@54(R5)      And add to buffer pointer
       MOV  @POSIRT,R11      Restore return address
       RT

POSI14 CI   R9,0
       JEQ  POSI11
       DEC  R9
       MOV  R9,@52(R5)       Save sector within AU
       AB   @B01,@54(R5)
       LI   R1,SECBUF
       JMP  POSI10
