!
!     RX02 FLOPPY DISC HANDLER
!
!     THIS IS THE UNIT 2&3 VERSION
!
!     %% LAST UPDATED 14TH MARCH 1980   FILE=RX021S
!
!     USES SYSTEM SLOTS 8 AND 14. INT SLOT -8.
!
!     CALLING PARAMETERS ARE AS FOLLOWS
!        P_A1=MODE    (0=READ,1=WRITE)
!        P_A2=ADDRESS OF BUFFER IN MEMORY
!        P_A3=BLOCK NUMBER ON DISC
!
!     SINCE DEIMOS DEALS IN 512 BYTE BLOCKS ALL TRANSFERS ARE 2*256
!BYTE SECTORS. THE FIRST 77 BLOCKS ARE RESERVED FOR THE SYSTEM.
!WITHIN EACH TRACK OF 26 SECTORS THE SECTORS ARE INTERLEAVED.
!
!     ON EXIT P_A1=FAULT NO. (0=OK)
!
!     ANY ERROR WILL RESULT IN UP TO 10 RETRIES.
!
!     STACK=300   STREAMS=0
!
CONTROL  K'101011'
SYSTEMROUTINESPEC  LINKIN(INTEGER  SERVICE)
SYSTEMROUTINESPEC  MAPHWR(INTEGER  SEG)
SYSTEMINTEGERFNSPEC  MAP ABS(INTEGER  VAD,LEN,ID)
PERMROUTINESPEC  SVC(INTEGER  EP,P1,P2)
BEGIN 
RECORDFORMAT  PF(BYTEINTEGER  SERVICE,REPLY,INTEGER  A1,A2,A3)
RECORDFORMAT  P2F(INTEGER  D)
RECORDFORMAT  RXF(INTEGER  CONTROL,DBREG)
CONSTRECORD (RXF)NAME  RX=K'117170';       !DEVICE ADDR
                                        ! VECTOR = 264
!
!     SYSTEM CONSTANTS
!
CONSTBYTEINTEGERNAME  KID=K'160030'
CONSTINTEGER  SYS1=8;                   !UNIT 2
CONSTINTEGER  SYS2=14;                  !UNIT 3
CONSTINTEGER  DINT=-8;                  !INT SLOT
!
!     RX02 PARAMETERS
!
CONSTINTEGER  TRBIT=K'400';             !READY BIT
CONSTINTEGERARRAY  RXTOP(1:2)=K'1751',K'1751';    !TOP OF DISC
OWNINTEGERARRAY  RXBOT(1:2)=K'77',K'77';          !BOTTOM OF DISC
CONSTINTEGER  RETC=10;                  !RETRY COUNT
CONSTINTEGER  READ=0;                   !INPUT PARAMS
CONSTINTEGER  WRITE=1
CONSTINTEGER  READFN=K'107';            !RX02 FUNCTIONS
CONSTINTEGER  WRITEFN=K'105'
CONSTINTEGER  EMPTYFN=K'103'
CONSTINTEGER  FILLFN=K'101'
CONSTINTEGER  TRDONE = K'200'
CONSTBYTEINTEGERARRAY  SECMAP(1:26)= C 
      1,3,5,7,9,11,13,15,17,19,21,23,25,2,4,6,8,10,12,14,16,18,20,22,24,26
!
!     GENERAL VARIABLS
!
RECORD  (PF) P,PX
RECORD  (P2F) NAME  P2
OWNINTEGER  SYS,FAULT,ID,CONT,SECTOR,TRACK,RETRIES,MAPIND,I,VADDR,PAR
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!           INTEGERFNS START HERE
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!     REPORT FAULT SEND A MESSAGE TO MOTHER
!
INTEGERFN  REPORT FAULT
      RECORD  (PF) PX
      PX_SERVICE=7; PX_REPLY=KID
      PX_A1=SECTOR; PX_A2=TRACK; PX_A3=RX_DBREG
      PONOFF(P)
      RESULT  = PX_A1
END 
!
!     MAPADDR MAPS BUS ADDRESS
!
INTEGERFN  MAPADDR(INTEGER  VADDR)
      PAR=MAP ABS(VADDR,512,ID)
      RESULT =1 IF  PAR=0
      PAR=PAR+(VADDR&K'17777')>>6
      IF  PAR>=K'2000' START ;          !SET 17TH&18TH BITS
         CONT=CONT!(PAR&K'6000')<<2
         PAR=PAR&K'1777'
      FINISH 
      RESULT =0
END 
!
!     SEEK DOES READ/WRITE
!
ROUTINE  SEEK(INTEGER  FN)
      RETRIES=0
      RD:   RX_CONTROL=CONT!FN;         !GO+INT ENABLE
      WHILE  RX_CONTROL&TRDONE=0 CYCLE ; REPEAT 
      RX_DBREG=SECTOR
      WHILE  RX_CONTROL&TRDONE=0 CYCLE ; REPEAT 
      RX_DBREG=TRACK
      P2_D=(-8)&X'FF'
      POFF(P2);                         !WAIT FOR INT
      IF  RX_CONTROL<0 START ;          !ERROR
         RETRIES=RETRIES+1
         IF  RETRIES#RETC THEN  ->RD;   !TRY AGAIN
         FAULT = REPORT FAULT
         IF  FAULT = 0 THEN  RETRIES=0 AND  -> RD
      FINISH 
END 
!
!     BUFFER DOES FILL/EMPTY
!
ROUTINE  BUFFER(INTEGER  FN)
      RETRIES=0
      WD:   RX_CONTROL=CONT!FN;         !GO+INT ENABLE
      WHILE  RX_CONTROL&TRDONE=0 CYCLE ; REPEAT 
      RX_DBREG=128;                    !WORD COUNT
      WHILE  RX_CONTROL&TRDONE=0 CYCLE ; REPEAT 
      RX_DBREG=PAR<<6+VADDR&K'77';      !BUS ADDRESS
      P2_D=(DINT)&X'FF'
      POFF(P);                          !WAIT FOR INT
      IF  RX_CONTROL<0 START ;          !ERROR
         RETRIES=RETRIES+1
         IF  RETRIES#RETC THEN  ->WD
         FAULT = REPORT FAULT
         IF  FAULT = 0 THEN  RETRIES = 0 AND  ->WD
      FINISH 
END 
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!**
!*****   CODE STARTS HERE
!**
!
LINKIN(DINT)
P2==PX
MAPHWR(4);                            !MAP TO DICS REGS
LINKIN(SYS1); LINKIN(SYS2)
!
!        MAIN LOOP-WAIT FOR DISC REQUEST
!
CYCLE 
      P_SERVICE=0
      POFF(P)
      IF  P_SERVICE=SYS2 START 
         CONT=K'420';                   !UNIT 3
         SYS=2
      FINISHELSESTART 
         CONT=K'400'
         SYS=1
      FINISH 
      FAULT=0; ID=P_REPLY
      VADDR=P_A2
      !
      !  CHECK IF ACCESS TO RESEVED AREA
      !
      IF  VADDR=0 START 
         RXBOT(SYS)=0; FAULT=9
      ELSESTART 
         IF  P_A3<RXBOT(SYS) OR  P_A3>RXTOP(SYS) C 
            THEN  FAULT=4 AND  ->FIN
         FAULT=MAPADDR(VADDR)
         ->FIN IF  FAULT#0
         !
         !  COMPUTE TRACK&SECTOR
         !
         TRACK=P_A3//13
         MAPIND=(P_A3-(TRACK*13))*2+1
         !
         !  DO DOUBLE TRANSFER
         !
         CYCLE  I=1, 1, 2
            SECTOR=SECMAP(MAPIND)
            IF  P_A1=READ START ;       !READ SEQUENCE
               SEEK(READFN)
               BUFFER(EMPTYFN) IF  FAULT = 0
            ELSEIF  P_A1=WRITE START ;  !WRITE SEQUENCE
               BUFFER(FILLFN)
               SEEK(WRITEFN)
            FINISH 
            EXIT  IF  FAULT # 0
            MAPIND=MAPIND+1;            !NEXT SECTOR
            VADDR=VADDR+256;           !NEXT ADDRESS
            IF  VADDR&K'17777'<256 START 
               PAR=MAP ABS(VADDR,0,10); !NEW SEG-RELEASE OLD ONE
               FAULT=MAPADDR(VADDR)
            FINISH 
            EXITIF  FAULT#0
         REPEAT 
         PAR=MAP ABS(VADDR,0,10);       !RELEASE USER SEG
      FINISH 
      !
      !RETURN MESSAGE TO USER
      !
FIN:  P_A1=FAULT
      P_SERVICE=ID
      IF  SYS=1 THEN  P_REPLY=SYS1 ELSE  P_REPLY=SYS2
      PON(P)
REPEAT 
!
ENDOFPROGRAM