;;; -*- Mode:LISP; Package:FILE-SYSTEM; Base:8; Readtable:ZL -*- ;;; ;;;Copyright LISP Machine, Inc. 1985 ;;; See filename "Copyright.Text" for ;;;licensing and release information. ;;; ;;; This file has been hacked to contain only those functions ;;; specific to the new lambda lambda tape software -dg 2/3/86 ;;; Now this file is used for both the cadr and lambda. ;;; Most of the functions in the file should not be called ;;; on the lambda. When they do direct unibus operations, ;;; I just left them alone, and they will get illegal instruction ;;; traps. In a few cases, I've made a function work on both ;;; machines (e.g. mt-rewind) ;;; 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. (DEFVAR *DEFAULT-RECORD-SIZE* #o10000 "The default number of bytes in a magtape record.") (DEFVAR *MT-EOT-HANDLER* () "Called on EOT by SOME functions. You should use something like CONDITION-BIND.") (DEFVAR FILE-SYSTEM-PACKAGE (PKG-FIND-PACKAGE "FS")) (DEFVAR PAGE-SIZE-IN-BYTES (* PAGE-SIZE 4.)) ;8 bit bytes. (DEFMACRO LAMBDA-ONLY () `(WHEN ( SI:PROCESSOR-TYPE-CODE SI:LAMBDA-TYPE-CODE) (FERROR NIL "this function is LAMBDA-specific"))) ;; 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-modofied) (let* ((lo (%pointer-plus (%pointer rqb) (si:array-data-offset rqb))) (hi (%pointer-plus lo (ceiling (array-length rqb) 2)))) (do ((loc (logand lo (- page-size)) (%pointer-plus loc page-size))) ((>= (%pointer-difference loc hi) 0)) (si:%wire-page loc wire-p set-modofied)))) ;(DEFUN WIRE-MT-RQB (RQB &OPTIONAL (WIRE-P T) SET-MODIFIED ; &AUX (LONG-ARRAY-FLAG (%P-LDB %%ARRAY-LONG-LENGTH-FLAG RQB)) ; (LOW (%POINTER-DIFFERENCE (%POINTER RQB) ; (%POINTER-PLUS (ARRAY-DIMENSION RQB 0) 2))) ; (HIGH (%POINTER-PLUS (%POINTER RQB) ; (%POINTER-PLUS 1 ; (%POINTER-PLUS LONG-ARRAY-FLAG ; (FLOOR (ARRAY-LENGTH RQB) 2)))))) ; (DO LOC (LOGAND LOW (- PAGE-SIZE)) (%POINTER-PLUS LOC PAGE-SIZE) ; (>= (%POINTER-DIFFERENCE HIGH LOC) 0) ; (SI:%WIRE-PAGE LOC WIRE-P SET-MODIFIED))) (DEFUN UNWIRE-MT-RQB (RQB) (WIRE-MT-RQB RQB NIL)) (DEFUN SIGN-EXTEND-16 (X) (IF (ZEROP (LOGAND 100000 X)) X (LOGIOR X -100000))) (defflavor tape-error () ;This should be used as the canonical error type (ferror)) ;for all types of device specific tape error flavors. ;See SYS:TAPE;LQUART for details of use (DEFFLAVOR QUART-ERROR... (defsignal no-tape tape-error () "The tape is not mounted in the tape drive") (defsignal write-protected tape-error () "The tape in the tape drive is write protected.") (defsignal no-drive tape-error () "The selected tape drive does not seem to exist or is powered down." ) (defsignal end-of-tape tape-error (unit command byte-count density ibm-mode rqb) "Mag tape runs off end of tape.") (defsignal beginning-of-tape tape-error () "Tape drive encountered the logical beginning-of-tape (BOT).") (DEFVAR MT-RETRY-COUNT 5) (DEFVAR MT-ATTEMPT-TO-WRITE-WITH-EXTENDED-GAP-COUNT 3) ;; Convenient spacing operations. ;; Note: NTIMES fed thru to hardware. NTIMES of 0 means moby many. (DEFUN MT-SPACE (&OPTIONAL (NTIMES 1) (UNIT 0)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (send dev :space ntimes)))) (DEFUN MT-SPACE-TO-EOF (&OPTIONAL (N-FILES 1) (UNIT 0)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (dotimes (c n-files) (send dev :search-filemark 1))))) (DEFUN MT-SPACE-REV (&OPTIONAL (NTIMES 1) (UNIT 0)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (send dev :space-reverse ntimes)))) ;; 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 (SKIP-N-FILES 0) (UNIT 0)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (condition-case () (send tape:*selected-device* :search-filemark-reverse 1) (tape:physical-beginning-of-tape)) (unless (zerop skip-n-files) (send tape:*selected-device* :previous-file))))) ;; 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)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (send tape:*selected-device* :search-filemark 2)))) (DEFUN MT-REWIND (&OPTIONAL (UNIT 0)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (send tape:*selected-device* :rewind)))) (DEFUN MT-RESET () (tape:with-device-locked tape:*selected-device* (send tape:*selected-device* :reset))) (defun tm-init () (tv:beep) (format t "~&This function is obsolete. Read the new tape documentation.") (mt-reset)) (compiler:make-obsolete tm-init "Read the new tape documentation") (defun tm-rewind () (tv:beep) (format t "~&This function is obsolete. Read the new tape documentation.") (mt-rewind)) (compiler:make-obsolete tm-rewind "Read the new tape documentation") (defun tm-unload () (tv:beep) (format t "~&This function is obsolete. Read the new tape documentation.") (mt-unload)) (compiler:make-obsolete tm-unload "Read the new tape documentation") (DEFUN MT-WRITE-EOF (&OPTIONAL (UNIT 0)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (send tape:*selected-format* :finish-tape dev)))) (DEFUN MT-UNLOAD (&OPTIONAL (UNIT 0)) (tape:using-device (dev tape:*selected-device* `(:unit ,unit)) (tape:with-device-locked dev (send tape:*selected-device* :unload)))) (deff MT-OFFLINE 'mt-unload) ;; 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)))