;;;
;;; raven-nubus.lisp
;;;
;;; NuBus interface emulation.
;;;

(in-package :nevermore)

(defun nubus-read (address width)
  "Read from NuBus space at ADDRESS with WIDTH either :BYTE or :WORD. Sets *nubus-error* to T if memory not mapped, otherwise sets *memory-data* to the requisite value."

  (setf *page-fault* nil)
  (setf *nubus-error* nil)
  (when (zerop (logand #x100 *machine-control-register*))
    ;; Memory cycle disabled.
    (setf *memory-busy* 0)
    (return-from nubus-read))
  ;; Memory busy should remain high for three cycles after this one.
  ;; Memory busy counter is decremented at the end of the cycle, so we
  ;; have to account for this one as well.
  (setf *memory-busy* 4)

  (if (= (ldb (byte 4 28) address) #xf)
      (let ((slot (ldb (byte 4 24) address)))
	(cond ((= slot *cpu-nubus-slot*) (cpu-nubus-read address width))
	      ((= slot *sib-nubus-slot*) (sib-nubus-read address width))
	      ((= slot *mem-nubus-slot*) (memory-nubus-read address width))
	      (t (setf *nubus-error* t))))
    (setf *nubus-error* t)))

(defun nubus-write (address width)
  "Write *memory-data* to NuBus space at ADDRESS with WIDTH either :BYTE or :WORD. Sets *nubus-error* to T if memory not mapped."

  (setf *page-fault* nil)
  (setf *nubus-error* nil)
  (when (zerop (logand #x100 *machine-control-register*))
    ;; Memory cycle disabled.
    (setf *memory-busy* 0)
    (return-from nubus-write))
  ;; Memory busy should remain high for three cycles after this one.
  ;; Memory busy counter is decremented at the end of the cycle, so we
  ;; have to account for this one as well.
  (setf *memory-busy* 4)

  (if (= (ldb (byte 4 28) address) #xf)
      (let ((slot (ldb (byte 4 24) address)))
	(cond ((= slot *cpu-nubus-slot*) (cpu-nubus-write address width))
	      ((= slot *sib-nubus-slot*) (sib-nubus-write address width))
	      ((= slot *mem-nubus-slot*) (memory-nubus-write address width))
	      (t (setf *nubus-error* t))))
    (setf *nubus-error* t)))

(defun start-unmapped-read (address)
  (format t "Reading NuBus Address ~X~%" address)
  (nubus-read address :word))

(defun start-unmapped-write (address)
  (format t "Writing NuBus Address ~X: ~X~%" address *memory-data*)
  (nubus-write address :word))

(defun start-unmapped-byte-read (address)
  (format t "Byte Reading NuBus Address ~X~%" address)
  (nubus-read address :byte))

(defun start-unmapped-byte-write (address)
  (format t "Byte Writing NuBus Address ~X: ~X~%" address *memory-data*)
  (nubus-write address :byte))


;;; EOF
