Thanks for all the answers, and thanks to Johnny for providing a pointer to the DX driver code.  FWIW, the DX driver performs the logical to physical translation using a “logical sector number”, where each logical block contains four consecutive logical sectors.   The routine that converts an LSN to a track and sector, and handles interleave and skew at the same time, is below.   I’m not even going to pretend I know how this works – it’s a bit obscure – but it’s straight forward enough to translate it literally into C.

 

Bob

 

;+

; *** - TRKSEC  -  CONVERT LOGICAL OR PHYSICAL BLOCK NUMBER TO

;              TRACK-SECTOR PAIR

; FROM ALGORITHM BY J GILBERT MODIFIED BY H. JACOBS

;

; INPUT:

;              R3 - I/O PACKET ADDRESS

;              I.PRM+10(R3) - LOGICAL OR PHYSICAL SECTOR

;

; OUTPUT:

;              I.PRM+14(R3) - SECTOR (1-26.)

;              I.PRM+15(R3) - TRACK (0-77.)

;              R3 - UNCHANGED

;              C CLEAR - VALID BLOCK

;              C SET - BAD BLOCK NUMBER (PHYSICAL OR LOGICAL)

;

;-

TRKSEC:               MOV      I.PRM+10(R3),R1              ; GET LOGICAL OR PHYSICAL BLOCK

               MOV      #8.,R0                  ; SET LOOP COUNT

               MOV      #6400,R2             ; SET DIVISOR

1$:         CMP       R2,R1                   ; DOES 26 GO INTO DIVIDEND?

               BHI         2$                          ; BRANCH IF NOT, C CLEAR

               SUB        R2,R1                   ; SUBTRACT 26 FROM DIVIDEND

               SEC                                      ; SET CARRY

2$:         ROL        R1                         ; SHIFT DIVIDEND AND QUOTIENT

               DEC        R0                         ; DONE?

               BGT        1$                          ; NO, LOOP

               MOVB   R1,R0                   ; GET TRACK NUMBER

               CLRB      R1                         ; CLEAR TRACK NUMBER

               SWAB    R1                         ; SHIFT DONE SECTOR NUMBER

               BITB       #IO.RPB&377,I.FCN(R3)  ; PHYSICAL BLOCK WANTED?

               BNE       10$                       ; YES

               CMP       #12.,R1                ; NO, C=1 IF 13<=R1<=25

               ROL        R1                         ; DOUBLE FOR INTERLEAVE FACTOR

               ASL         R0                         ; ADD TRACK -TRACK SKEW

               ADD       R0,R1                   ; SKEW BY 2*TRACK

               ADD       R0,R1                   ; SKEW BY 4*TRACK

               ADD       R0,R1                   ; SKEW BY 6*TRACK

               ASR        R0                         ; RESTORE TRACK NUMBER

               MOV      #26.,R2                ; SET MODULUS

5$:         SUB        R2,R1                   ; MODULO SECTOR INTO RANGE -26. TO -1.

               BGE        5$                          ; LOOP TILL REMAINDER GOES NEG

               ADD       R2,R1                   ; CONVERT TO RANGE 0-25.

               INC        R0                         ; LBN0 STARTS ON TRACK 1

10$:       INC        R1                         ; CONVERT TO RANGE 1-26.

               MOV      R1,I.PRM+14(R3)              ; SAVE SECTOR NUMBER

               MOVB   R0,I.PRM+15(R3)              ; SAVE TRACK NUMBER

               CMP       #77.*256.,I.PRM+14(R3)  ; IS IT A VALID TRACK/SECTOR?

               RETURN