;;; -*- Mode: Lisp; Package: File-System; Base: 8 -*- ;;; MagTape definitions. Mostly copied from RG;MT. ;internal functions: ; MT-PRINT-STATUS prints current status from hardware. ; EXECUTE-MT-RQB actually does it. This normally done by microcode for DISK-RQBs. ; MT-WAIT-READY, MT-WAIT-UNIT-READY ; UNIBUS-MAP-MT-RQB, UNIBUS-UNMAP-MT-RQB. ; MT-RUN rqb command &optional minus-byte-count unit density ibm-mode ; MT-RUN-SIMPLE command unit &optional count. For commands that dont transfer data. ; MT-SPACE, MT-SPACE-TO-EOF, MT-SPACE-REV, MT-SPACE-REV-TO-BOF, MT-SPACE-TO-APPEND ; MT-REWIND, MT-WRITE-EOF, MT-OFFLINE. ; Normal RQBs are now used for magtape, but ; PRINT-MT-RQB, WIRE-MT-RQB, UNWIRE-MT-RQB, UNIBUS-MAP-MT-RQB and UNIBUS-UNMAP-MT-RQB ; must be used with magtape RQBs. ;; This is also in FSDEFS (REMPROP 'QUOTIENT-CEILING 'SOURCE-FILE-NAME) (DEFSUBST QUOTIENT-CEILING (Y X) (CEILING Y X)) (DEFVAR FILE-SYSTEM-PACKAGE (PKG-FIND-PACKAGE "FS")) (DEFCONST %MT-RQ-DONE-FLAG 0) ;0 RQ ENTERED, -1 COMPLETED ;; These are set up by the requester (DEFCONST %MT-RQ-COMMAND 1) ;MT COMMAND REGISTER (DEFCONST %MT-BYTE-COUNT 2) ;NEGATIVE BYTE COUNT (DEFCONST %MT-READ 3) ;ADDITIONAL COMMAND BITS AND STATUS ;; These are stored when the operation completes. ;; The order must agree with the order of the UNIBUS addresses. (DEFCONST %MT-RQ-STATUS 4) ;MT STATUS REG (DEFCONST %MT-COMMAND-AFTER 5) ;MT COMMAND REGISTER AFTER XFER (DEFCONST %MT-BYTE-COUNT-AFTER 6) ;MT RECORD COUNT AFTER (DEFCONST %MT-RQ-MEM-ADDRESS 7) ;LAST UNIBUS REF ADDR (DEFCONST %MT-DATA-BUFFER 10) (DEFCONST %MT-READ-AFTER 11) (EVAL-WHEN (COMPILE LOAD EVAL) ;This says that the selected drive is ready. (DEFSUBST MT-STATUS-READY () (LDB-TEST 0001 (%UNIBUS-READ MT-UA-STATUS))) ;This says that the controller is ready. (DEFSUBST MT-COMMAND-READY () (LDB-TEST 0701 (%UNIBUS-READ MT-UA-COMMAND))) ;These are bits in the status stored after a request is executed. ;End of file mark reached when trying to read something. (DEFSUBST MT-STATUS-EOF () (LDB-TEST 1601 (AR-1 RQB %MT-RQ-STATUS))) ;End of tape reached. (DEFSUBST MT-STATUS-EOT () (LDB-TEST 1201 (AR-1 RQB %MT-RQ-STATUS))) ;At beginning of tape (rewound, or spaced back that far). (DEFSUBST MT-STATUS-BOT () (LDB-TEST 0501 (AR-1 RQB %MT-RQ-STATUS))) ;Any sort of error. (DEFSUBST MT-STATUS-ERROR () (NOT (ZEROP (LOGAND 115600 (AR-1 RQB %MT-RQ-STATUS))))) ) ;These are the OLD ways of accessing these flags. (DEFCONST %%MT-STATUS-ILL-COM 1701) (DEFCONST %%MT-STATUS-EOF 1601) (DEFCONST %%MT-STATUS-ODD-LENGTH 1501) ;Last word filled with 0s (DEFCONST %%MT-STATUS-PARITY-ERR 1401) ;parity error, LRC error, or postamble error (DEFCONST %%MT-STATUS-GRANT-LATE 1301) (DEFCONST %%MT-STATUS-EOT 1201) (DEFCONST %%MT-STATUS-RLENGTH 1101) ;RECORD LENGTH ERROR (DEFCONST %%MT-STATUS-BAD-TAPE 1001) (DEFCONST %%MT-STATUS-NXM 0701) (DEFCONST %%MT-STATUS-ON-LINE 0601) (DEFCONST %%MT-STATUS-BOT 0501) (DEFCONST %%MT-STATUS-7-TRACK 0401) (DEFCONST %%MT-STATUS-SETTLE 0301) ;after rewinding (DEFCONST %%MT-STATUS-WRITE-LOCK 0201) (DEFCONST %%MT-STATUS-REWINDING 0101) (DEFCONST %%MT-STATUS-READY 0001) (DEFCONST %MT-STATUS-ERROR 115600) ;Mask for bits which are errors normally ;This is the bit to set to tell the controller to execute the command ;already set up in the various registers. (DEFCONST %MT-COMMAND-GO 1) ;These are fields to set up in the RQB's %MT-RQ-COMMAND word ;to control a transfer or operation to be done. (EVAL-WHEN (COMPILE LOAD EVAL) (DEFSUBST MT-COMMAND-UNIT () (LDB 1003 (AR-1 RQB %MT-RQ-COMMAND))) (DEFSUBST MT-COMMAND-DENSITY () (LDB 1502 (AR-1 RQB %MT-RQ-COMMAND))) (DEFSUBST MT-COMMAND-XBA-BITS () (LDB 0402 (AR-1 RQB %MT-RQ-COMMAND))) (DEFSUBST MT-COMMAND-INTERRUPT-ENABLE () (LDB 0601 (AR-1 RQB %MT-RQ-COMMAND))) ;This field's value is one of the command codes below. (DEFSUBST MT-COMMAND () (LDB 0103 (AR-1 RQB %MT-RQ-COMMAND))) ) ;Mag tape command codes. (DEFCONST %MT-COMMAND-OFFLINE 0) ;unload tape (DEFCONST %MT-COMMAND-READ 1) (DEFCONST %MT-COMMAND-WRITE 2) (DEFCONST %MT-COMMAND-WRITE-EOF 3) (DEFCONST %MT-COMMAND-SPACE-FOR 4) (DEFCONST %MT-COMMAND-SPACE-REV 5) (DEFCONST %MT-COMMAND-WRITE-WITH-EXTENDED-GAP 6) (DEFCONST %MT-COMMAND-REWIND 7) (DEFCONST MT-COMMAND-NAMES '(%MT-COMMAND-OFFLINE %MT-COMMAND-READ %MT-COMMAND-WRITE %MT-COMMAND-WRITE-EOF %MT-COMMAND-SPACE-FOR %MT-COMMAND-SPACE-REV %MT-COMMAND-WRITE-WITH-EXTENDED-GAP %MT-COMMAND-REWIND)) (DEFCONST %%MT-COMMAND 0103) (DEFCONST %%MT-COMMAND-XBA-BITS 0402) ;EXTENDED UNIBUS ADR 17,16 (DEFCONST %MT-COMMAND-INTERRUPT-ENABLE 1_6.) (DEFCONST %%MT-COMMAND-READY 0701) (DEFCONST %%MT-COMMAND-UNIT 1003) (DEFCONST %MT-COMMAND-POWER-CLEAR 1_12.) (DEFCONST %%MT-COMMAND-DENSITY 1502) (DEFCONST %MT-COMMAND-ERROR 100000) ;Unibus register addresses. (DEFCONST MT-UA-STATUS 772520) (DEFCONST MT-UA-COMMAND 772522) (DEFCONST MT-UA-BYTEC 772524) (DEFCONST MT-UA-CMA 772526) (DEFCONST MT-UA-BFR 772530) (DEFCONST MT-UA-DRD 772532) ;Error reporting. (DEFUN MT-PRINT-STATUS NIL (FORMAT T "~%Status ") (MT-DECODE-STATUS (%UNIBUS-READ MT-UA-STATUS)) (FORMAT T "~%Command ") (MT-DECODE-COMMAND (%UNIBUS-READ MT-UA-COMMAND))) (DEFUN MT-DECODE-STATUS (STATUS) (CADR:CC-PRINT-SET-BITS STATUS '(TAPE-UNIT-READY REWIND-STATUS WRITE-LOCK SETTLE-DOWN SEVEN-TRACK BOT DRIVE-ON-LINE NXM BAD-TAPE RECORD-LENGTH-ERROR EOT BUS-GRANT-LATE PARITY-ERROR NOT-USED END-OF-FILE ILLEGAL-COMMAND))) (DEFUN MT-DECODE-COMMAND (COM) (CADR:CC-PRINT-SET-BITS COM '(GO FCN-0 FCN-1 FCN-2 XBA16 XBA17 INT-ENABLE CONTROLLER-READY UNIT-SEL0 UNIT-SEL1 UNIT-SEL2 PARITY-EVEN POWER-CLEAR DENSITY0 DENSITY1 ERROR))) (DEFUN PRINT-MT-RQB (RQB) (FORMAT T "~%command before:") (MT-DECODE-COMMAND (AR-1 RQB %MT-RQ-COMMAND)) (FORMAT T "~%Byte count before ~s" (AR-1 RQB %MT-BYTE-COUNT)) (FORMAT T "~%command after:") (MT-DECODE-COMMAND (AR-1 RQB %MT-COMMAND-AFTER)) (FORMAT T "~%status after:") (MT-DECODE-STATUS (AR-1 RQB %MT-RQ-STATUS)) (FORMAT T "~%mem addr after ~S, byte-count-after ~S" (AR-1 RQB %MT-RQ-MEM-ADDRESS) (AR-1 RQB %MT-BYTE-COUNT-AFTER)) RQB) ;Low-level command execution. ;Initialize the various header words of an RQB, such as %MT-RQ-COMMAND, ;then call EXECUTE-MT-RQB. ;; This must be used rather than SI:WIRE-DISK-RQB so not to hack the CCW list. (DEFUN WIRE-MT-RQB (RQB &OPTIONAL (WIRE-P T) SET-MODIFIED &AUX (LONG-ARRAY-FLAG (%P-LDB %%ARRAY-LONG-LENGTH-FLAG RQB)) (LOW (- (%POINTER RQB) (ARRAY-DIMENSION RQB 0) 2)) (HIGH (+ (%POINTER RQB) 1 LONG-ARRAY-FLAG (FLOOR (ARRAY-LENGTH RQB) 2)))) (DO LOC (LOGAND LOW (- PAGE-SIZE)) (+ LOC PAGE-SIZE) (>= LOC HIGH) (SI:WIRE-PAGE LOC WIRE-P SET-MODIFIED))) (DEFUN UNWIRE-MT-RQB (RQB) (WIRE-MT-RQB RQB NIL)) (DEFUN EXECUTE-MT-RQB (RQB &OPTIONAL SET-MODIFIED) (WIRE-MT-RQB RQB T SET-MODIFIED) (MT-WAIT-READY) (LET ((UA (UNIBUS-MAP-MT-RQB RQB))) (%UNIBUS-WRITE MT-UA-COMMAND (AR-1 RQB %MT-RQ-COMMAND)) ;SELECT UNIT (MT-WAIT-UNIT-READY) (%UNIBUS-WRITE MT-UA-CMA UA) (%UNIBUS-WRITE MT-UA-BYTEC (AR-1 RQB %MT-BYTE-COUNT)) (%UNIBUS-WRITE MT-UA-DRD (AR-1 RQB %MT-READ)) (%UNIBUS-WRITE MT-UA-COMMAND (+ (AR-1 RQB %MT-RQ-COMMAND) %MT-COMMAND-GO)) ;TURN ON THE "GO" BIT. (MT-WAIT-READY) (DOTIMES (W 6) (AS-1 (%UNIBUS-READ (+ MT-UA-STATUS (* 2 W))) RQB (+ %MT-RQ-STATUS W))) (UNIBUS-UNMAP-MT-RQB RQB) (UNWIRE-MT-RQB RQB) RQB)) (DEFUN SIGN-EXTEND-16 (X) (IF (ZEROP (LOGAND 100000 X)) X (LOGIOR X -100000))) (DEFVAR PAGE-SIZE-IN-BYTES (* PAGE-SIZE 4.)) ;8 bit bytes. (DEFUN MT-WAIT-READY () "Await controller ready" (OR (MT-COMMAND-READY) (PROCESS-WAIT "MagTape" #'(LAMBDA () (MT-COMMAND-READY)))) NIL) (DEFUN MT-WAIT-UNIT-READY () "Await selected unit ready" (OR (MT-STATUS-READY) (PROCESS-WAIT "MT Unit" #'(LAMBDA () (MT-STATUS-READY)))) NIL) (DEFUN UNIBUS-MAP-MT-RQB (RQB &OPTIONAL (FIRST-UMP 0) &AUX (LONG-ARRAY-FLAG (%P-LDB %%ARRAY-LONG-LENGTH-FLAG RQB)) (HIGH (+ (%POINTER RQB) 1 LONG-ARRAY-FLAG (FLOOR (ARRAY-LENGTH RQB) 2)))) (DO ((VADR (+ (%POINTER RQB) PAGE-SIZE) (+ VADR PAGE-SIZE)) ;Start with 2nd page of rqb array (UMP FIRST-UMP (1+ UMP)) (NP 0 (1+ NP))) ((>= VADR HIGH)) (COND ((> NP 14.) (FERROR NIL "TOO MANY PAGES"))) (SETUP-UNIBUS-MAP UMP VADR)) (+ 140000 (* FIRST-UMP 2000))) (DEFUN UNIBUS-UNMAP-MT-RQB (RQB &OPTIONAL (FIRST-UMP 0) &AUX (LONG-ARRAY-FLAG (%P-LDB %%ARRAY-LONG-LENGTH-FLAG RQB)) (LOW (- (%POINTER RQB) (ARRAY-DIMENSION RQB 0) 2)) (HIGH (+ (%POINTER RQB) 1 LONG-ARRAY-FLAG (FLOOR (ARRAY-LENGTH RQB) 2)))) (DO ((VADR (+ LOW PAGE-SIZE) (+ VADR PAGE-SIZE)) ;Start with 2nd page of rqb array (UMP FIRST-UMP (1+ UMP))) ((>= VADR HIGH)) (%UNIBUS-WRITE (+ 766140 (* 2 UMP)) 0))) ;;; The Unibus map is 16 words at 766140. It consists of 14 address bits, write-ok, and valid ;;; It controls locations 140000-177777 (2000 byte locations per page). (DEFUN SETUP-UNIBUS-MAP (UNIBUS-MAP-PAGE XBUS-ADR) (%UNIBUS-WRITE (+ 766140 (* 2 UNIBUS-MAP-PAGE)) (+ 140000 (LDB 1016 (%PHYSICAL-ADDRESS XBUS-ADR)))) (+ 140000 (* UNIBUS-MAP-PAGE 2000) (* 4 (LOGAND 377 XBUS-ADR)))) ; returns ubus-adr ;Use MT-RUN to transfer the contents of an RQB. ;Use MT-RUN-SIMPLE to do spacing operations. (DEFSIGNAL END-OF-TAPE FERROR (UNIT COMMAND BYTE-COUNT DENSITY IBM-MODE RQB) "Mag tape runs off end of tape.") (DEFVAR MT-RETRY-COUNT 5) (DEFVAR MT-ATTEMPT-TO-WRITE-WITH-EXTENDED-GAP-COUNT 3) (DEFUN MT-RUN (RQB COMMAND &OPTIONAL MINUS-BYTE-COUNT (UNIT 0) (DENSITY 0) IBM-MODE) (PROG ((RETRIES MT-RETRY-COUNT)) AGAIN (SETF (AREF RQB %MT-RQ-COMMAND) 0) (SETF (MT-COMMAND-UNIT) UNIT) (SETF (MT-COMMAND-DENSITY) DENSITY) (SETF (MT-COMMAND) COMMAND) (IF (NULL MINUS-BYTE-COUNT) (SETQ MINUS-BYTE-COUNT (MINUS (ARRAY-LENGTH (RQB-8-BIT-BUFFER RQB))))) (AS-1 MINUS-BYTE-COUNT RQB %MT-BYTE-COUNT) (AS-1 (IF IBM-MODE 1_10. 0) RQB %MT-READ) (EXECUTE-MT-RQB RQB (= COMMAND %MT-COMMAND-READ)) (COND ((MT-STATUS-EOT) (CERROR ':NO-ACTION NIL 'END-OF-TAPE "End of tape on unit ~D, command ~D, ~D bytes. Density ~S, IBM-mode ~S, rqb ~S." UNIT (NTH COMMAND MT-COMMAND-NAMES) (- MINUS-BYTE-COUNT) DENSITY IBM-MODE RQB))) (COND ((NOT (MT-STATUS-ERROR)) (RETURN T)) (T (FORMAT T "~%MAGTAPE ERROR!") (PRINT-MT-RQB RQB) (MT-RUN-SIMPLE %MT-COMMAND-SPACE-REV UNIT 1) (AND (= COMMAND %MT-COMMAND-WRITE) ( RETRIES MT-ATTEMPT-TO-WRITE-WITH-EXTENDED-GAP-COUNT) (SETQ COMMAND %MT-COMMAND-WRITE-WITH-EXTENDED-GAP)) (IF (>= (SETQ RETRIES (1- RETRIES)) 0) (GO AGAIN) (CATCH-ERROR-RESTART-EXPLICIT-IF T (MT-ERROR :RETRY "Retry magtape operation.") (FERROR 'MT-ERROR "MagTape operation failed.")) (GO AGAIN)))))) (DEFUN MT-RUN-SIMPLE (COMMAND UNIT &OPTIONAL COUNT (RQB (GET-DISK-RQB 0) DONT-RETURN-RQB)) (UNWIND-PROTECT (PROGN (IF COUNT (AS-1 (MINUS COUNT) RQB %MT-BYTE-COUNT)) (SETF (AREF RQB %MT-RQ-COMMAND) 0) (SETF (MT-COMMAND) COMMAND) (SETF (MT-COMMAND-UNIT) UNIT) (EXECUTE-MT-RQB RQB)) (OR DONT-RETURN-RQB (RETURN-DISK-RQB RQB))) T) ;Convenient spacing operations. ;Note: NTIMES fed thru to hardware. NTIMES of 0 means moby many. (DEFUN MT-SPACE (&OPTIONAL (NTIMES 1) (UNIT 0)) (MT-RUN-SIMPLE %MT-COMMAND-SPACE-FOR UNIT NTIMES)) (DEFUN MT-SPACE-TO-EOF (&OPTIONAL (UNIT 0) (NTIMES 1)) (DOTIMES (C NTIMES) (MT-SPACE 0 UNIT))) (DEFUN MT-SPACE-REV (&OPTIONAL (NTIMES 1) (UNIT 0)) (DOTIMES (I NTIMES) (MT-RUN-SIMPLE %MT-COMMAND-SPACE-REV UNIT 1))) ;; Reverse through the tape, positioning the tape at the beginning of a file. ;; If SKIP-N-BLOCKS is 0, this positions the tape at the beginning of this file. ;; If SKIP-N-BLOCKS is 1, this positions the tape at the beginning of the previous file, etc. ;; If this reaches the beginning of the tape prematurely, it stops there and returns NIL. (DEFUN MT-SPACE-REV-TO-BOF (&OPTIONAL (UNIT 0) (SKIP-N-FILES 0) &AUX RQB) (UNWIND-PROTECT (PROG () (SETQ RQB (GET-DISK-RQB 0)) L (MT-RUN-SIMPLE %MT-COMMAND-SPACE-REV UNIT 1 RQB) (COND ((MT-STATUS-EOF) (COND ((ZEROP SKIP-N-FILES) ;; If we stop at an EOF block, we must space forward over it. (MT-RUN-SIMPLE %MT-COMMAND-SPACE-FOR UNIT 1 RQB) (RETURN T))) (DECF SKIP-N-FILES)) ((MT-STATUS-BOT) (RETURN (ZEROP SKIP-N-FILES)))) (GO L)) (RETURN-DISK-RQB RQB))) ;; This function attempts to bypass all files on the tape until two ;; consecutive EOFs are found, then positions the tape over the last EOF. ;; The tape is now in a configuration allowing one to append new files. (DEFUN MT-SPACE-TO-APPEND (&OPTIONAL (UNIT 0) &AUX RQB) (UNWIND-PROTECT (PROG ((EOF T)) (SETQ RQB (GET-DISK-RQB 0)) L (MT-RUN-SIMPLE %MT-COMMAND-SPACE-FOR UNIT 1 RQB) (IF (MT-STATUS-EOF) (IF (NOT EOF) (SETQ EOF T) (MT-RUN-SIMPLE %MT-COMMAND-SPACE-REV UNIT 1 RQB) (RETURN T)) (SETQ EOF NIL)) ;; MT-RUN-SIMPLE doesn't have this.. (IF (MT-STATUS-EOT) (CERROR ':NO-ACTION NIL 'END-OF-TAPE "End of tape on unit ~D, command ~D, ~D bytes. Density ~S, IBM-mode ~S, rqb ~S." UNIT '%MT-COMMAND-SPACE-FOR 1 0 NIL RQB)) (GO L)) (RETURN-DISK-RQB RQB)) T) (DEFUN MT-REWIND (&OPTIONAL (UNIT 0)) (MT-RUN-SIMPLE %MT-COMMAND-REWIND UNIT)) (DEFUN MT-WRITE-EOF (&OPTIONAL (UNIT 0)) (MT-RUN-SIMPLE %MT-COMMAND-WRITE-EOF UNIT)) (DEFUN MT-UNLOAD (&OPTIONAL (UNIT 0)) (MT-RUN-SIMPLE %MT-COMMAND-OFFLINE UNIT)) (DEFUN MT-OFFLINE (&OPTIONAL (UNIT 0)) (MT-RUN-SIMPLE %MT-COMMAND-OFFLINE UNIT)) ;; Standard End of Tape handlers ;; This one is useful when you have transporting things which are bigger than ;; a tape. it just rewinds, lets you reload, and continues. ;; Install it as a handler for END-OF-TAPE, using CONDITION-BIND. (DEFUN CONTINUING-MT-EOT-HANDLER (CONDITION &AUX (UNIT (SEND CONDITION ':UNIT))) (PROG ((STREAM ERROR-OUTPUT)) (MT-REWIND UNIT) (FUNCALL STREAM ':BEEP) (FORMAT STREAM "~%>>> MagTape unit ~D reached end of tape <<<~%" UNIT) (MT-OFFLINE UNIT) ;This will wait... L (FORMAT STREAM "Please type [Resume] to continue tape operation: ") (FUNCALL STREAM ':CLEAR-INPUT) (COND ((NOT (CHAR-EQUAL (FUNCALL STREAM ':TYI) #\RESUME)) (FUNCALL STREAM ':BEEP) (FUNCALL STREAM ':TYO #\CR) (GO L))) (FORMAT STREAM "[Resuming tape operation]~%") (RETURN ':NO-ACTION)))