;-*- mode: lisp; base: 8; readtable: ZL -*- ; ** (c) Copyright 1983 Lisp Machine Inc ** (DEFCONST UC-LAMBDA-DISK '( (locality a-mem) a-active-iopb (0) (locality i-mem) ;Routines to be reimplemented for each disk controller: ; ; start-disk-op (and start-disk-op-1, start-disk-op-2) ; await-disk ; disk-completion-get-status ;;; Here to perform a disk swapping operation. ;;; M-A has the virtual memory address, M-T has the command. ;;; M-B is no longer an argument at this level. ;;; The CCW is already set up starting at location in M-C. M-C, M-T bashed. ;;; Returns with operation successfully completed. ;m-tem4 has transfer size in pages. If fast cache swapin on, this is used by hexadec ;ager. DISK-SWAP-HANDLER (CALL-XCT-NEXT DISK-PGF-SAVE) ((A-DISK-IDLE-TIME) M-ZERO) ;I use the disk ((M-1) VMA-PAGE-ADDR-PART M-A) ;Convert virtual address to disk address (CALL-GREATER-OR-EQUAL M-1 A-DISK-MAXIMUM ILLOP) ;Address out of bounds ((M-1) ADD M-1 A-DISK-OFFSET) ;Relocate to appropriate part of disk ((m-tem) a-disk-page-unit) ((m-1) dpb m-tem (byte-field 8 24.) a-1) ((a-disk-transfer-size) m-tem4) (CALL START-DISK-SWAP) ;Start the disk operation ;; Turn run light off, saving old value on stack. ((vma-start-read m-t) add vma (a-constant 2)) (check-page-read-map-reload-only) ((pdl-push) md) ((md-start-write) m-zero) (check-page-write-map-reload-only) (CALL READ-MICROSECOND-CLOCK) ;Read microsecond clock into M-2 #-lambda(begin-comment) ((M-TEM) A-PROCESSOR-SWITCHES) (JUMP-IF-BIT-SET (BYTE-FIELD 1 4) M-TEM DS-HEXA-AGER) #-lambda(end-comment) ((M-1) A-AGING-SCAN-POINTER) ;Run Ager while in disk wait (CALL-NOT-EQUAL M-1 A-FINDCORE-SCAN-POINTER AGER) #+lambda ds-hexa-ager-return ;; Scanning pages on swapout to control volatilities, see comment in UC-SCAVENGER. ; ((q-r) a-disk-read-write) ; (call-equal q-r (a-constant disk-write-command) volatility-scan-pages) (CALL AWAIT-DISK) ;Now wait for operation to complete (CALL-XCT-NEXT READ-MICROSECOND-CLOCK) ;Get current time ((M-1) M-2) ;but save old time ((M-2) SUB M-2 A-1) ;Get delta time ((A-DISK-WAIT-TIME) ADD M-2 A-DISK-WAIT-TIME) ;Increment wait time counter ;; Restore run light to previous value. ((md) pdl-pop) ((vma-start-write) m-t) (check-page-write-map-reload-only) (JUMP DISK-PGF-RESTORE) #-lambda(begin-comment) ds-hexa-ager ((m-5) ldb (byte-field 4 8) m-a) ds-ha-0 (call load-scan-for-hexadec) ((m-1) a-aging-scan-pointer) (call-not-equal m-1 a-findcore-scan-pointer ager) (call store-scan-for-hexadec) ((m-tem4) sub m-tem4 (a-constant 1)) (jump-equal m-tem4 a-zero ds-hexa-ager-return) ((m-5) add m-5 (a-constant 1)) (jump-xct-next ds-ha-0) ((m-5) ldb (byte-field 4 0) m-5) #-lambda(end-comment) ;volatility-scan-pages ; ((pdl-push) m-a) ; ((pdl-push) a-disk-transfer-size) ; ;; Round down to bottom of page. ; ((m-a) dpb m-zero (byte 8 0) a-a) ;volatility-scan-loop ; (jump-equal m-zero a-disk-transfer-size volatility-scan-done) ; (call-xct-next volatility-scan-page) ; ((vma) m-a) ; ((m-a) add m-a (a-constant 400)) ; ((a-disk-transfer-size) add m-minus-one a-disk-transfer-size) ; (jump volatility-scan-loop) ;volatility-scan-done ; (popj-after-next ; (a-disk-transfer-size) pdl-pop) ; ((m-a) pdl-pop) ;;; Here to start a disk operation, first waiting for the disk to become idle. ;;; M-1 has the disk address, M-T has the command. ;;; The CLP is already built and is in M-C. M-T, M-C, M-1, M-2 bashed. ;;; Multiple pages can be transfered to consecutive pages on the disk, as ;;; per the CCW list. Returns with A-DISK-RUN-LIGHT in VMA. START-DISK-SWAP (CALL AWAIT-DISK) ;Wait until disk is idle ((A-DISK-READ-WRITE) M-T) ;Then store parameters into A-memory ((A-DISK-CLP) M-C) ((A-DISK-RETRY-STATE) M-ZERO) (call convert-m-1-to-a-disk-address) (JUMP-XCT-NEXT START-DISK-OP) ((A-DISK-RESERVED-FOR-USER) (A-CONSTANT 0)) ;Not any more, it isn't! ;;; Here to start a disk operation, first waiting for the disk to become idle. ;;; M-1 has the disk address, M-B has the page frame number of the first main ;;; memory page to transfer (if sign bit set, M-B has NUBUS physical page). ;;; this is only used when flushing the METER buffer ;;; M-T has the command. ;;; The CLP is always 777 . M-T, M-C, M-1, M-2 bashed. ;;; Returns with A-DISK-RUN-LIGHT in VMA. START-DISK-1-PAGE ((M-2) (A-CONSTANT 1)) ;Transfer just one page ((M-C) (A-CONSTANT #+lambda 777 #+exp 776)) ;CLP is always 777 ;;; M-1 starting disk address, M-B starting main memory page frame number (if sign set, ;;; as above, but if more than one page, it will be consecutive PHYSICAL NUBUS pages). ;;; M-2 number of pages to transfer, M-T command, M-C address of CCW list. ;;; Bashes M-T, M-1, M-2. Returns with A-DISK-RUN-LIGHT in VMA. START-DISK-N-PAGES (CALL AWAIT-DISK) ;Wait until disk is idle ((A-DISK-READ-WRITE) M-T) ;Then store parameters into A-memory ((A-DISK-CLP) M-C) ((A-DISK-RETRY-STATE) M-ZERO) ((a-disk-transfer-size) m-2) ((M-T) M-2) (call convert-m-1-to-a-disk-address) ;; Now build the CCW list #-lambda(begin-comment) ((VMA) ADD (M-CONSTANT -1) A-DISK-CLP) ((MD) DPB M-B VMA-PHYS-PAGE-ADDR-PART (A-CONSTANT 1)) (jump-if-bit-clear (byte-field 1 31.) m-b build-ccw-list-1) ((md) dpb m-b (byte-field 22. 8) (a-constant (plus (byte-mask (byte-field 1 31.)) 1))) ;NUBUS physical page to ;NUBUS word address. BUILD-CCW-LIST-1 (JUMP-GREATER-THAN M-T (A-CONSTANT 1) BUILD-CCW-LIST-2) ((MD) SUB MD (A-CONSTANT 1)) ;last BUILD-CCW-LIST-2 ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) (CHECK-PAGE-WRITE-NO-INTERRUPT) ((M-T) SUB M-T (A-CONSTANT 1)) (JUMP-GREATER-THAN-XCT-NEXT M-T (A-CONSTANT 0) BUILD-CCW-LIST-1) ((MD) ADD MD (A-CONSTANT (EVAL PAGE-SIZE))) #-lambda(end-comment) #-exp(begin-comment) ((vma) a-disk-clp) (jump-if-bit-set (byte-field 1 31.) m-b exp-build-physical-ccw-list) ((m-tem1) dpb m-b vma-phys-page-addr-part a-zero) ;convert page frame to cadr-physical build-ccw-list-1 ((m-tem2) m-t) ((m-t) m-tem1) (call translate-cadr-physical-to-nubus) ((m-t) m-tem2) ((md-start-write) m-lam) (illop-if-page-fault) ((md) (a-constant 1024.)) ((vma-start-write) add vma (a-constant 1)) (illop-if-page-fault) ((vma) add vma (a-constant 1)) ((m-t) sub m-t (a-constant 1)) ((m-tem1) add m-tem1 (a-constant (eval page-size))) (jump-greater-than m-t a-zero build-ccw-list-1) (jump ccw-list-done) exp-build-physical-ccw-list ((m-tem1) dpb m-b (byte-field 22. 10.) a-zero) ;nubus page to nubus address build-phys-ccw-list-1 ((md-start-write) m-tem1) (illop-if-page-fault) ((md) (a-constant 1024.)) ((vma-start-write) add vma (a-constant 1)) (illop-if-page-fault) ((vma) add vma (a-constant 1)) ((m-t) sub m-t (a-constant 1)) ((m-tem1) add m-tem1 (a-constant 1024.)) (jump-greater-than m-t a-zero build-phys-ccw-list-1) ccw-list-done #-exp(end-comment) ((A-DISK-RESERVED-FOR-USER) (A-CONSTANT 0)) ;Not any more, it isn't! (jump start-disk-op) DISK-COMPLETION-MAIN-PROGRAM ;simulate interrupt level re register saving, then call ; disk-completion ((A-INTR-VMA) VMA) ((A-INTR-MD) MD) ((A-INTR-A) M-A) ((A-INTR-B) M-B) ((A-INTR-T) M-T) (CALL DISK-COMPLETION) ((MD) A-INTR-MD) ((VMA) A-INTR-VMA) ((M-T) A-INTR-T) (POPJ-AFTER-NEXT (M-B) A-INTR-B) ((M-A) A-INTR-A) ;;; Disk completion handler - called from XBUS interrupt handler, status in MD on CADR only. ;;; The following registers may be clobbered ;;; M-A, M-B, M-T ;;; M-TEM, A-TEM1, A-TEM2, A-TEM3 ;;; DISPATCH-CONSTANT, Q-R, VMA, MD DISK-COMPLETION (CALL DISK-COMPLETION-GET-STATUS) ;return status in M-A (JUMP-NOT-EQUAL M-ZERO A-DISK-DOING-READ-COMPARE DISK-COMPLETION-READ-COMPARE-OVER) (JUMP-NOT-EQUAL M-A A-ZERO DISK-COMPLETION-ERROR) ;set up to go back to start-disk-op-1 if you want to do read compare's... DISK-COMPLETION-OK ;; Here when a disk operation has successfully completed ((MD) M-ZERO) ;Turn off disk run light ((VMA-START-WRITE) A-DISK-RUN-LIGHT) (CHECK-PAGE-WRITE-NO-INTERRUPT) ((A-DISK-BUSY) M-ZERO) (POPJ) ; (POPJ-AFTER-NEXT (VMA-START-WRITE) A-DISK-REGS-BASE) ;Clear interrupt enable *** ; (CHECK-PAGE-WRITE-NO-INTERRUPT) DISK-COMPLETION-READ-COMPARE-OVER (CALL ILLOP) DISK-COMPLETION-ERROR ((A-DISK-ERROR-COUNT) M+A+1 M-ZERO A-DISK-ERROR-COUNT) (CALL LOG-DISK-ERROR) (call illop) ;fix use of a-disk-transfer-size before removing this (JUMP START-DISK-OP-1) ;;; Log a disk error for later analysis by macrocode or console program LOG-DISK-ERROR (declare (clobbers a-tem)) ((M-TEM) A-DISK-CLP) ((MD) DPB M-TEM (BYTE-FIELD 20 20) A-DISK-COMMAND) ((VMA-START-WRITE) A-DISK-ERROR-LOG-POINTER) (ILLOP-IF-PAGE-FAULT) ((MD) A-DISK-FINAL-ADDRESS) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) (ILLOP-IF-PAGE-FAULT) ((MD) A-DISK-STATUS) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) (ILLOP-IF-PAGE-FAULT) ((MD) A-DISK-MA) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) (ILLOP-IF-PAGE-FAULT) (POPJ-LESS-THAN-XCT-NEXT VMA (A-CONSTANT 637)) ((A-DISK-ERROR-LOG-POINTER) ADD VMA (A-CONSTANT 1)) (POPJ-AFTER-NEXT (A-DISK-ERROR-LOG-POINTER) (A-CONSTANT 600)) (NO-OP) ;;; Support for "user" disk I/O ;;; Note that the interrupt-enable bit in the command word controls ;;; whether or not system error recovery features are invoked. #-lambda(begin-comment) XDSKOP (MISC-INST-ENTRY %DISK-OP) #+exp (call illop) ;set up a-disk-transfer-size before removing this ;Get disk-rq array, which must be temp-wired #+exp ((vma) pdl-top) (DISPATCH-XCT-NEXT #+lambda DISPATCH-WRITE-VMA (I-ARG DATA-TYPE-INVOKE-OP) Q-DATA-TYPE PDL-TOP ARRAY-HEADER-SETUP-DISPATCH) ((m-a) invalidate-array-cache c-pdl-buffer-pointer-pop) (call store-array-registers-in-accumulators) ;; For now, no queueing, just perform request immediately ((A-DISK-IDLE-TIME) M-ZERO) ;I use the disk ((A-DISK-RESERVED-FOR-USER) SETO) ;I want the disk (CALL AWAIT-DISK) ;Wait for disk control to become available ((VMA-START-READ) ADD M-E (A-CONSTANT (EVAL (// %DISK-RQ-COMMAND 2)))) (CHECK-PAGE-READ) ;Copy user's commands into A-memory ((A-DISK-COMMAND) READ-MEMORY-DATA) ((A-DISK-READ-WRITE) (BYTE-FIELD 4 0) READ-MEMORY-DATA) ;For error recovery ((VMA-START-READ) ADD VMA (A-CONSTANT 1)) ;CLP (CHECK-PAGE-READ) ((A-DISK-CLP) READ-MEMORY-DATA) ((VMA-START-READ) ADD VMA (A-CONSTANT 1)) ;Address (CHECK-PAGE-READ) ((A-DISK-ADDRESS) READ-MEMORY-DATA) #-lambda(begin-comment) ;offset only unit 0, and then only if the highest bit of the cylinder address is 0 ((m-1) ldb da-cylinder read-memory-data) ((m-j) ldb da-unit read-memory-data) (jump-not-equal m-j a-zero xdskop-no-offset) (jump-if-bit-set da-cylinder-highest-bit m-1 xdskop-no-offset) ((m-1) add m-1 a-disk-cylinder-offset) xdskop-no-offset ((m-1) dpb m-zero da-cylinder-highest-bit a-1) ((a-disk-address) dpb m-1 da-cylinder a-disk-address) #-lambda(end-comment) ((A-DISK-RETRY-STATE) M-ZERO) ((A-DISK-DOING-READ-COMPARE) M-ZERO) (CALL-XCT-NEXT START-DISK-OP-2) ;Fire it up ((M-J) A-DISK-COMMAND) ;WAIT FOR OPERATION TO COMPLETE ((a-active-iopb) a-iopb-base) (call await-disk-hardware) (CALL-IF-BIT-SET (BYTE-FIELD 1 11.) M-J AWAIT-DISK) ;Await retry if enabled (CALL-IF-BIT-CLEAR (BYTE-FIELD 1 11.) M-J DISK-COMPLETION-GET-STATUS) ;Get status ;into A-MEM if havent already. (CALL-IF-BIT-CLEAR (BYTE-FIELD 1 11.) M-J DISK-COMPLETION-OK) ;and finish up if nec. ;Return status from A-memory. Unfortunately not quite the same as at LOG-DISK-ERROR. ((VMA) ADD M-E (A-CONSTANT (EVAL (// %DISK-RQ-STATUS-LOW 2)))) ((MD-START-WRITE) A-DISK-STATUS) (CHECK-PAGE-WRITE) ((VMA) ADD VMA (A-CONSTANT 1)) ((MD-START-WRITE) A-DISK-MA) (CHECK-PAGE-WRITE) ((VMA) ADD VMA (A-CONSTANT 1)) ((MD-START-WRITE) A-DISK-FINAL-ADDRESS) (CHECK-PAGE-WRITE) ((VMA) ADD VMA (A-CONSTANT 1)) ((MD-START-WRITE) A-DISK-ECC) (CHECK-PAGE-WRITE) ((MD) DPB (M-CONSTANT -1) (BYTE-FIELD 17. 15.) A-DISK-RETRY-STATE) ((VMA-START-WRITE) ADD M-E (A-CONSTANT (EVAL (// %DISK-RQ-DONE-FLAG 2)))) (CHECK-PAGE-WRITE) ;Set completion flag, return retry state (CALL-EQUAL M-ZERO A-DISK-RESERVED-FOR-USER ILLOP) ;Took a page fault?? (POPJ-AFTER-NEXT (M-T) A-V-NIL) ((A-DISK-RESERVED-FOR-USER) M-ZERO) ;I'm done with it #-lambda(end-comment) ;;; Support for "user" disk I/O ;;; Note that the interrupt-enable bit in the command word controls ;;; whether or not system error recovery features are invoked. #-exp(begin-comment) x-io-cmd-run (misc-inst-entry %io-cmd-run) ;set up a-disk-transfer-size before removing this ;Get disk-rq array, which must be temp-wired #+exp ((vma) pdl-top) (DISPATCH-XCT-NEXT #+lambda DISPATCH-WRITE-VMA (I-ARG DATA-TYPE-INVOKE-OP) Q-DATA-TYPE PDL-TOP ARRAY-HEADER-SETUP-DISPATCH) ((m-a) invalidate-array-cache c-pdl-buffer-pointer-pop) (call store-array-registers-in-accumulators) ; ((md) m-e) ; (no-op) ; (dispatch l2-map-status-code d-get-map-bits) ;get map set up ((vma-start-read) m-e) (check-page-read-no-interrupt) ((md) m-e) (no-op) ((m-1) dpb l2-map-physical-page (byte-field 22. 10.) a-zero) ((m-1) dpb m-e (byte-field 8 2) a-1) ;; For now, no queueing, just perform request immediately ((A-DISK-IDLE-TIME) M-ZERO) ;I use the disk ((A-DISK-RESERVED-FOR-USER) SETO) ;I want the disk (CALL AWAIT-DISK) ;Wait for disk control to become available ((md) setz) ((vma-start-write) a-nupi-special-event-vadr) (illop-if-page-fault) ((md) m-1) ((vma-start-write-unmapped) (a-constant #xf2e00004)) ((a-active-iopb) m-e) (call await-disk-hardware) (CALL-EQUAL M-ZERO A-DISK-RESERVED-FOR-USER ILLOP) ;Took a page fault?? (POPJ-AFTER-NEXT (M-T) A-V-NIL) ((A-DISK-RESERVED-FOR-USER) M-ZERO) ;I'm done with it #-exp(end-comment) #-lambda(begin-comment) ;This is the LAMBDA INTERPHASE disk driver convert-m-1-to-a-disk-address (declare (args a-1) (clobbers a-tem1 a-2)) (CALL-XCT-NEXT DIV) ;Convert disk address to physical ((M-2) DPB M-ZERO Q-ALL-BUT-POINTER A-DISK-BLOCKS-PER-CYLINDER) ((Q-R) ADD Q-R A-DISK-CYLINDER-OFFSET) ;offset entire world!!! ((A-DISK-ADDRESS) DPB Q-R DA-CYLINDER A-ZERO) ;Save cylinder (CALL-XCT-NEXT DIV) ((M-2) DPB M-ZERO Q-ALL-BUT-POINTER A-DISK-BLOCKS-PER-TRACK) (popj-after-next (A-DISK-ADDRESS) DPB Q-R DA-HEAD A-DISK-ADDRESS) ;Save head ((A-DISK-ADDRESS) DPB M-1 DA-BLOCK A-DISK-ADDRESS) ;Save block ;;; Here to start a disk operation that has been set up in the A-memory variables. ;;; Also called from interrupt level for retries ;;; Returns immediately; call AWAIT-DISK if you want to wait for completion. ;;; Returns with address of disk-run-light in VMA START-DISK-OP ((A-DISK-COMMAND) A-DISK-READ-WRITE) ((A-DISK-DOING-READ-COMPARE) M-ZERO) ;;; Here to start some command other than the one we are really supposed to be doing START-DISK-OP-1 ; ((MD) DPB (M-CONSTANT -1) ;Turn on interrupt enable ; (BYTE-FIELD 1 11.) A-DISK-COMMAND) ;;; Enter here from %DISK-OP. must not clobber M-3 from below here. START-DISK-OP-2 (CALL STORE-IOPB-FROM-A-MEM) (CALL IP-DISK-START) ((A-DISK-BUSY) (M-CONSTANT -1)) ((MD) (M-CONSTANT -1)) (POPJ-AFTER-NEXT (VMA-START-WRITE) A-DISK-RUN-LIGHT) (CHECK-PAGE-WRITE-NO-INTERRUPT) ;;; Subroutine to wait for a disk operation to complete. Checks for interrupts, ;;; but doesn't check for interrupts between discovering that it is idle and ;;; returning; hence it is guaranteed still to be idle. await-disk (popj-equal a-disk-busy m-zero) ((a-active-iopb) a-iopb-base) (call await-disk-hardware) (call disk-completion-main-program) (jump await-disk) AWAIT-DISK-DELAY ((M-TEM) (A-CONSTANT 100.)) ;give delay of 40 US at full (half) speed. AW-D-0 (JUMP-GREATER-THAN-XCT-NEXT M-TEM A-ZERO AW-D-0) ((M-TEM) SUB M-TEM (A-CONSTANT 1)) await-disk-hardware ;WAIT FOR OPERATION TO COMPLETE ((VMA-START-READ) a-active-iopb) (CHECK-PAGE-READ) ;allow interrupts. interrupt hacker does not hack disks now. ((M-TEM) LDB (BYTE-FIELD 8 16.) READ-MEMORY-DATA) (JUMP-EQUAL M-TEM (A-CONSTANT 201) AWAIT-DISK-DELAY) (JUMP-EQUAL M-TEM (A-CONSTANT 0) AWAIT-DISK-DELAY) (popj) DISK-COMPLETION-GET-STATUS (CALL MAP-INTERPHASE-ERROR) ((A-DISK-STATUS) M-A) (POPJ) MAP-INTERPHASE-ERROR ((VMA-START-READ) A-IOPB-BASE) (CHECK-PAGE-READ-NO-INTERRUPT) ((M-TEM) LDB (BYTE-FIELD 8 16.) READ-MEMORY-DATA) ;status byte ((M-A) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 200)) ;no errors on successful reply ((M-TEM) LDB (BYTE-FIELD 8 24.) READ-MEMORY-DATA) ;error code. ;map Interphase error code to CADR error bit. ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 5) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 33)) ;1B(hex), unit not selected ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 6) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 36)) ;1E, drive faulted ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 8.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 57)) ;2F, not on cylinder ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 9.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 20)) ;10, drive not ready ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 10.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 22)) ;12, seek error (via header compare) ; ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 11.) A-ZERO) ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 12.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 34)) ;1C, no address mark, header field ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 13.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 47)) ;27, data overrun ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 14.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 61)) ;31, format overrun on data ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 15.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 23)) ;13, ECC code error-data field ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 16.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 43)) ;23, Uncorrectable error ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 17.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 51)) ;29, Sector not found ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 18.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 52)) ;2A, ID field header wrong ; ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 19.) A-ZERO) ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 20.) A-ZERO) (POPJ-EQUAL M-TEM (A-CONSTANT 30)) ;18, BUS timeout ; ((M-A) DPB M-MINUS-ONE (BYTE-FIELD 1 23.) A-ZERO) (CALL ILLOP) ;disk error not mappable to corresponding CADR disk error (POPJ) IP-DISK-START ;clobbers M-T, M-LAM plus registers clobbered by map faults. ;store multibus->nubus mapping register so as to allow disk control to access ; IOPB. (CALL-XCT-NEXT TRANSLATE-CADR-PHYSICAL-TO-NUBUS) ((M-T) A-IOPB-BASE) ((m-lam) xor m-lam a-local-phys-adr-convert) ((MD) LDB (BYTE-FIELD 22. 10.) M-LAM (A-CONSTANT 40000000)) ;page number to ;store in SDU map. Constant is enable bit in map. ((VMA) A-MULTIBUS-DISK-MAP-BASE) ;construct hardware-virtual-address of SDU map. ((VMA-START-WRITE) ADD VMA A-MULTIBUS-MAP-HARDWARE-VIRTUAL-ADDRESS) (CHECK-PAGE-WRITE-NO-INTERRUPT) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 2000)) ;write 3 times, 1 byte ea time. (CHECK-PAGE-WRITE-NO-INTERRUPT) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 2000)) (CHECK-PAGE-WRITE-NO-INTERRUPT) ((m-t) a-processor-switches) (jump-if-bit-set (lisp-byte %%processor-switch-use-disk-sharing-protocol) m-t share-start) ;writes IOPB base address and gives start command. ((MD) A-MULTIBUS-DISK-MAP-BASE) ((MD) DPB MD (BYTE-FIELD 10. 10.) A-ZERO) ;multibus byte adr of IOPB map ((M-T) A-IOPB-BASE) ((M-T) DPB M-T (BYTE-FIELD 8. 2) A-ZERO) ;byte offset within page. ((M-T) ADD MD A-T) ;M-T now has byte adr where disk should look for IOPB ((VMA) A-DISK-REGS-BASE) ((vma) add vma (a-constant 2)) ;write IOPB base address ((MD-START-WRITE) LDB (BYTE-FIELD 8 16.) M-T A-ZERO) (CHECK-PAGE-WRITE-NO-INTERRUPT) ((VMA) ADD VMA (A-CONSTANT 1)) ((MD-START-WRITE) LDB (BYTE-FIELD 8 8) M-T A-ZERO) (CHECK-PAGE-WRITE-NO-INTERRUPT) ((VMA) ADD VMA (A-CONSTANT 1)) ((MD-START-WRITE) LDB (BYTE-FIELD 8 0) M-T A-ZERO) (CHECK-PAGE-WRITE-NO-INTERRUPT) ((VMA) A-DISK-REGS-BASE) ((MD-START-WRITE) (A-CONSTANT IP-DISK-START-COMMAND)) (CHECK-PAGE-WRITE-NO-INTERRUPT) (POPJ) share-start ((md) (a-constant 1)) ((vma) a-proc-conf-virtual-adr) ((vma-start-write) add vma (a-constant (eval %processor-conf-share-runme))) (check-page-write-no-interrupt) ((vma-start-write) (a-constant (eval (+ 177370000 (ash #x1fc -2))))) ;multibus interrupt 7 (check-page-write-no-interrupt) (popj) STORE-IOPB-FROM-A-MEM ;clobbers M-1, M-2, M-LAM, M-TEM, M-C ;translates CADR type disk command in A-memory variables to IOPB form and ; sets up multibus map. ;fill in iopb ; wd0: (errors,status,command-options,command) 10400+command ; wd1: (cyl lsb, cyl msb, head, unit) ; wd2: (sect count lsb, sect count msb, sect lsb, sect msb) ; wd3: (buf lsb, buf msb, buf xmb, dma count) ; wd4: (rel adr lsb, rel adr msb, io adr lsb, io adr msb) ; wd5: (iopb link lsb, iopb link msb, iopb llink xmb, reserved) (CALL-XCT-NEXT SETUP-MAP-FROM-CLP) ((M-C) A-DISK-CLP) ((M-LAM) DPB M-ZERO (BYTE-FIELD 28. 4) A-DISK-COMMAND) ;get CADR disk command (JUMP-EQUAL-XCT-NEXT M-LAM (A-CONSTANT DISK-READ-COMMAND) SIOPB-1) ((MD) (A-CONSTANT IP-DISK-READ-COMMAND-WORD)) (JUMP-EQUAL-XCT-NEXT M-LAM (A-CONSTANT DISK-WRITE-COMMAND) SIOPB-1) ((MD) (A-CONSTANT IP-DISK-WRITE-COMMAND-WORD)) (CALL-NOT-EQUAL M-LAM (A-CONSTANT DISK-READ-COMPARE-COMMAND) ILLOP) ((MD) (A-CONSTANT IP-DISK-READ-COMPARE-COMMAND-WORD)) SIOPB-1 ((VMA-START-WRITE) A-IOPB-BASE) (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ;store command word. ((M-1) A-DISK-ADDRESS) ((M-2) LDB M-1 DA-UNIT A-ZERO) ((M-TEM) LDB M-1 DA-HEAD A-ZERO) ((M-2) DPB M-TEM (BYTE-FIELD 8 8) A-2) ((M-TEM) LDB M-1 DA-CYLINDER A-ZERO) ((M-2) DPB M-TEM (BYTE-FIELD 8 24.) A-2) ;m-2, hi byte gets low byte of cyl ((M-TEM) LDB M-TEM (BYTE-FIELD 8 8) A-ZERO) ;move hi byte of cyl to low byte of m-tem ((M-2 MD) DPB M-TEM (BYTE-FIELD 8 16.) A-2) ;insert hi byte of cyl in m-2 and md ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) ;wd1 (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ;store first disk address word ((M-TEM) LDB M-1 DA-BLOCK A-ZERO) ((M-2) DPB M-TEM (BYTE-FIELD 8 8) A-ZERO) ((M-TEM) LDB (BYTE-FIELD 8 8) M-TEM A-ZERO) ((M-2) DPB M-TEM (BYTE-FIELD 8 0) A-2) ; ((M-2) ADD M-2 A-2) ;double the sector number ; ((M-C) ADD M-C A-C) ;double the sector count ((M-2) DPB M-C (BYTE-FIELD 8 24.) A-2) ((M-C) LDB (BYTE-FIELD 8 8) M-C A-ZERO) ((M-2 MD) DPB M-C (BYTE-FIELD 8 16.) A-2) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) ;wd2 (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ;store sector count, sector ((M-TEM) A-MULTIBUS-DISK-MAP-BASE) ;first mapping reg used for data. ((m-tem) add m-tem (a-constant 2)) ((M-TEM) DPB M-TEM (BYTE-FIELD 10. 2.) A-ZERO) ;first multibus byte adr for data.n ;shifted -8. (lsb of address is always 0) ((M-2) DPB M-TEM (BYTE-FIELD 8 16.) (A-CONSTANT 200)) ;200 is DMA count, dpb in msb ((MD) SELECTIVE-DEPOSIT M-TEM (BYTE-FIELD 8 8) A-2) ;stick in xsb ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ;store buffer addr, dma count ((M-TEM) A-MULTIBUS-DISK-DEVICE-NUMBER) ((M-TEM1) LDB (BYTE-FIELD 8. 8.) M-TEM A-ZERO) ((MD) DPB M-TEM (BYTE-FIELD 8. 8.) A-TEM1) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ;store rel adr, io adr ((MD) (A-CONSTANT 0)) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 1)) (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ;linked IOPB address. (POPJ) SETUP-MAP-FROM-CLP ;set up MULTIBUS to NUBUS map from CADR CLP pointer in M-C. ;ACs clobbered: M-1, M-2, M-T, M-LAM, M-C. M-C returns number of pages ; which were set up. Note well that the CLP is a CADR-HARDWARE-VIRTUAL-ADDRESS. ; ie, it would be a physical address in CADR. ((M-2) A-MULTIBUS-DISK-MAP-BASE) ;construct hardware-virtual-address of SDU map. ((m-2) add m-2 (a-constant 2)) ((M-2) add M-2 A-MULTIBUS-MAP-HARDWARE-VIRTUAL-ADDRESS) ((M-1) M-C) SM-CLP-0 ((m-lam) sub m-1 a-c) (call-greater-or-equal m-lam a-number-of-data-mapping-registers-for-disk illop) (CALL-XCT-NEXT PHYS-MEM-READ) ;CLP is a CADR-HARDWARE-VIRTUAL-ADDRESS. ((VMA) M-1) ((M-T) MD) ;now have CADR ccw word (CALL TRANSLATE-CADR-PHYSICAL-TO-NUBUS) ;map to nubus physical address, ans in M-LAM ((m-lam) xor m-lam a-local-phys-adr-convert) ((VMA) M-2) ((MD-START-WRITE) LDB (BYTE-FIELD 22. 10.) M-LAM (A-CONSTANT 40000000)) ;store in SDU map. Constant is enable bit in map. (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 2000)) ;write 3 times, 1 byte ea time. (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ((VMA-START-WRITE) ADD VMA (A-CONSTANT 2000)) (CHECK-PAGE-WRITE-MAP-RELOAD-ONLY) ((M-1) ADD M-1 (A-CONSTANT 1)) (JUMP-IF-BIT-SET-XCT-NEXT (BYTE-FIELD 1 0) M-T SM-CLP-0) ((M-2) ADD M-2 (A-CONSTANT 1)) ((M-C) SUB M-1 A-C) ;RETURN NUMBER OF PAGES SET UP IN M-C (POPJ) #-lambda(end-comment) #-exp (begin-comment) ;This is the EXPLORER NUPI disk driver convert-m-1-to-a-disk-address ;*** hack unit here (popj-after-next (a-disk-address) m-1) (no-op) ;;; Here to start a disk operation that has been set up in the A-memory variables. ;;; Also called from interrupt level for retries ;;; Returns immediately; call AWAIT-DISK if you want to wait for completion. ;;; Returns with address of disk-run-light in VMA START-DISK-OP ((a-disk-command) a-disk-read-write) ((a-disk-doing-read-compare) m-zero) ;;; Here to start some command other than the one we are really supposed to be doing start-disk-op-1 ; ((md) dpb (m-constant -1) ;Turn on interrupt enable ; (byte-field 1 11.) a-disk-command) ;;; Enter here from %DISK-OP. must not clobber M-3 from below here. start-disk-op-2 (call store-nupi-command-block-from-a-mem) (call nupi-disk-start) ((a-disk-busy) (m-constant -1)) ((md) (m-constant -1)) (popj-after-next (vma-start-write) a-disk-run-light) (check-page-write-no-interrupt) ;;; Subroutine to wait for a disk operation to complete. Checks for interrupts, ;;; but doesn't check for interrupts between discovering that it is idle and ;;; returning; hence it is guaranteed still to be idle. await-disk (popj-equal a-disk-busy m-zero) ((a-active-iopb) a-nupi-command-block-base) (call await-disk-hardware) (call disk-completion-main-program) (jump await-disk) await-disk-delay ((m-tem) (a-constant 100.)) ;give delay of 40 US at full (half) speed. aw-d-0 (jump-greater-than-xct-next m-tem a-zero aw-d-0) ((m-tem) sub m-tem (a-constant 1)) ;address of base of command block in M-A await-disk-hardware ;check for operation to complete ((vma-start-read) m+a+1 m-zero a-active-iopb) (check-page-read) ;allow interrupts. interrupt hacker does not hack disks now. (popj-if-bit-set (byte-field 1 30.) md) ((vma-start-read) a-nupi-special-event-vadr) (check-page-read) (popj-not-equal md a-zero) (jump await-disk-delay) ;this is called with a-intr-a, etc alive ... therefore must not let interrupt happen disk-completion-get-status ((vma-start-read) m+a+1 m-zero a-nupi-command-block-base) (check-page-read-no-interrupt) ((a-disk-status) a-zero) ((m-a) a-zero) (jump-if-bit-clear (byte-field 1 29.) md check-for-special-nupi-event) ((m-tem) ldb (byte-field 8 8) md) ;device error code (call map-nupi-error) ((a-disk-status) m-a) (popj) check-for-special-nupi-event ((vma-start-read) a-nupi-special-event-vadr) (illop-if-page-fault) (call-not-equal md a-zero get-nupi-extended-status) (popj) ;this should do the extended status command, then set a-disk-status to some cadr error code ;actually, we should only get here on complete machine failures, or if we create a grabage ;command block get-nupi-extended-status (call illop) (popj) map-nupi-error ;map nupi error code to CADR error bit. ((m-a) dpb m-minus-one (byte-field 1 5) a-zero) (popj-equal m-tem (a-constant #x41)) ;unit not selected ((m-a) dpb m-minus-one (byte-field 1 6) a-zero) (popj-equal m-tem (a-constant #x46)) ;drive faulted (temperature) (popj-equal m-tem (a-constant #xa3)) ;write fault ((m-a) dpb m-minus-one (byte-field 1 8.) a-zero) (popj-equal m-tem (a-constant #xa6)) ;not on cylinder ((m-a) dpb m-minus-one (byte-field 1 9.) a-zero) (popj-equal m-tem (a-constant #x62)) ;drive not ready (popj-equal m-tem (a-constant #x44)) (popj-equal m-tem (a-constant #x65)) ;drive offline (popj-equal m-tem (a-constant #x43)) ;write protected ... a little the same (popj-equal m-tem (a-constant #x42)) ;no media loaded ((m-a) dpb m-minus-one (byte-field 1 12.) a-zero) (popj-equal m-tem (a-constant #xc3)) ;no address mark, header field (popj-equal m-tem (a-constant #xc4)) ((m-a) dpb m-minus-one (byte-field 1 13.) a-zero) (popj-equal m-tem (a-constant #x63)) ;data overrun ((m-a) dpb m-minus-one (byte-field 1 16.) a-zero) (popj-equal m-tem (a-constant #xc2)) ;Uncorrectable error ((m-a) dpb m-minus-one (byte-field 1 17.) a-zero) (popj-equal m-tem (a-constant #xc5)) ;Sector not found (call illop) ;disk error not mappable to corresponding CADR disk error (popj) nupi-DISK-START ;clobbers M-T, M-LAM plus registers clobbered by map faults. ((md) setz) ((vma-start-write) a-nupi-special-event-vadr) (illop-if-page-fault) (call-xct-next translate-cadr-physical-to-nubus) ((m-t) a-nupi-command-block-base) ((md) m-lam) ((vma-start-write-unmapped) (a-constant #xf2e00004)) (popj) store-nupi-command-block-from-a-mem ;clobbers M-1, M-LAM, M-TEM, M-C ;translates CADR type disk command in A-memory variables to command block form ((m-tem) dpb m-zero (byte-field 28. 4) a-disk-command) ;get CADR disk command (jump-equal-xct-next m-tem (a-constant disk-read-command) store-nupi-command-block-1) ((m-1) (a-constant #x12)) ;nupi read command (jump-equal-xct-next m-tem (a-constant disk-write-command) store-nupi-command-block-1) ((m-1) (a-constant #x13)) (call illop) store-nupi-command-block-1 ;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 ;command word ((m-tem) a-disk-address) ((m-tem) ldb (byte-field 8 24.) m-tem) ;unit select in low byte ((m-tem) dpb m-minus-one (byte-field 1 22.) a-tem) ;scatter bit ((md) dpb m-1 (byte-field 8 24.) a-tem) ;command in high byte ((vma-start-write m-1) a-nupi-command-block-base) (check-page-write-no-interrupt) ;status word ((md) setz) ((vma-start-write m-1) m+1 m-1) (check-page-write-no-interrupt) ;parameter list pointer ((m-t) a-disk-clp) (call translate-cadr-physical-to-nubus) ((md) xor m-lam a-local-phys-adr-convert) ((vma-start-write m-1) m+1 m-1) (check-page-write-no-interrupt) ;transfer count ((m-t) a-disk-transfer-size) ((md) dpb m-t (byte-field 22. 10.) a-zero) ;convert from pages to bytes ((vma-start-write m-1) m+1 m-1) (check-page-write-no-interrupt) ;device block address ((md) dpb m-zero (byte-field 8 24.) a-disk-address) ;zero out the unit number ((vma-start-write m-1) m+1 m-1) (check-page-write-no-interrupt) ;interrupt address ((md) setz) ((vma-start-write m-1) m+1 m-1) (check-page-write-no-interrupt) ;reserved 1 ((md) setz) ((vma-start-write m-1) m+1 m-1) (check-page-write-no-interrupt) ;reserved 2 ((md) setz) ((vma-start-write m-1) m+1 m-1) (check-page-write-no-interrupt) (popj) #-exp(end-comment) ))