! FILE 'RX022S'
!
!     RX02 FLOPPY DISC HANDLER
!
!     THIS IS THE UNIT 0&1 VERSION
!
!     %% LAST UPDATED 2ND APRIL 1980   FILE=RX022S
!
!     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)
SYSTEMINTEGERFNSPEC  GET 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
!
OWNINTEGER  KID
CONSTINTEGER  SYS1=3;                   !UNIT 2
CONSTINTEGER  SYS2=14;                  !UNIT 3
CONSTINTEGER  DINT=-3;                  !INT SLOT
!
!     RX02 PARAMETERS
!
CONSTINTEGER  TRBIT=K'400';             !READY BIT
OWNINTEGER  TOP=1000
OWNINTEGER  BOT=88
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,FN
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!           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(PX)
      RESULT  = PX_A1
END 
!
!     MAPADDR MAPS BUS ADDRESS
!
INTEGERFN  MAPADDR(INTEGER  VADDR)
      PAR=MAP ABS(VADDR,256,ID)
      RESULT =1 IF  PAR=0
      PAR=PAR+(VADDR&K'17700')>>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=(DINT)&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(P2);                          !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
KID=GET ID
LINKIN(SYS1); LINKIN(SYS2)
      WHILE  RX_CONTROL&K'40' = 0 CYCLE ; REPEAT 
!
!        MAIN LOOP-WAIT FOR DISC REQUEST
!
CYCLE 
      P_SERVICE=0
      POFF(P)
      IF  P_A3&K'020000'#0 START 
         P_A3 = P_A3&K'017777'
         CONT=K'420';                   !UNIT 3
         SYS=2
      FINISHELSESTART 
         CONT=K'400'
         SYS=1
      FINISH 
      FAULT=0; ID=P_REPLY
       FN = P_A1
      VADDR=P_A2
      !
      !  CHECK IF ACCESS TO RESEVED AREA
      !
      IF  VADDR=0 START 
         BOT=0; FAULT=9
      ELSESTART 
         IF  P_A3<BOT OR  P_A3>TOP 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  FN=READ START ;       !READ SEQUENCE
               SEEK(READFN)
               BUFFER(EMPTYFN) IF  FAULT = 0
            ELSEIF  FN=WRITE START ;  !WRITE SEQUENCE
               BUFFER(FILLFN)
               SEEK(WRITEFN)
            FINISH 
            EXIT  IF  FAULT # 0
            MAPIND=MAPIND+1;            !NEXT SECTOR
            VADDR=VADDR+256;           !NEXT ADDRESS
!            PAR = PAR+4;                ! THIS REALLY SHIFTS IT
! ALLWAYS DO NEXT BIT FOR NOW, 2 PROBLEMS, NEW SEG & > 32K
!            %IF VADDR&K'17777'<512 %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
      P_REPLY = SYS1
      PON(P)
REPEAT 
!
ENDOFPROGRAM