;;; -*- Mode:LISP; Package:LAMBDA; Base:8; Readtable:ZL -*- ;;; Copyright LISP Machine, Inc. 1986 ;;; See filename "Copyright.Text" for ;;; licensing and release information. (defvar nupi-quad-slot #xf2) (defvar nupi-debug-command-block-address (+ #xf4000000 (* 440 4))) (defvar nupi-debug-special-event-location (+ nupi-debug-command-block-address (* 4 8))) (defvar nupi-debug-data-scratch-block #xf4000000) (defun read-nupi-config-reg () (bus-read (dpb nupi-quad-slot (byte 8 24.) #xe0000b))) (defun write-nupi-config-reg (data) (bus-write (dpb nupi-quad-slot (byte 8 24.) #xe0000b) data)) (defun print-nupi-config (&optional (data (read-nupi-config-reg))) (format t "~&RESET ~s" (ldb (byte 1 0) data)) (format t "~&Enable Bus Master ~s" (ldb (byte 1 1) data)) (format t "~&Fault LED ~s" (ldb (byte 1 2) data)) (format t "~&System bus test ~s" (ldb (byte 1 3) data)) (format t "~&Reserved ~s" (ldb (byte 4 4) data)) (format t "~&Failure Override ~s" (ldb (byte 1 8) data)) (format t "~&Undefined ~s" (ldb (byte 7 9) data))) (defun enable-nupi-bus-master () (write-nupi-config-reg (dpb 1 (byte 1 1) (read-nupi-config-reg)))) ;NUPI command block ; ; off in words n-bytes ; 0 1 unit-select ; 0 1 spare ; 0 1 options ; 0 1 command ; 1 4 returned status ; 2 4 buffer pointer or param list pointer ; 3 4 transfer count (in bytes) (must be multiple of 4) ; 4 4 device block address ; 5 4 interrupt address ; 6 4 reserved ; 7 4 reserved (defconst nupi-commands '((#x00 "illegal") (#x41 "formatter set up") (#x81 "NUPI set up") (#x02 "Request device status") (#x42 "Request Formatter Status") (#x82 "Request NUPI Status") (#x10 "Restore Device") (#x11 "Seek") (#x12 "Read") (#x13 "Write") (#x14 "Format") (#x15 "Read to NUPI Buffer") (#x16 "NUPI Buffer to Nubus Transfer") (#x17 "Swap NUPI Buffer and Write") (#x20 "Rewind (tape)") (#x21 "Unload (tape)") (#x22 "Erase (tape)") (#x23 "Space forward (tape)") (#x25 "Write Filemark (tape)") (#x26 "Tape retension") (#x27 "Space forward by filemarks") (#x29 "Skip forward to end of data") (#x2a "Load") (#x2b "Load/unload cmd with bit params") (#x30 "Device selftest") (#x70 "Formatter selftest") (#xb0 "NUPI selftest") (#x71 "SCSI pass through read") (#x72 "SCSI pass through write") )) (defconst nupi-error-classes '("no error" "self test error" "attention error" "bus related error" "command error" "hardware error" "media error" "reserved error")) (defconst nupi-controller-errors '((#x61 "nubus time out") (#x62 "nubus bus error") (#x63 "scsi bus parity error") (#x64 "formatter busy") (#x65 "rate error") (#x66 "bus error trap") (#x81 "command aborted") (#x82 "invalid command") (#x83 "invalid parameter") (#x84 "scsi command completed without data transfer") (#x8c "attempted read-and-hold with one pending") (#x8d "attempeted write-and-swap without valid buffer") (#xa1 "illegal interrupt") (#xa2 "scsi function complete without cause") (#xa3 "timeout on NCR 5385 data register full wait") (#xa4 "scsi invalid command interrupt") (#xa6 "hardware error trap") (#xa7 "queue overflow") (#xa8 "address error trap") (#xa9 "illegal instruction error trap") (#xaa "nubus dma locked up") )) (defconst nupi-device-errors '((#x41 "no selected unit") (#x42 "media not loaded") (#x43 "write protected") (#x44 "offline device now online or media change") (#x46 "temperature fault") (#x47 "invalid media type") (#x48 "status: scsi sense data available") (#x49 "status: tape incorrect length indicate") (#x4a "tape end of media") (#x4b "status: tape incorrect length indicate and end of media") (#x4c "status: tape file mark detected") (#x4d "status: tape incorrect length indicate and file mark detected") (#x4e "status: tape end of media and file mark detected") (#x4f "status: tape incorrect length indicate, end of media, and file mark detected") (#x50 "scsi bus hung needs hardware reset") (#x61 "scsi bus parity error") (#x62 "drive not ready") (#x63 "rate error") (#x64 "invalid scsi interrupt: selected") (#x65 "device offline") (#x66 "invalid scsi testability interrupt") (#x67 "invalid scsi disconnect") (#x68 "invalid mode for scsi status") (#x69 "invalid mode for scsi command byte request") (#x6a "sequence error: scsi completion address") (#x6b "sequence error: scsi requested data") (#x6c "sequence error: dma start/stop address") (#x70 "unknown message received from formatter") (#x71 "invalid mode on scsi message in") (#x72 "excess scsi status") (#x73 "excess scsi command bytes requested") (#x74 "expected scsi restore message but note received") (#x75 "reconnected to unit not waiting for it") (#x76 "expected scsi cmd complete msg; did not receive it") (#x77 "illegal scsi message for reconnected state") (#x78 "reselected without valid scsi id") (#x79 "invalid mode on scsi message out") (#x7a "invalid mode on scsi data transfer") (#x81 "command aborted") (#x82 "invalid command") (#x83 "invalid parameter") (#x84 "illegal block address") (#x85 "volume overflow") (#x8a "formatter failed to connect to scsi bus") (#x8e "unknown error code feturned from the formatter") (#xa1 "missing index signal") (#xa2 "no seek complete") (#xa3 "write fault") (#xa4 "track 0 not found") (#xa5 "multiple units selected") (#xa6 "seek error") (#xa7 "formatter hardware error") (#xc1 "id error") (#xc2 "uncorrectable data error") (#xc3 "id address mark not found") (#xc4 "data address mark not found") (#xc5 "block not found (sector address)") (#xc6 "bad block not found") (#xc7 "format error") (#xc8 "corrrectable data check") (#xc9 "interleave error") (#xca "media error"))) (defun print-exp-command-block () (print-nupi-command-block #xf4000680)) (defun print-nupi-command-block (&optional (adr nupi-debug-command-block-address)) (let ((command-word (bus-read adr)) (status (bus-read (+ adr 4))) (parameter-list (bus-read (+ adr 8))) (transfer-count (bus-read (+ adr 12.))) (device-address (bus-read (+ adr 16.))) (interrupt-address (bus-read (+ adr 20.))) (reserved-1 (bus-read (+ adr 24.))) (reserved-2 (bus-read (+ adr 28.))) ) (format t "~&Unit ~s" (ldb (byte 8 0) command-word)) (format t "~&Spare ~s" (ldb (byte 8 8) command-word)) (format t "~&Options ~s" (ldb (byte 8 16.) command-word)) (if (ldb-test (byte 1 20.) command-word) (format t " Swap-partial-completion-interrupt")) (if (ldb-test (byte 1 21.) command-word) (format t " device-address-is-physical")) (if (ldb-test (byte 1 22.) command-word) (format t " SCATTER")) (if (ldb-test (byte 1 23.) command-word) (format t " Interrupt-enable")) (format t "~&Command #x~16r ~a" (ldb (byte 8 24.) command-word) (cadr (assq (ldb (byte 8 24.) command-word) nupi-commands))) (format t "~&Status ~s" status) (format t "~& Busy ~s" (ldb (byte 1 31.) status)) (format t "~& Complete ~s" (ldb (byte 1 30.) status)) (format t "~& Error ~s" (ldb (byte 1 29.) status)) (format t "~& Retries required ~s" (ldb (byte 1 28.) status)) (format t "~& Aux status available ~s" (ldb (byte 1 27.) status)) (format t "~& Paging partial completion ~s" (ldb (byte 1 26.) status)) (format t "~& spare ~s" (ldb (byte 2 24.) status)) (let ((error (ldb (byte 8 16.) status))) (format t "~& controller error #x~x" error) (when (not (zerop error)) (format t " Class: /"~a/"" (nth (ldb (byte 3 21.) status) nupi-error-classes)) (format t " ~a" (cadr (assq error nupi-controller-errors))) )) (let ((error (ldb (byte 8 8) status))) (format t "~& device error ~s" error) (when (not (zerop error)) (format t " Class /"~a/"" (nth (ldb (byte 3 13.) status) nupi-error-classes)) (format t " ~a " (cadr (assq error nupi-device-errors))) )) (format t "~& spare ~s" (ldb (byte 3 5) status)) (format t "~& ECC applied ~s" (ldb (byte 1 4) status)) (format t "~& n-retries ~s" (ldb (byte 3 0) status)) (format t "~¶meter-list #x~16r" parameter-list) (format t "~&Transfer count ~d." transfer-count) (format t "~&Device block address ~s" device-address) (format t "~&Interrupt address #x~16r" interrupt-address) (format t "~&Reserved ~s ~s" reserved-1 reserved-2))) (defun make-nupi-command-block (nubus-address command options unit-select parameter-list-pointer transfer-count device-block-address interrupt-address ) (bus-write nubus-address (+ unit-select (ash options 16.) (ash command 24.))) (bus-write (+ nubus-address 4) 0) ;status (bus-write (+ nubus-address 8) parameter-list-pointer) (bus-write (+ nubus-address 12.) transfer-count) (bus-write (+ nubus-address 16.) device-block-address) (bus-write (+ nubus-address 20.) interrupt-address) (bus-write (+ nubus-address 24.) 0) (bus-write (+ nubus-address 28.) 0)) (defun read-nupi-extended-status () (make-nupi-command-block nupi-debug-command-block-address #x82 0 0 nupi-debug-data-scratch-block (* (+ 21. 2) 4) 0 0) (execute-nupi-command nupi-debug-command-block-address) (wait-for-nupi-command-complete)) (defun print-nupi-extended-status (&optional verbose) (read-nupi-extended-status) (let ((data (bus-read nupi-debug-data-scratch-block))) (format t "~&NUPI flags ~s " data) (if (ldb-test (byte 1 0) data) (format t "~& nubus error fetching command block")) (if (ldb-test (byte 1 1) data) (format t "~& overtemperature in brick")) (if (ldb-test (byte 1 2) data) (format t "~& illegal nubus access to NUPI")) (if (ldb-test (byte 1 3) data) (format t "~& Multiple commands sent illegally")) (if (ldb-test (byte 1 4) data) (format t "~& Illegal command or command block")) (if (ldb-test (byte 1 5) data) (format t "~& power fail")) (if (ldb-test (byte 1 6) data) (format t "~& command aborted with no nubus command block updates")) (if (ldb-test (byte 1 7) data) (format t "~& Nubus interrupt taken without cause")) (if (ldb-test (byte 1 8) data) (format t "~& invalid special event interrupt address")) (if (ldb-test (byte 1 9) data) (format t "~& NUPI hardware or software error")) (if (ldb-test (byte 1 10.) data) (format t "~& invalid scsi bus operation")) (if (not (zerop (ldb (byte 20. 11.) data))) (format t "~& Spares: ~s" (ldb (byte 5 11.) data))) (if (ldb-test (byte 1 31.) data) (format t "~& NUPI has buffer"))) (when verbose (format t "~&Last self test data ~s" (bus-read (+ nupi-debug-data-scratch-block 4))) (flet ((convert (n) (if (< n 5) n (1+ n)))) (dotimes (n 21.) (if (< n 7) (format t "~&Formatter ~d" (convert n)) (format t "~&Formatter ~d Unit ~d" (convert (truncate (- n 7) 2)) (ldb (byte 1 0) (- n 7)))) (describe-scsi-extended-status (bus-read (+ nupi-debug-data-scratch-block 8 (* n 4)))))) )) (deff nupi-status 'print-nupi-extended-status) (defun describe-scsi-extended-status (data) (format t "~& Device type ~a" (nth (ldb (byte 3 29.) data) '("unknown" "quarter inch tape" "disk" "printer" "write once optical disk" "read only optical disk" "floppy" "undefined"))) (format t "~& Offline ~s" (ldb (byte 1 28.) data)) (format t "~& error status available ~s" (ldb (byte 1 27.) data)) (format t "~& self test failed ~s" (ldb (byte 1 26.) data)) (format t "~& overtemperature ~s" (ldb (byte 1 25.) data)) (format t "~& write protected ~s" (ldb (byte 1 24.) data)) (format t "~& indeterminate device status ~s" (ldb (byte 1 23.) data)) (format t "~& unit attention (newly online or media change) ~s" (ldb (byte 1 22.) data)) (format t "~& not ready ~s" (ldb (byte 1 21.) data)) (format t "~& reserved ~s" (ldb (byte 5 16.) data)) (format t "~& last command ~16r ~a" (ldb (byte 8 8) data) (cadr (assq (ldb (byte 8 8) data) nupi-commands))) (format t "~& last options ~s" (ldb (byte 8 0) data))) (defun execute-nupi-command (&optional (nubus-address nupi-debug-command-block-address)) (bus-write nupi-debug-special-event-location 0) (bus-write (dpb nupi-quad-slot (byte 8 24.) #xe00004) nubus-address)) (defun wait-for-nupi-command-complete (&optional (adr nupi-debug-command-block-address) (check-for-error t)) (let ((status 0) (special-event 0)) (do ((end-time (%pointer-plus (time) (* 60. 5)))) ((or (ldb-test (byte 1 30.) status) (not (zerop special-event)))) (if (time-lessp end-time (time)) (ferror nil "disk timeout")) (setq status (bus-read (+ adr 4))) (setq special-event (bus-read nupi-debug-special-event-location)) ) (when check-for-error (cond ((ldb-test (byte 1 29.) status) (cerror :no-action nil nil "error in command block")) ((not (zerop special-event)) (cerror :no-action nil nil "error in command block (special status available)")))) ) ) ;returns a list of fixnums suitable as unit arguments ; (byte 3 0) is unit number (only 0 and 1 supported) ; (byte 3 3) is formatter number (0 - 7 except 5) ; (byte 2 6) unused (defun find-nupi-disks (&aux result) ;skip first word - just status stuff ;skip second word - self test stuff ;skip next 7 - formatter status (read-nupi-extended-status) (dotimes (i 14.) (flet ((convert (n) (if (< n 5) n (1+ n)))) (let ((status (bus-read (+ nupi-debug-data-scratch-block (* 9 4) (* i 4))))) (cond ((and (= (ldb (byte 3 29.) status) 2) ;type disk (= (ldb (byte 1 28.) status) 0)) ;offline = false (push (dpb (convert (floor i 2)) (byte 3 3) (ldb (byte 1 0) i)) result)))))) (reverse result)) (defun nupi-read (unit logical-block phys-page n-blocks) (make-nupi-command-block nupi-debug-command-block-address #x12 0 unit (ash (cadr-page-to-nubus-page phys-page) 10.) (* n-blocks 1024.) logical-block 0) (execute-nupi-command) (wait-for-nupi-command-complete) ) (defun nupi-write (unit logical-block phys-page n-blocks) (make-nupi-command-block nupi-debug-command-block-address #x13 0 unit (ash (cadr-page-to-nubus-page phys-page) 10.) (* n-blocks 1024.) logical-block 0) (execute-nupi-command) (wait-for-nupi-command-complete) ) (defun nupi-reset () (bus-write nupi-quad-slot #xe0000b 1)) (defun nupi-setup () (bus-write nupi-debug-special-event-location 0) (bus-write nupi-debug-data-scratch-block nupi-debug-special-event-location) (make-nupi-command-block nupi-debug-command-block-address #x81 0 0 nupi-debug-data-scratch-block 4 0 0) (execute-nupi-command) (wait-for-nupi-command-complete)) ;--- ;(defun exp-disk-init () ; ;this usually figures out the disk parameters, but we can only use ; ;logical block numbers with the NUPI anyway... ; ; (setq lam-disk-type t) ; ) ;(defun exp-disk-write (&rest ignore) ; (ferror nil "this has never been tested") ; nil) ;(defun exp-disk-read (logical-block phys-page n-blocks) ; (declare (special si:lam-disk-unit)) ; (nupi-read si:lam-disk-unit logical-block phys-page n-blocks))