.NLIST ; .LIST TTM ; LIST IN TELETYPE (80-COLUMN) MODE ; .NLIST ; DON'T LIST ANYTHING ; .NLIST SYM ; DON'T LIST SYMBOL TABLE ; .NLIST COM ; DON'T LIST COMMENTS ; .NLIST SEQ ; DON'T LIST LINE NUMBERS ; .NLIST LOC ; DON'T LIST PC LOCATIONS ; .NLIST BIN ; DON'T LIST BINARY CODE .NLIST CND ; DON'T LIST UNSATISIFED CONDITIONAL CODING ; .LIST MEB ; LIST MACRO EXPANSIONS .NLIST BEX ; LIST ONLY 1ST LINE OF BINARY EXPANSIONS .ENABL AMA ; LIST ABSOLUTE ADDRESSES .LIST ; ;************************************ .TITLE BADBLK ;************************************ ; .IDENT /PMC002/ ; ; AS IS STANDARD FOR ALL KODAK TASKS, IN ANSWER TO ANY ; QUERY CAUSES TASK TO EXIT. ; .SBTTL DIFFERENCES BETWEEN TASKS "BAD" AND "BADBLK" ; ; TASK MAY BE INSTALLED AND INVOKED BY >BAD ; ; ; THIS TASK DIFFERS FROM SYSTEM TASK "BAD" IN THAT ; ; 1) IT CHECKS LARGE GROUPS OF BLOCKS INSTEAD OF SINGLE BLOCKS ; 2) IT OFFERS AN OPTION FOR THE NUMBER OF RE-TRIES TO BE MADE ; BEFORE A BLOCK IS MARKED "BAD". ; 3) ALL GOOD BLOCKS ON THE DISK MAY BE CLEARED, INSTEAD OF LEAVING ; THEM FILLED WITH A NON-ZERO TEST PATTERN. ; 4) IT LISTS ALL THE BAD BLOCKS THAT ARE FOUND. ; 5) IF BLOCKS REQUIRE SEVERAL RE-TRIES, EVEN THOUGH THEY ; ARE FINALLY CONSIDERED GOOD, THE BLOCK NUMBERS AND ; NUMBER OF RE-TRIES REQUIRED ARE LISTED. ; 6) IF A PACK HAS A LABEL, THE LABEL AND DATE ARE DISPLAYED ; FOR VERIFICATION BEFORE THE DATA ARE DESTROYED. ; .SBTTL DESCRIPTION OF TASK OPERATION ; ; TASKS "BAD" AND "BADBLK" BOTH START BY FINDING THE HIGHEST ; GOOD BLOCK ON THE PACK. THIS BLOCK IS THEN RESERVED FOR STORING ; ALL THE BAD-BLOCK DATA SUBSEQUENTLY FOUND -- AND IS ITSELF MARKED ; AS A "BAD-BLOCK" EVEN THOUGH IT IS NOT! IT IS IDENTIFIABLE BY ; VIRTUE OF HAVING A VALID CHECKSUM IN ITS LAST WORD. IT MAY BE ; REFERRED TO AS THE "BAD-BLOCK-STORAGE-BLOCK". ; ; SINCE NO EXTENSION FILE HEADERS CAN BE PROVIDED FOR THIS ; BLOCK, THE MINIMUM NUMBER OF BAD BLOCKS THAT CAN BE RECORDED IS ; THE NUMBER OF POINTERS IN FILE BADBLK.SYS, OR 102. THIS NUMBER ; CAN BE GREATER IF THERE ARE CONTIGUOUS BAD BLOCKS. THE THEORETICAL ; MAXIMUM NUMBER IS 102*256, OR 26112, SINCE EACH RETRIEVAL POINTER ; CAN REFERENCE UP TO 256 CONTIGUOUS BLOCKS. THIS NUMBER CAN NEVER ; BE APPROACHED ON A USEABLE DISK PACK, HOWEVER. ; ; IF "INIT" IS RUN WITH THE OPTION "BAD=[AUTO]", IT STARTS ; AT THE HIGHEST BLOCK AND CHECKS ITS CHECKSUM. IF INVALID, INIT ; SEARCHES BACKWARDS ONE BLOCK AT A TIME, LOOKING FOR A VALID ; CHECKSUM. (THE LIMIT OF THIS SEARCH IS NOT KNOWN, BUT IS ; PROBABLY ABOUT 100 BLOCKS). IF A VALID CHECKSUM IS FOUND, INIT ; MOVES THE DATA FROM THIS BLOCK INTO FILE BADBLK.SYS. IF NO BLOCK ; WITH A VALID CHECKSUM IS FOUND, INIT PROCEEDS, BUT WARNS THAT NO ; BAD-BLOCK DATA WAS FOUND, AND FILE BADBLK.SYS IS LEFT EMPTY. ; ; IF INIT IS RUN WITH THE OPTION "BAD=[AUTO,MAN]", IT PERFORMS ; THE OPERATION DESCRIBED ABOVE, BUT IN ADDITION ALLOWS THE MANUAL ; ENTRY OF ADDITIONAL BLOCKS AS BEING BAD. THESE WOULD NORMALLY ; BE MARGINAL BLOCKS. ; ; IF INIT IS RUN WITH OPTION "BAD=[MAN]", THE LAST GOOD DISK ; BLOCK IS NOT MARKED AS BAD, AND IS AVAILABLE FOR ALLOCATION IN ; ANOTHER FILE. HOWEVER, THIS COULD ONLY OCCUR IF THE THE PACK ; WERE COMPLETELY FILLED. ; ; "BAD" AND "BADBLK" ALWAYS IGNORE AND PREVIOUS "BAD-BLOCK" ; DATA AND RECORD ONLY THE CURRENT DISK-DRIVE CONDITIONS. ; .SBTTL MACROS .PAGE ; .MCALL ALUN$S, QIOW$S, EXIT$S, HMBOF$, DEF$L .MCALL QIO$S, MRKT$S, WTLO$S, RDEF$S ; HMBOF$ DEF$L ; ; LOCAL MACRO FOR OUTPUTTING MESSAGES TO THE CONSOLE .MACRO MSG A MOV #'A',R4 MOV #'A'L,R5 CALL TYPE .ENDM ; ; LOCAL MACRO FOR READING DATA OR ANSWERS IN RESPONSE TO A PROMPT .MACRO GETANS A,B,C .IF NB C .IFT MOV #C,R2 .IFF MOV #DATA,R2 .ENDC .IF NB B .IFT MOV #B,R3 .IFF MOV #1,R3 .ENDC MOV #'A',R4 MOV #'A'L,R5 CALL INPUT .ENDM ; .SBTTL TASK CONSTANTS AND VARIABLES .PAGE CR=15 LF=12 DATA: .BLKW 16. CLEAR: .WORD 0 TRIES: .WORD 10. BLKCT: .BLKW 2 BBADR: .WORD 0,1 ; INITIALLY SET TO READ HOME BLOCK IOST: .BLKW 2 ; I/O STATUS BLOCK BLOCKS: .WORD BLOX ; BUFFER BLOCKS (SEE BUFFER SECTION) BYTES: .WORD BITES ; BYTES IN BUFFERS " " " PT: .WORD 4 ; POINTER FOR BAD-BLOCK STORAGE BLOCK .SBTTL SYSTEM ERRORS THAT CAUSE TASK TO STOP ; ; SYSTEM ERRORS THAT WILL CAUSE TASK TO STOP. ; (MAY REQUIRE FUTURE REVISION) ERR: .BYTE IE.DNR ; DEVICE NOT READY .BYTE IE.FHE ; FATAL HARDWARE ERROR .BYTE IE.OFL ; DEVICE OFF-LINE .BYTE IE.BCC ; BLOCK CHECK .BYTE IE.BLK ; LOGICAL BLOCK TOO LARGE ERRCT=.-ERR ; .SBTTL MESSAGES ; .EVEN M1: .ASCII \ THIS IS THE TASK TO DETECT BAD BLOCKS \ .ASCII \ON A DISK PACK.\\ ALL DATA ON THE PACK WILL \ .ASCII \BE DESTROYED.\\ ENTER DRIVE, E.G. "DP2:" \ .ASCII \ \ M1L=.-M1 .EVEN DR: .ASCII \ \ DRIVE: .BLKB 4 DRL=.-DR M2: .ASCII \ BADBLK STOPPED. LUN ASGMT FAILURE.\ M2L=.-M2 M3: .ASCII \ THE DEFAULT VALUE FOR THE NUMBER OF I/O\ .ASCII \ TRIES\\ BEFORE A BLOCK IS MARKED BAD IS 10.\ .ASCII \ DO YOU WANT A LESSER NUMBER? [Y/N] \ M3L=.-M3 M4: .ASCII \ ENTER THE NUMBER \ M4L=.-M4 M5: .ASCII \ BLOCK NUMBER \ M5A: .BLKB 7 .ASCII \ \ M5B: .BLKB 7 M5L=.-M5 M6: .ASCII \ MARKED BAD\ M6L=.-M6 M7: .ASCII \ REQUIRED \ M7A: .BLKB 1 .ASCII \ TRIES\ M7L=.-M7 M8: .ASCII \ STOP. DEVICE NOT IN PUD.\ M8L=.-M8 M9: .ASCII \ STOP. DEVICE IS MOUNTED.\ M9L=.-M9 M10: .ASCII \ BADBLK FINISHED\ M10L=.-M10 M11: .ASCII \ DISK IS NG. HOME BLOCK IS BAD.\ M11L=.-M11 M12: .ASCII \ PACK LABEL IS \ M12L=.-M12 LABEL=BUF2+H.VNAM LABELL=12. SPACE: .ASCII \ \ SPACEL=.-SPACE DATE=BUF2+H.VDAT DATEL=7 M13: .ASCII \ OK TO PROCEED? [Y/N] \ M13L=.-M13 M17: M14: .ASCII \ *** STOP *** \ M17L=.-M14 .ASCII \FCS \ M14A: .BLKB 4 M14L=.-M14 M15: .ASCII \ STOP. UNIT DID NOT RESPOND.\ M15L=.-M15 M16: .ASCII \ CLEAR PACK? (INCREASES RUN TIME BY \ .ASCII \50%) [Y/N] \ M16L=.-M16 M20: .ASCII \ STOP. TOO MANY BAD BLOCKS.\ M20L=.-M20 ; .SBTTL SUBROUTINES ; .EVEN ;***************************************************** ; TYPE SUBROUTINE ;***************************************************** TYPE: QIOW$S #IO.WLB,#1,#1,,#IOST,, RETURN ; ;***************************************************** ; INPUT SUBROUTINE ;***************************************************** INPUT: QIOW$S #IO.RPR,#1,#1,,#IOST,, CMP IOST,#IE.EOF BEQ 10$ RETURN 10$: EXIT$S ; ;***************************************************** ; DISK-WRITE SUBROUTINE ;***************************************************** WRITE: QIOW$S #IO.WLB,#2,#2,,#IOST,, RETURN ; ;***************************************************** ; SUBROUTINE TO READ BAD-BLOCK DATA BLOCK ;***************************************************** RDBBF: QIOW$S #IO.RLB,#2,#2,,#IOST,,<#BUF1,#512.,#0,BBADR,BBADR+2> RETURN ; ;***************************************************** ; SUBROUTINE TO WRITE BAD-BLOCK DATA BLOCK ;***************************************************** WRBBF: QIOW$S #IO.WLB,#2,#2,,#IOST,,<#BUF1,#512.,#0,BBADR,BBADR+2> RETURN ; ;***************************************************** ; SUBROUTINE TO PRINT BAD BLOCK INFORMATION ON CONSOLE ;***************************************************** PNTBLK: MOV #M5A,R0 MOV R4,R1 CLR R2 CALL $CBOMG ; HIGH ORDER WORD OF BLOCK NUMBER MOVB #' ,(R0)+ MOV R5,R1 MOV #1,R2 CALL $CBOMG ; LOW ORDER WORD OF BLOCK NUMBER MSG M5 RETURN ; ;***************************************************** ; SUBROUTINES TO FILL BUFFER WITH TEST PATTERNS ;***************************************************** ; ; (R0 MUST CONTAIN NUMBER OF BYTES TO BE WRITTEN TO DISK) FILLA: ; FILL WITH BIT PATTERN MOV #BUF,R3 MOV #125252,R1 MOV #52525,R2 BR FILLC FILLB: ; FILL WITH ZEROES CLR R2 CLR R1 FILLC: ASR R0 ; CONVERT BYTES TO WORDS ASR R0 ; CONVERT WORDS TO DOUBLE WORDS INC R0 ; AND ADD 1 10$: MOV R1,(R3)+ MOV R2,(R3)+ SOB R0,10$ MOV #BUF,R2 RETURN ; ;************************************************************* ; SUBROUTINE TO CHECK I/O ERRORS FOR TASK EXIT OR CONTINUATION ;************************************************************* ERRTST: TSTB IOST BLT 10$ RETURN 10$: MOV #ERRCT,R0 MOV #ERR,R1 20$: CMPB (R1),IOST BEQ 30$ INCB R1 SOB R0,20$ SEN ; RETURN WITH N STATUS BIT SET RETURN 30$: MOV #M14A,R0 MOVB (R1),R1 BIC #177400,R1 MOV #14412,R2 CALL $CBTA MSG M14 EXIT$S ; .SBTTL START OF PROGRAM .PAGE START: GETANS M1,4,DRIVE ; GET DRIVE MOV DRIVE,R0 ; ASSIGN LUN BIC #177770,DRIVE+2 MOVB DRIVE+2,R1 ALUN$S #2,R0,R1 BCC 10$ MSG M2 ; EXIT ON ASSIGNMENT FAILURE EXIT$S ; ; FIND DEVICE IN THE PUD 10$: MOV .PUDBA,R0 11$: CMP R0,.PUDEA ; CHK FOR END OF PUD BGT 13$ CMP DRIVE,U.DN(R0) BNE 12$ CMPB DRIVE+2,U.UN(R0) BEQ 14$ 12$: ADD #U.SZ,R0 ; GO TO NEXT PUD ENTRY BR 11$ 13$: MSG M8 EXIT$S ; EXIT IF DEVICE NOT IN PUD 14$: CMP U.RP(R0),R0 ; CHK FOR REDIRECTION BEQ 15$ MOV U.RP(R0),R0 MOV U.DN(R0),DRIVE MOVB U.UN(R0),DRIVE+2 BISB #60,DRIVE+2 BR 14$ 15$: BITB #CH.OFF,U.CH(R0) ; MOUNTED? BNE 16$ MSG M9 ; EXIT IF SO EXIT$S ; ; SAVE BLOCK COUNT 16$: MOV U.LBH(R0),BLKCT MOV U.LBN(R0),BLKCT+2 ; ; CHECK FOR CLEARING PACK GETANS M16 BICB #40,DATA CMPB #'Y,DATA BNE 17$ INC CLEAR ; ; READ HOME BLOCK AND PRINT CURRENT LABEL 17$: QIO$S #IO.RLB,#2,#2,,#IOST,,<#BUF2,#512.,#0,BBADR,BBADR+2> MRKT$S #3,#3,#2 WTLO$S 0,#6 RDEF$S #3 MOV $DSW,R1 BEQ 18$ MSG M15 EXIT$S 18$: CALL ERRTST MSG DR MSG M12 MSG LABEL MSG SPACE MSG DATE GETANS M13 BIC #40,DATA CMPB #'Y,DATA BEQ 20$ MSG M17 EXIT$S 20$: GETANS M3 ; CHECK ON NUMBER OF RE-TRIES TO BE MADE BICB #40,DATA CMPB #'Y,DATA BNE 30$ GETANS M4,1,TRIES SUB #60,TRIES BGT 30$ ; BE SURE VALUE IS + MOV #1,TRIES ; 30$: MOV BLKCT,R4 MOV BLKCT+2,R5 ; ; WRITE TEST PATTERN TO HIGHEST BLOCK (ONE LESS THAN BLOCK COUNT) 32$: SUB #1,R5 SBC R4 MOV #512.,R3 ; BYTE COUNT MOV #BUF,R2 CALL WRITE CALL ERRTST BLT 32$ 35$: MOV #BUF1,R2 CALL WRITE ; BAD BLOCK STORAGE BLOCK MOV R4,BLKCT MOV R4,BBADR MOV R5,BLKCT+2 MOV R5,BBADR+2 ; ; START CHECKING AT BLOCK 0,0 CLR R4 CLR R5 ; .SBTTL MAIN MULTI-BLOCK LOOP OF TASK ; ; ; SEE IF CHECKING IS FINISHED. BLKCT IS ALWAYS THE NUMBER OF ; BLOCKS STILL TO BE CHECKED. R4 AND R5 INDEX THE BLOCKS ; CURRENTLY BEING CHECKED. 60$: TST BLKCT BNE 70$ TST BLKCT+2 BNE 65$ JMP 85$ 65$: CMP BLOCKS,BLKCT+2 BLOS 70$ MOV BLKCT+2,R3 ASH #9.,R3 MOV R3,BYTES CLR BLKCT+2 BR 80$ 70$: SUB BLOCKS,BLKCT+2 SBC BLKCT ; ; WRITE MULTI-BLOCK TEST PATTERNS 80$: MOV BYTES,R0 CALL FILLA ; SET UP TEST PATTERN MOV #BUF,R2 MOV BYTES,R3 CALL WRITE ; WRITE FIRST TEST PATTERN CALL ERRTST BLT 90$ ADD #2,R2 CALL WRITE ; WRITE REVERSE TEST PATTERN CALL ERRTST BLT 90$ TST CLEAR BEQ 82$ MOV BYTES,R0 MOV #BUF,R3 CALL FILLB ; FILL BUFFER WITH ZEROS MOV BYTES,R3 MOV #BUF,R2 CALL WRITE ; CLEAR DISK BLOCKS CALL ERRTST BLT 90$ 82$: ADD BLOCKS,R5 ; SET UP NEXT GROUP OF BLOCKS ADC R4 BR 60$ ; ; END OF TASK 85$: MSG M10 EXIT$S ; .SBTTL SINGLE-BLOCK LOOP AFTER WRITE-FAILURE IN MAIN LOOP ; ; ; IF MULTI-BLOCK WRITE FAILS, START SINGLE BLOCK OPERATION 90$: MOV #512.,R0 MOV #BUF2,R3 CALL FILLB MOV #512.,R0 CALL FILLA MOV BLOCKS,R1 MOV #512.,R3 92$: MOV TRIES,R0 MOV #BUF,R2 95$: CALL WRITE CALL ERRTST BLT 96$ ADD #2,R2 CALL WRITE CALL ERRTST BLT 96$ TST CLEAR BEQ 120$ MOV #BUF2,R2 CALL WRITE CALL ERRTST BGT 120$ 96$: SOB R0,95$ MOV R1,-(SP) ; ; IF SINGLE-BLOCK WRITE FAILS AFTER REQUESTED NUMBER OF TRIES, ; MARK BLOCK AS BAD. MOV R4,-(SP) MOV R5,-(SP) CALL PNTBLK MSG M6 MOV (SP)+,R5 MOV (SP)+,R4 CMP #1,R5 ; CHECK FOR HOME BLOCK BNE 97$ TST R4 BNE 97$ MSG M11 ; IF HOME BLOCK IS BAD TASK STOPS EXIT$S ; .SBTTL RECORDING OF BAD BLOCK DATA ; 97$: CALL RDBBF ; READ BAD-BLOCK STORAGE BLOCK CMPB BUF1+2,BUF1+3 ; MAKE SURE ITS NOT FULL! BLT 98$ MSG M20 EXIT$S 98$: MOV PT,R0 ; NEXT WORD FOR STORING BAD BLOCK DATA TST BUF1+2(R0) ; IF 0, GO USE IT BEQ 105$ ; IF THERE ARE 400 CONTIG BAD BLOCKS, MOVB BUF1+1(R0),R1 ; SET UP NEW POINTER BIC #177400,R1 CMP #377,R1 BEQ 100$ INC R1 ADD BUF1+2(R0),R1 ; LAST BAD BLOCK + 1 CMP R1,R5 ; IF LATEST BAD BLOCK IS NOT CONTIG BNE 100$ ; WITH PREVIOUS ONE, SET UP NEW POINTER INCB BUF1+1(R0) ; OTHERWISE, INCREMENT CONTIG BLOCK COUNT ADD #400,BUF1+H.CHK2 ; UPDATE CHECKSUM BR 110$ ; ; SET UP NEW RETRIEVAL POINTER 100$: ADD #2,WDSUSD ADD #2,BUF1+H.CHK2 ADD #4,PT ADD #4,R0 ; ; STORE BLOCK NUMBER IN POINTER AND UPDATE CHECKSUM 105$: MOV R5,BUF1+2(R0) MOVB R4,BUF1(R0) ADD R5,BUF1+H.CHK2 ADD R4,BUF1+H.CHK2 110$: CALL WRBBF ; WRITE BACK BAD-BLOCK RECORD BLOCK MOV (SP)+,R1 ; RESTORE R1 BR 130$ ; ; IF WRITE IS SUCCESSFUL, CHECK THE NUMBER OF ATTEMPTS REQUIRED. ; (THIS POINTS OUT MARGINAL BLOCKS, THAT CAN BE ENTERED MANUALLY ; DURING "INIT" IF DESIRED). 120$: CMP TRIES,R0 BEQ 130$ MOV R4,-(SP) MOV R5,-(SP) CALL PNTBLK MOV TRIES,M7A SUB R0,M7A ADD #60,M7A MSG M7 MOV (SP)+,R5 MOV (SP)+,R4 130$: DEC R1 ; CONTINUE SINGLE-BLOCK OPERATION BLE 140$ ; TO END OF BLOCK GROUP ADD #1,R5 ADC R4 JMP 92$ 140$: JMP 60$ ; THEN REVERT TO MULTI-BLOCK MODE ; .SBTTL BUFFER SPACE FOR TEST PATTERNS ETC. ; ; BUF: .REPT 128. .WORD 125252 .WORD 52525 .ENDM BUF1: .WORD 1401 WDSUSD: .WORD 146000 .BLKW 253. .WORD 147401 BUF2: .BLKW 40.*256.+2 BLOX=.-BUF/512. BITES=.-BUF-4 ; .END START