.MCALL .MODULE .MODULE DZ,VERSION=20,COMMENT=,AUDIT=YES ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. .SBTTL CONDITIONAL ASSEMBLY SUMMARY ;+ ;COND ; MMG$T std conditional ; TIM$IT std conditional (no code effects) ; ERL$G std conditional ;- .ENABL LC .SBTTL General Comments ;+ ; This handler serves as the standard RT-PC RX50 device handler. It ; is both the system and non-system handler. It also provides two ; special function capabilities to support physical I/O on the floppy ; as a foreign volume. The special functions are: ; ; Code Action ; ; 377 Absolute sector read. ; WCNT=TRACK, BLK=SECTOR, BUFFER=256 word buffer ; 376 Absolute sector write. Arguments same as code 377. ; ; In standard RT-PC mode, a 2:1 interleave is used on a single track and ; a 2 sector skew is used across tracks. ;- .SBTTL DEFINITIONS .MCALL .DRDEF, .ASSUME, .BR, .ADDR .DRDEF DZ,52,FILST$!SPFUN$,800.,0,0 .DRPTR FETCH=DZLOAD,LOAD=DZLOAD .DREST CLASS=DVC.DK .DRSPF <377> ; Read Absolute .DRSPF <376> ; Write Absolute .SBTTL Constants and defaults .IIF NDF DZ.CMA, DZ.CMA = 173206 ;Interrupt A command register .IIF NDF DZ.CMB, DZ.CMB = 173212 ;Interrupt B command register .IIF NDF DZ.IEN, DZ.IEN = 1 ;Bit number of interrupt enable bit DZ$CS0 = 4 ;Offset from RX5ID to RX5CS0 SPFUNC = 100000 ;Special functions flag in command word SYSPTR = 54 ;Pointer to base of RMON P1EXT = 432 ;Offset from $RMON to external routine GETVEC = 436 ;Offset from $RMON to $GTVEC routine ; RX50 Controller defaults PC$CSR = 174000 ;Base device address of PC option modules PC$VEC = 300 ;Base interrupt vector address for PC options PC$IC1 = 173206 ;PC interrupt controller 1 CSR address PC$IC2 = 173212 ;PC interrupt controller 2 CSR address MMUSR0 = 177572 ;Memory management unit SR0 MMUSR3 = 172516 ;Memory management unit SR3 .IRPC X <01234567> KISAR'X = 172340+<2*X> ;Kernel Instruction PAR'X KISDR'X = 172300+<2*X> ;Kernel Instruction PDR'X .ENDR AP$ACF= 077406 ;4KW page with no trap/abort PROCFG = 37776 ;PAR1 biased address of start of PRO3xx CONFIG table CTI = -10. ;Offset to number of option slots SLOT0 = -14. ;Option slot 0 ID DZ$ID = 2004 ;Hardware device id # for RX50 controller ; Control and status register bit definitions DZ.ID = -4 ;Offset to RX5ID from RX5CS0 ;+ ;Offset and command mode bit definitions of RX5CS0. ;- DZ.CS0 = 0 ;RX5CS0 C0.DSK = 002 ;Disk select C0.DRV = 004 ;Drive select C0.MTO = 010 ;Extended motor timeout C0.FN0 = 020 ;Mask bit for FUNTION BIT 0 C0.FN1 = 040 ;Mask bit for FUNTION BIT 1 C0.FN2 = 100 ;Mask bit for FUNTION BIT 2 C0.STA = 000 ;Read status function C0.RSD = 040 ;Restore drive function C0.RSS = 060 ;Restore subsystem function (RX INIT) C0.RED = 100 ;Read sector function C0.RER = 120 ;Read sector with retries function (EXTENDED) C0.RAD = 140 ;Read address function C0.WRT = 160 ;Write sector C0.DON = 10 ;Done bit ;+ ;These offsets are relative to the RX5CS0 register (X04). ;- DZ.CS1 = 2 ;Offset to RX5CS1 from RX5CS0 DZ.CS2 = 4 ;Offset to RX5CS2 from RX5CS0 DZ.CS3 = 6 ;Offset to RXCS3 from RXCS0 DZ.DB = 14 ;Offset to RX5DB from RX5CS0 DZ.CA = 16 ;Offset to RXCA from RXCS0 DZ.GO = 20 ;Offset to RX5GO from RX5CS0 DZMTRK = 79. ;Highest track ; Error and status register bit definitions RETRY = 8. ;Max number of retries (write function only) DZNREG = 7. ;Number of registers for error log ; Miscellaneous hardware definitions KISAR1 = 172342 ;KT-11 PAR for mapping user buffer .SBTTL Installation checks .DRINS DZ BR 1$ ;Non-system handler installation entry point BR 2$ ;System handler installation entry point 1$: MOV @#SYSPTR,R3 ;R3 -> $RMON MOV GETVEC(R3),R3 ;R3 -> $GTVEC TST (R3)+ ;R3 -> $GTCSR 2$: MOV #DZ$ID,-(SP) ;Push hardware device id number on stack CALL @R3 ;Call $GTCSR routine MOV (SP)+,R3 ;*C* Pop CSR address off stack RETURN ;Return with carry indicating success/failure ;+ ;Routine to find the entry for DZ in the monitor device tables ;- FINDRV: .ADDR #DEVNAM,R0 ;R0 -> DEVICE NAME MOV PC,-(SP) ; ADD #DAREA-.,@SP ;(SP) -> .DSTATUS information area EMT 342 ;.DSTATUS (#DAREA,#DEVNAM) BCS O.BAD ;Branch if not known MOV DAREA+4,R1 ;Return the entry point BEQ O.BAD ;Branch if handler is not loaded BR O.GOOD ;Return with success DAREA: .BLKW 4 ;.DSTAT information DEVNAM: .RAD50 /DZ / ;Device name ;+ ;The EMT area for reads/writes of the handler file is placed here to ;leave room for the set option code ;- BAREA: .BYTE 17,10 ;Channel 17, READ .BLKW 0 ;Block number to read/write .BLKW 0 ;Buffer address .WORD 256. ;Transfer count (words .WORD 0 ;Completion (WAIT) .IIF GT,<.-356> .ERROR ;Installation code is too large .SBTTL SET options .DRSET RETRY, 127., O.RTRY, NUM .IF NE ERL$G .DRSET SUCCES, -1, O.SUCC, NO .ENDC ;NE ERL$G .SBTTL Handler modification routines O.RTRY: CMP R0,R3 ;RETRY entry - asking for too many? BHI O.BAD ;Yes, user is being unreasonable MOV R0,DRETRY ;Nope, so tell the handler BNE O.GOOD ;Okay if non-zero BR O.BAD ;Can't ask for no retries .IF NE ERL$G O.SUCC: MOV #0,R3 ;'Success' entry point ; (Must be two words) N.SUCC: MOV R3,SCSFLG ;'Nosuccess' entry point .ASSUME O.SUCC+4 EQ N.SUCC BR O.GOOD .ENDC ;NE ERL$G O.GOOD: TST (PC)+ ;Clear C-bit O.BAD: SEC ;Set C-bit. Don't install RETURN .IIF GT,<.-1000> .ERROR .SBTTL Driver request entry point .ENABL LSB .DRBEG DZ .IF NE ERL$G BR DZENT ;Branch over success flag SCSFLG: .WORD 0 ; :Successful logging flag (default=YES) ; =0 - Log successes, ; <>0 - Don't log successes .ASSUME . LE DZSTRT+1000 DZENT: .ENDC ;NE ERL$G MOV #9.,DZTRY ;Set retry count (no retries) MOV #110,R0 ;Get "clear IRR" command BIS (PC)+,R0 ;Set in the interrupt enable bit INTENB: .WORD DZ.IEN ; : Interrupt enable bit MOV #50,R2 ;Get "clear IMR" command BIS INTENB,R2 ;OR in the IMR address bit MOV (PC)+,R1 ;R1 -> interrupt mask register IRRA: .WORD DZ.CMA ; : Interrupt A control command register MOV R0,@R1 ;Clear pending interrupts MOV R2,@R1 ;Enable interrupts MOV (PC)+,R1 ;R1 -> interrupt mask register IRRB: .WORD DZ.CMB ; : Interrupt B command register MOV R0,@R1 ;Clear pending interrupts NOP ;NOTE: This NOP becomes the following ; MOV R2,@R1 ;Enable interrupts MOV R2,(PC)+ ;Save the enable interrupts command ENABLE: .WORD 0 ; : Enable interrupt command MOV #70,R2 ;Get a "set IMR" command BIS INTENB,R2 ;OR in the IMR address bit MOV R2,(PC)+ ;Save the disable interrupts command DSABLE: .WORD 0 ; : Disable interrupt command CLR (PC)+ ;Clear .SPFUN flag SPFUNF: .WORD 0 ; : .SPFUN flag MOV DZCQE,R3 ;R3 -> queue element MOV (R3)+,R5 ;R5 = block number MOV #C0.RED,R4 ;Assume read on drive 0, disk A, side 0 MOVB (R3)+,R1 ;R1 = special function code (sign extended) CMPB #376,R1 ;Is special function request out of range? [+GTS] BLE 45$ ;NO, OK [+GTS] JMP DZABRT ;YES, Abort [+GTS] DRETRY: .WORD RETRY ;Retry count 45$: ; [+GTS] MOVB (R3)+,R0 ;R0 = unit number ASRB R0 ;Shift it to check for disk A or disk B BCC 20$ ;Branch if disk A BIS #C0.DSK,R4 ;Select disk B for transfer 20$: ASRB R0 ;Shift unit to check for second drive BCC 30$ ;Nope, first drive BIS #C0.DRV,R4 ;Select second drive 30$: ASRB R0 ;Valid unit number? [+GTS] BCS DZERR ;NO, report hard error [+GTS] MOV (R3)+,R0 ;R0 -> user's buffer MOV (R3)+,R2 ;R2 = word count BPL 40$ ;Positive means read. All set up (non-SPFUN) BIS #C0.WRT,R4 ;Make it a write NEG R2 ;Make word count positive 40$: ASL R1 ;Double the special function code MOV R1,SPFUNF ;Flag special function, if any ADD PC,R1 ;Form PIC reference to CHGTBL ADD CHGTBL-.(R1),R4 ;Modify the code, set sign bit if .SPFUN MOV R4,DZFUN2 ;Save the function code TST SPFUNF ;Special function? BNE 90$ ;If .SPFUN, go do special setup ; ; Normal I/O, convert block number to track and sector number and interleave ; ASL R2 ;Make word count unsigned byte count MOV (PC)+,R4 ;Loop count for 8 bit division .BYTE -7.,-10. ;Count becomes 0, -10 in high byte for later 50$: CMP #1280.,R5 ;Does 10 go into dividend (10.*200)? BHI 60$ ;Branch if not, C-bit clear ADD #-1280.,R5 ;Subtract 10 from dividend, and set C-bit ;(10.*200) 60$: ROL R5 ;Shift dividend and quotient INCB R4 ;Decrement loop count BLE 50$ ;Branch until divide done MOVB R5,R1 ;Copy track number 0:79, zero extend ADD R4,R5 ;Make sector < 0 MOV R1,R4 ;Copy track number ASL R1 ;Multiply by 2 (skew) 70$: SUB #10.,R1 ;Reduce track number * 2 MOD 10 BGT 70$ ; to find offset for this track, -10:0 MOV R1,TRKOFF ;Save it BR 100$ ;Go save parameters and start ; ; Special function request, set track, sector, and byte count ; 90$: SWAB R5 ;Put physical sector in high byte BISB R2,R5 ; and physical track in low byte MOV #512.,R2 ;Set the byte count to 512 ; ; Merge here to start operation ; 100$: MOV R0,(PC)+ ;Save buffer address BUFRAD: .WORD 0 ; : User virtual buffer address MOV R5,(PC)+ ;Save track and sector for starting I/O TRACK: .BYTE 0 ; : Track number SECTOR: .BYTE 0 ; : Sector number, kept < 0 unless .SPFUN MOV R2,(PC)+ ;Save byte count. BYTCNT: .WORD 0 ; : Byte count for transfer .IF NE MMG$T TST (R3)+ ;Skip the completion routine address MOV @R3,PARVAL ;Save the PAR1 value for mapping user buffer .ENDC ;NE MMG$T .BR DZINIT ;Go start up funtion .DSABL LSB .SBTTL Start transfer or retry .ENABL LSB DZINIT: MOV DZCSA,R4 ;R4 -> RX5CS0 MOV R4,R5 ;Copy pointer ADD #DZ.DB,R5 ;R5 -> RX5DB 10$: MOV DZFUN2,R0 ;R0 = function code MOV R0,-(SP) ;Save the function code BIC #^C,@SP ;Leave only the function ; code bits CMP #C0.WRT,(SP)+ ;Is this a write function? BNE 30$ ;Branch if not, it's a read. Go fill silo TST DZTRY ;Is the retry count already set? BNE 20$ ;Branch if so MOV DRETRY,DZTRY ;Set it up 20$: JSR R0,SILOFE ;Write, load the silo from the user buffer MOVB (R2)+,@R5 ; : MOVB to be placed in-line in SILOFE MOV R1,@R5 ; : Zero-fill instruction for short writes 30$: MOVB SECTOR,R2 ;R2 = sector number BGT 50$ ;If > 0, .SPFUN, don't interleave SUB #-6.,R2 ;Add 6 to do interleaving BGT 40$ ;If > 0, map -5:-1 to 2:10. NOTE: C-bit = 0 ADD #4.,R2 ; Else map -10:-6 to 1:9 SEC ;Add 1 when doubling 40$: ROL R2 ;Double and interleave, sector 1:10 ADD (PC)+,R2 ;Add in the track offset, sector -9:10 TRKOFF: .WORD 0 ; : Track offset = track*2 MOD 10, range -10:0 BGT 50$ ;No modulus problems ADD #10.,R2 ;Fix to put sector in 1:10 range 50$: MOVB R0,@R4 ;Set up function, drive, disk, and side MOV TRACK,R0 ;Get track number CMPB R0,#DZMTRK+1 ;Is it time to wrap around BNE 60$ ;Branch if not CLR R0 ;Wrap around 60$: MOVB R0,DZ.CS1(R4) ;Set up track MOVB R2,DZ.CS2(R4) ;Set up the sector CLRB DZ.GO(R4) ;Start the transfer RETURN ;Return. We'll be back with an interrupt DZERR: MOV DZCQE,R4 ;R4 -> Current queue element BIS #HDERR$,@-(R4) ;Set hard error in CSW BR DZABRT ;Exit on hard error .SBTTL Interrupt and abort entry points .DRAST DZ,5 ;AST entry point .FORK DZFBLK ;Request fork level immediately MOV (PC)+,R0 ;Get function code DZFUN2: .WORD 0 ; : Function, drive, disk, and side MOV #512.,R3 ;Load a handy constant MOV (PC)+,R4 ;Get address of RX5CS0 DZCSA: .WORD DZ$CS0 ; : Address of RX5CS0 MOV R4,R5 ;R5 -> RX5CS0 ADD #DZ.DB,R5 ;R5 -> RX5DB TSTB @R4 ;Error? BMI DZRTRY ;Branch if so MOV DRETRY,DZTRY ;Reset the retry count MOV R0,-(SP) ;Push the function code BIC #17,@SP ;Leave only the function code bits CMP #C0.WRT,(SP)+ ;Is this a write function? BEQ 70$ ;Branch if so. Don't empty silo JSR R0,SILOFE ;For read, move the data from silo to buffer MOVB @R5,(R2)+ ; : MOVB to be placed in line in SILOFE MOV @R5,R2 ; : Data sluffer to be used for short read MOV #1,DZTRY ;Reads do retries in the controller 70$: INCB SECTOR ;Return here after writes. Bump sector number BNE 80$ ;Not off end of track yet ADD #-10.*256.+1,TRACK ;Reset sector, bump to next track ADD #2,TRKOFF ;Bump track offset value BLE 80$ ;OK if still in range -9:0 SUB #10.,TRKOFF ;Reset to proper range mod 10 80$: .IF EQ MMG$T ADD R3,BUFRAD ;Update buffer address .IFF ;EQ MMG$T ADD #8.,PARVAL ;Change map to bump address for next time .ENDC ;EQ MMG$T SUB R3,BYTCNT ;Reduce the amount left to transfer BHI 10$ ;Branch if not done 90$: .IF NE ERL$G TST SCSFLG ;Logging successful transfer? BNE 100$ ;If not, branch MOV #DZ$COD*400+377,R4 ;Set up R4 = ID/-1 MOV DZCQE,R5 ; and R5 -> current queue element CALL @$ELPTR ;Call error logger to report success .ENDC ;EQ ERL$G DZABRT: CLR DZFBLK+2 ;Clear fork block to avoid a dispatch 100$: MOV DSABLE,@IRRA ;Disable interrupts MOV DSABLE,@IRRB ; for both A and B interrupts .DRFIN DZ ;Go to I/O completion .DSABL LSB .SBTTL DZRTRY - Error handling .ENABL LSB DZRTRY: .IF NE ERL$G .ADDR #DZRBUF,R3 ;R3 -> location to store register information MOV R3,R2 ;Save in R2 for later MOV #DZNREG,R0 ;Get number of registers 10$: MOV (R4)+,(R3)+ ;Store the registers DEC R0 ;Count down BNE 10$ ;Loop MOVB DRETRY,R3 SWAB R3 BISB #DZNREG,R3 ;R3 = Max retry count / device register count MOV #,R4 BISB DZTRY,R4 DECB R4 ;R4 = Device ID / current retry count MOV DZCQE,R5 ;R5 -> queue element CALL @$ELPTR ;Call error logger MOV DZCSA,R4 ;Restore R4 = RX5CS0 address .ENDC ;NE ERL$G DEC (PC)+ ;Decrement retry count DZTRY: .WORD 0 ; : Retry count BGT 30$ ;Branch if more retries 20$: JMP DZERR ;Report an error 30$: MOV DZ.CS1(R4),R0 ;Get the error code .ADDR #DZERRT,R3 ; and addr of retry-able error table (PICly) 40$: TSTB @R3 ;End of table? BEQ 20$ ;Branch if so. CMP R0,(R3)+ ;Can we retry this one? BNE 40$ ;Branch if not JMP DZINIT ;Try again .DSABL LSB .SBTTL SILOFE - Fill or empty the silo ;+ ; SILOFE - Fill or empty the silo, dumping or zero-filling, if needed ; ; R4 -> RX5CS0 ; R5 -> RX5DB ; ; JSR R0,SILOFE ; .WORD fill/empty instruction: (R2 -> user buffer, R5 -> RX5DB) ; "MOVB (R2)+,@R5" for fill (write) ; "MOVB @R5,(R2)+" for empty (read) ; .WORD sluff instruction: (R5 -> RX5DB) ; "CLRB @R5" for fill (write) ; "MOVB @R5,R2" for empty (read) ; ; R1,R2 modified ; R3 = 512. ; ; NOTE: 1. This routine assumes errors can not occur during a fill or empty!! ; 2. Seek does a silo empty, a time waster ;- .ENABL LSB SILOFE: MOV (R0)+,20$ ;Put correct MOV instruction in for fill/empty MOV (R0)+,40$ ;Put in instruction to sluff data MOV #512.,R3 ;Set up loop counter CLRB DZ.CA(R4) ;Reset sector buffer, if need be MOV BUFRAD,R2 ;Get user virtual buffer address in R2 MOV BYTCNT,R1 ;Get byte count BEQ 50$ ;If zero, we are seeking .IF NE MMG$T JSR R0,@(PC)+ ;Let the monitor execute the following code. $P1EXT: .WORD P1EXT ; - Loaded by LOAD/FETCH code .WORD PARVAL-. ;Number of instructions in bytes plus 2. .ENDC ;NE MMG$T CMP R1,R3 ;Is the byte count <= 512.? BLOS 10$ ;OK if so MOV R3,R1 ;Do only 512. bytes at a time 10$: SUB R1,R3 ;Get amount to zero fill 20$: HALT ;Instruction to MOV or sluff data from silo DEC R1 ;Check for count done BNE 20$ ;Branch if more to transfer .IF NE MMG$T PARVAL: .WORD 0 ;using this value for the PAR 1 bias. .ENDC ;NE MMG$T 30$: TST R3 ;Need to zero anything? BEQ 50$ ;Branch if not 40$: HALT ;Sluff data DEC R3 ;More to zero? BNE 40$ ;Branch if so 50$: MOV #512.,R3 ;Restore R3 NOP ;;; RTS R0 ;Return .DSABL LSB .SBTTL Tables, fork block, end of driver ; Changes to CSR0 function code for special functions ; ; All function codes vector into this table. Normal reads and writes ; come in at label CHGTBL and return unchanged. The 376/377 SPFUNs will ; always enter this table as reads (C0.RED). ; 377 (absolute read) will come into the word before CHGTBL. ; Since it is already a read, this table will add a zero to keep the ; code unchanged. 376 (absolute write) will go into the second word before ; CHGTBL. It will add write and subtract read to make the code a write. ; .WORD C0.WRT-C0.RED ;376: read -> write .WORD C0.RED-C0.RED ;377: read -> read (stays the same as non-SPFUN) CHGTBL: .WORD 0 ;Non-SPFUN - the code stays the same DZFBLK: .WORD 0,0,0,0 ;DZ fork queue element ; Table of errors that can be retried .NLIST BEX DZERRT: .WORD 060 ;Data record not found .WORD 140 ;ID CRC .WORD 200 ;Data CRC .WORD 210 ;Lost data .WORD 0,0,0,0 ;Extra entries for table .LIST BEX .IF NE ERL$G DZRBUF: .BLKW DZNREG ;Error log storage .ENDC ;NE ERL$G .SBTTL VECTOR TABLE DZ$VEC = PC$VEC .DRVTB DZ,0,DZINT,SLOTID=DZ$ID .SBTTL Bootstrap read routine .DRBOT DZ,BOOT1,READ1,CONTROL= . = DZBOOT+40 ;Put the "JMP BOOT" into SYSCOM area BOOT1: JMP @#BOOT-DZBOOT ;Start the bootstrap .ENABL LSB . = DZBOOT+120 READ1: MOV @#B$DEVU,-(SP) ;Get unit booted from BR 10$ READ: MOV BTUNIT,-(SP) ;Get unit booted from 10$: CALL FNDCSR ;Initialize DZCSR0, if necessary MOV (SP)+,R4 ;R4 = unit booted from ASL R4 ;Turn unit number into drive/disk bits BIS #C0.RED,R4 ;Set up a read function MOV R4,(PC)+ ;Save select bits SELBIT: .WORD 0 ; : Function, disk, and drive select bits ASL R1 ;Turn word count into byte count MOV (PC)+,R4 ;Loop count for 8 bit division .BYTE -7.,-10. ;Count becomes 0, -10 in high byte for later 20$: CMP #1280.,R0 ;Does 10 go into dividend (10.*200)? BHI 30$ ;Branch if not, C-bit clear ADD #-1280.,R0 ;Subtract 10 from dividend, and set C-bit ; (-10.*200) 30$: ROL R0 ;Shift dividend and quotient INCB R4 ;Decrement loop count BLE 20$ ;Branch until divide done MOVB R0,R5 ;Copy track number 0:79, zero extend ADD R4,R0 ;Make sector < 0 MOV R5,R4 ;Copy track number ASL R5 ;Skew * 2 40$: SUB #10.,R5 ;Reduce track number * 2 MOD 10 BGT 40$ ; to find offset for this track, -10:0 MOV R5,TRKOF ;Save it (track offset) MOV R0,(PC)+ ;Save track and sector for starting I/O TRK: .BYTE 0 ; : Track number SEC: .BYTE 0 ; : Sector number, kept < 0 unless .SPFUN 50$: MOVB SEC,R0 ;R0 = sector number SUB #-6.,R0 ;Add 6 to do interleaving BGT 60$ ;If > 0, map -5:-1 to 2:10. NOTE: C-bit = 0 ADD #4.,R0 ; Else map -10:-6 to 1:9 SEC ;Add 1 when doubling 60$: ROL R0 ;Double and interleave, sector 1:10 ADD (PC)+,R0 ;Add in the track offset, sector -9:10 TRKOF: .WORD 0 ; : Track offset = track*2 MOD 10, range -10:0 BGT 70$ ;No modulus problems ADD #10.,R0 ;Fix to put sector in 1:10 range 70$: MOV (PC)+,R5 ;R5 -> RX5CS0 DZCSR0: .WORD PC$CSR+DZ$CS0 MOV SELBIT,@R5 ;Set up function MOVB TRK,DZ.CS1(R5) ;Stuff the track address MOVB R0,DZ.CS2(R5) ; and the sector MOV R5,R4 ;R4 -> RX5CS0 ADD #DZ.DB,R4 ;R4 -> RX5SB CLRB DZ.GO(R5) ;Start the transfer 80$: BITB #C0.DON,@R5 ;Done? BEQ 80$ ;Branch if not CLRB DZ.CA(R5) ;Reset the sector buffer pointer MOV #512.,R0 ;Set loop count 90$: MOVB @R4,(R2)+ ;Move a byte DEC R1 ;Decrement the byte count BEQ 100$ ;Branch if done DEC R0 ;Decrement the loop count BNE 90$ ;Get another byte 100$: INCB SEC ;Return here after writes. Bump sector number BNE 110$ ;Not off end of track yet ADD #-10.*256.+1,TRK ;Reset sector, bump to next track ADD #2,TRKOF ;Bump track offset value BLE 110$ ;OK if still in range -9:0 SUB #10.,TRKOF ;Reset to proper range mod 10 110$: TST R1 ;Done? BNE 50$ ;Branch if not CLC ;Make sure C-bit cleared RETURN .DSABL LSB FNDCSR: ASRB (PC)+ ;First time FNDCSR has been called? .WORD 1 BCC 3$ ;Branch if so CLR R5 ;Prepare to find configuration table BISB @#173050,R5 ;Get 32KB top of system RAM boundary SWAB R5 ;Convert to ASL R5 ; PAR value SUB #200,R5 ; of last 4KW page MOV R5,@#KISAR1 ;Map to it through kernel PAR1 MOV #AP$ACF,R5 MOV R5,@#KISDR1 ;Set 4K with no system trap/abort action CLR @#KISAR0 MOV R5,@#KISDR0 ;Set 4K with no system trap/abort action MOV #177600,@#KISAR7 ;Make KERNEL PAR7 -> I/O page MOV R5,@#KISDR7 ;Set 4K with no system trap/abort action BIS #20,@#MMUSR3 ;Turn on 22 bit addressing. INC @#MMUSR0 ;Turn on the KT-11 MOV #CTI+PROCFG,R3 ;Point to # of option slots .ASSUME SLOT0 EQ CTI-4 MOV @R3,R4 ;R4 = # of option slots MOV R4,R5 1$: TST -(R3) CMP -(R3),#DZ$ID ;Is RX50 in this slot? BEQ 2$ ;Branch if yes SOB R5,1$ ;Continue looking for device id CLR @#MMUSR0 ;Turn off memory management JMP @# ;Error -- cannot find device 2$: CLR @#MMUSR0 ;Turn off memory management SUB R5,R4 ;Compute slot # ASH #7.,R4 ;Compute CSR for RX50 ADD R4,DZCSR0 ; and save it for future use 3$: RETURN . = DZBOOT+556 BOOT: CALL FNDCSR ;Initialize DZCSR0 MOV DZCSR0,R2 ;R2 -> RX5CS0 MOV @R2,R1 ;Get status BIC #^C,R1 ;Clear all but disk and drive bits ;READ STATUS command (000) is also OR'd in .ASSUME EQ 0 MOV R0,(PC)+ ;Save the booted unit number BTUNIT: .WORD 0 ; : Booted unit number ASR R0 ;Convert disk, drive bits to unit number BIS R0,R1 ;Set unit number MOV R1,@R2 ;Save it until later CLRB DZ.GO(R2) ;Initiate the command 10$: BIT #,@R2 ;Is device busy? BEQ 10$ ;Branch if so MOV #10000,SP ;Set stack pointer MOV #2,R0 ;R0 = block number of second part of boot MOV #<4*256.>,R1 ;4 blocks worth MOV #1000,R2 ;Read at location 1000 CALL READ ;Go read it in MOV #READ1-DZBOOT,@#B$READ ;Store start location for read routine MOV BTUNIT,@#B$DEVU ; and the booted unit number JMP @#B$BOOT ; and go to next part of boot .DREND DZ ; FETCH/LOAD CODE DZLOAD: MOV (R5),R5 ; Get handler address .IF NE MMG$T MOV @#SYSPTR,R4 ;R4 -> monitor base MOV P1EXT(R4),$P1EXT-DZLQE(R5) ; Get address of externalization ; routine .ENDC ;NE MMG$T MOV #DZ$ID,-(SP) ; @SP = DZ hardware id # TST (R1)+ ; R1 -> $GTCSR CALL (R1) ; @SP = DZ CSR ADD (SP)+,DZCSA-DZLQE(R5) ; Store addr of RX5CS0 in a ; convenient place MOV #DZ$ID,-(SP) ; @SP = DZ hardware id # TST (R1)+ ; R1 -> $GTSLT CALL (R1) ; @SP = DZ slot # MOV (SP)+,INTENB-DZLQE(R5) ;Save slot # for future use CLC ; Return success RETURN .END