2020-10-26 21:08:24 -04:00
|
|
|
;;-*-Lisp-*-
|
2020-09-04 14:44:23 -04:00
|
|
|
(in-package goal)
|
|
|
|
|
|
|
|
;; name: dma-h.gc
|
|
|
|
;; name in dgo: dma-h
|
|
|
|
;; dgos: GAME, ENGINE
|
|
|
|
|
2021-07-09 22:20:37 -04:00
|
|
|
;; Constants/type for the PS2 DMA hardware
|
2021-02-21 11:02:28 -05:00
|
|
|
;; There are a number of DMA channels.
|
|
|
|
;; The PS2 supports several types of DMA, including simple chunk transfer and more complicated
|
|
|
|
;; "chain" transfers, where the hardware can follow a linked data-structure.
|
|
|
|
|
2021-07-09 22:20:37 -04:00
|
|
|
;; The code is organized into dma, dma-buffer, and dma-bucket
|
|
|
|
;; - dma interacts with the hardware and actually sends the DMA data.
|
|
|
|
;; - dma-buffer is memory management for the data to be sent
|
|
|
|
;; - dma-bucket is organization of all the frame's DMA data in the correct order
|
|
|
|
|
2021-04-11 16:07:01 -04:00
|
|
|
;; In OpenGOAL, "DMA" will be instant, meaning the game code will stop, wait until the
|
|
|
|
;; DMA is finished, and then continue. As a result, there is no need for DMA synchronization.
|
|
|
|
;; When this flag is set, all DMA syncs will be instantaneous.
|
2021-02-21 11:02:28 -05:00
|
|
|
(defglobalconstant INSTANT_DMA #t)
|
|
|
|
|
2021-04-11 16:07:01 -04:00
|
|
|
;; Some DMA sync functions return a count for how long it took.
|
|
|
|
;; When INSTANT_DMA is enabled, these functions will return this value.
|
2021-02-21 11:02:28 -05:00
|
|
|
(defglobalconstant INSTANT_DMA_COUNT 123)
|
|
|
|
|
2021-05-01 00:32:19 -04:00
|
|
|
;; DMA Channel Control Register. This starts the DMA and can be checked to see if it's done.
|
2021-04-11 16:07:01 -04:00
|
|
|
;; There is one CHCR per DMA channel.
|
2021-02-21 11:02:28 -05:00
|
|
|
(deftype dma-chcr (uint32)
|
|
|
|
((dir uint8 :offset 0 :size 1) ;; 1 - from memory
|
|
|
|
(mod uint8 :offset 2 :size 2) ;; normal, chain, interleave
|
|
|
|
(asp uint8 :offset 4 :size 2) ;; none, 1, 2
|
|
|
|
(tte uint8 :offset 6 :size 1) ;; transfer tag (sc only)
|
|
|
|
(tie uint8 :offset 7 :size 1) ;; tag interrupt
|
|
|
|
(str uint8 :offset 8 :size 1) ;; start!
|
|
|
|
(tag uint16 :offset 16)
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x4
|
|
|
|
:flag-assert #x900000004
|
|
|
|
)
|
|
|
|
|
|
|
|
(defmethod inspect dma-chcr ((obj dma-chcr))
|
|
|
|
(format #t "~Tdir: ~D~%" (-> obj dir))
|
|
|
|
(format #t "~Tmod: ~D~%" (-> obj mod))
|
|
|
|
(format #t "~Tasp: ~D~%" (-> obj asp))
|
|
|
|
(format #t "~Ttte: ~D~%" (-> obj tte))
|
|
|
|
(format #t "~Ttie: ~D~%" (-> obj tie))
|
|
|
|
(format #t "~Tstr: ~D~%" (-> obj str))
|
|
|
|
(format #t "~Ttag: #x~X~%" (-> obj tag))
|
|
|
|
obj
|
|
|
|
)
|
|
|
|
|
2021-04-11 16:07:01 -04:00
|
|
|
;; Each DMA Channel has a bank of registers with the following layout.
|
|
|
|
;; Some channels have more advanced features, but all support at least these three.
|
2021-02-21 11:02:28 -05:00
|
|
|
(deftype dma-bank (structure)
|
|
|
|
((chcr dma-chcr :offset 0) ;; control register
|
|
|
|
(madr uint32 :offset 16) ;; memory address
|
|
|
|
(qwc uint32 :offset 32) ;; quadword count
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x24
|
|
|
|
:flag-assert #x900000024
|
|
|
|
)
|
|
|
|
|
|
|
|
;; DMA register layout for channels supporting source-chain
|
|
|
|
(deftype dma-bank-source (dma-bank)
|
|
|
|
((tadr uint32 :offset 48) ;; tag address
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x34
|
|
|
|
:flag-assert #x900000034
|
|
|
|
)
|
|
|
|
|
|
|
|
;; The DMA source chain supports a two-entry "call stack" of tags.
|
|
|
|
;; The tag addresses are stored here.
|
|
|
|
(deftype dma-bank-vif (dma-bank-source)
|
|
|
|
((as0 uint32 :offset 64) ;; pushed tag register
|
|
|
|
(as1 uint32 :offset 80) ;; pushed tag register
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x54
|
|
|
|
:flag-assert #x900000054
|
|
|
|
)
|
|
|
|
|
|
|
|
;; The toSPR and fromSPR DMA channels require a second address in the scratchpad.
|
|
|
|
;; This is an offset from the start of SPR.
|
|
|
|
(deftype dma-bank-spr (dma-bank-source)
|
|
|
|
((sadr uint32 :offset 128) ;; spad address.
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x84
|
|
|
|
:flag-assert #x900000084
|
|
|
|
)
|
|
|
|
|
2021-04-11 16:07:01 -04:00
|
|
|
;; These addresses are the location of DMA banks for each channel.
|
|
|
|
;; These do not exist in OpenGOAL.
|
2021-05-01 00:32:19 -04:00
|
|
|
(defconstant VIF0_DMA_BANK (the dma-bank-vif (get-vm-ptr #x10008000)))
|
|
|
|
(defconstant VIF1_DMA_BANK (the dma-bank-vif (get-vm-ptr #x10009000)))
|
|
|
|
(defconstant GIF_DMA_BANK (the dma-bank (get-vm-ptr #x1000a000)))
|
2021-02-22 09:36:30 -05:00
|
|
|
;; ipuFrom, ipTop, sif0, sif1, sif2 believed unused.
|
2021-05-01 00:32:19 -04:00
|
|
|
(defconstant SPR_FROM_BANK (the dma-bank-spr (get-vm-ptr #x1000d000)))
|
|
|
|
(defconstant SPR_TO_BANK (the dma-bank-spr (get-vm-ptr #x1000d400)))
|
2021-02-21 11:02:28 -05:00
|
|
|
|
2021-04-11 16:07:01 -04:00
|
|
|
(defconstant VU0_DATA_MEM_MAP (the (pointer uint32) #x11004000))
|
|
|
|
(defconstant VU1_DATA_MEM_MAP (the (pointer uint32) #x1100c000))
|
|
|
|
|
|
|
|
|
|
|
|
;; The DMA system also has some shared control registers that
|
|
|
|
;; apply to all channels.
|
|
|
|
|
|
|
|
;; D_CTRL, master DMA control register, shared for all channels.
|
2021-02-21 11:02:28 -05:00
|
|
|
(deftype dma-ctrl (uint32)
|
2021-04-16 18:36:19 -04:00
|
|
|
((dmae uint8 :offset 0 :size 1)
|
|
|
|
(rele uint8 :offset 1 :size 1)
|
|
|
|
(mfd uint8 :offset 2 :size 2)
|
|
|
|
(sts uint8 :offset 4 :size 2)
|
|
|
|
(std uint8 :offset 6 :size 2)
|
|
|
|
(rcyc uint8 :offset 8 :size 3)
|
|
|
|
)
|
2021-02-21 11:02:28 -05:00
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x4
|
|
|
|
:flag-assert #x900000004
|
|
|
|
)
|
|
|
|
|
|
|
|
;; D_ENABLEW, D_ENABLER?
|
|
|
|
(deftype dma-enable (uint32)
|
2021-04-16 18:36:19 -04:00
|
|
|
((cpnd uint8 :offset 16 :size 1))
|
2021-02-21 11:02:28 -05:00
|
|
|
:flag-assert #x900000004
|
|
|
|
)
|
|
|
|
|
|
|
|
;; D_SQWC
|
|
|
|
(deftype dma-sqwc (uint32)
|
2021-04-16 18:36:19 -04:00
|
|
|
((sqwc uint8 :offset 0 :size 8)
|
|
|
|
(tqwc uint8 :offset 16 :size 8)
|
|
|
|
)
|
2021-02-21 11:02:28 -05:00
|
|
|
:flag-assert #x900000004
|
|
|
|
)
|
|
|
|
|
|
|
|
;; Shared DMA control registers.
|
|
|
|
(deftype dma-bank-control (structure)
|
|
|
|
((ctrl dma-ctrl :offset 0)
|
|
|
|
(stat uint32 :offset 16)
|
|
|
|
(pcr uint32 :offset 32)
|
|
|
|
(sqwc dma-sqwc :offset 48)
|
|
|
|
(rbsr uint32 :offset 64)
|
|
|
|
(rbor uint32 :offset 80)
|
|
|
|
(stadr uint32 :offset 96)
|
|
|
|
(enabler uint32 :offset 5408)
|
|
|
|
(enablew uint32 :offset 5520)
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x1594
|
|
|
|
:flag-assert #x900001594
|
|
|
|
)
|
|
|
|
|
2021-05-01 00:32:19 -04:00
|
|
|
(defconstant DMA_CONTROL_BANK (the dma-bank-control (get-vm-ptr #x1000e000)))
|
2021-02-21 11:02:28 -05:00
|
|
|
|
|
|
|
;; Seems to be unused. The vu-function type is used instead.
|
|
|
|
(deftype vu-code-block (basic)
|
|
|
|
((name basic :offset-assert 4)
|
|
|
|
(code uint32 :offset-assert 8)
|
|
|
|
(size int32 :offset-assert 12)
|
|
|
|
(dest-address uint32 :offset-assert 16)
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x14
|
|
|
|
:flag-assert #x900000014
|
|
|
|
)
|
|
|
|
|
|
|
|
;; ?? not sure what this is.
|
|
|
|
(deftype vu-stat (uint64)
|
|
|
|
()
|
|
|
|
:flag-assert #x900000008
|
|
|
|
)
|
|
|
|
|
2021-04-23 20:29:15 -04:00
|
|
|
|
|
|
|
(defenum dma-tag-id
|
|
|
|
:bitfield #f
|
|
|
|
:type uint8
|
|
|
|
(refe 0) ;; addr=ADDR, ends after this transfer
|
|
|
|
(cnt 1) ;; addr=after tag, next-tag=after data
|
|
|
|
(next 2) ;; addr=after tag, next-tag=ADDR
|
|
|
|
(ref 3) ;; addr=ADDR, next-tag=after tag
|
|
|
|
(refs 4) ;; ref, but stall controled
|
2022-04-24 15:15:16 -04:00
|
|
|
(call 5) ;;
|
2021-04-23 20:29:15 -04:00
|
|
|
(ret 6) ;;
|
|
|
|
(end 7) ;; next, but ends.
|
|
|
|
)
|
|
|
|
|
2021-02-21 11:02:28 -05:00
|
|
|
;; In source chain mode, the DMA controller reads "DMAtag"s to determine addresses
|
|
|
|
;; sizes, and the next thing to transfer.
|
|
|
|
;; A tag is 8 bytes.
|
|
|
|
(deftype dma-tag (uint64)
|
2021-04-23 20:29:15 -04:00
|
|
|
((qwc uint16 :offset 0) ;; quadword count
|
|
|
|
(pce uint8 :offset 26 :size 2) ;; priority (source mode)
|
|
|
|
(id dma-tag-id :offset 28 :size 3) ;; ID (what the tag means)
|
|
|
|
(irq uint8 :offset 31 :size 1) ;; interrupt at the end?
|
|
|
|
(addr uint32 :offset 32 :size 31) ;; address (31 bits)
|
|
|
|
(spr uint8 :offset 63 :size 1) ;; spr or not flag.
|
2021-02-21 11:02:28 -05:00
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x8
|
|
|
|
:flag-assert #x900000008
|
|
|
|
)
|
|
|
|
|
2021-06-19 14:24:55 -04:00
|
|
|
|
2021-07-09 22:20:37 -04:00
|
|
|
;; DMA data is divided into buckets.
|
2022-06-05 18:51:19 -04:00
|
|
|
;; At the end of a frame, the buckets are all connected together in order and sent.
|
|
|
|
;; The order of these buckets should match the C++ buckets.h file, and determines the
|
|
|
|
;; order that textures are uploaded and things are drawn.
|
|
|
|
|
|
|
|
;; there is typically a texture upload bucket followed by renderer-specific draw buckets.
|
2022-04-24 15:15:16 -04:00
|
|
|
(defconstant BUCKET_COUNT (#if PC_PORT 70 69))
|
2021-06-19 14:24:55 -04:00
|
|
|
(defenum bucket-id
|
|
|
|
:type int32
|
|
|
|
:bitfield #f
|
2022-04-24 15:15:16 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
;; 0
|
|
|
|
;; 1
|
|
|
|
;; 2
|
2022-03-29 21:38:48 -04:00
|
|
|
(sky-draw 3) ;; actual sky and cloud framebuffer draws
|
|
|
|
(ocean-mid-and-far 4) ;; actual ocean framebuffer draws for mid/transition/far
|
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(tfrag-tex0 5) ;; tfrag texture upload, level 0
|
|
|
|
(tfrag-0 6) ;; tfrag draw, level 0
|
|
|
|
(tfrag-near-0 7) ;; tfrag near draw, level 0
|
|
|
|
(tie-near-0 8) ;; tie near draw, level 0
|
|
|
|
(tie-0 9) ;; tie draw, level 0
|
|
|
|
(merc-tfrag-tex0 10) ;; merc, with tfrag textures, level 0
|
|
|
|
(generic-tfrag-tex0 11) ;; generic merc, with tfrag textures, level 0
|
|
|
|
|
|
|
|
(tfrag-tex1 12) ;; tfrag texture upload, level 1
|
|
|
|
(tfrag-1 13) ;; tfrag draw, level 1
|
|
|
|
(tfrag-near-1 14) ;; tfrag near draw, level 1
|
|
|
|
(tie-near-1 15) ;; tie near draw, level 1
|
|
|
|
(tie-1 16) ;; tie draw, level 1
|
|
|
|
(merc-tfrag-tex1 17) ;; merc, with tfrag textures, level 1
|
|
|
|
(generic-tfrag-tex1 18) ;; generic merc, with tfrag textures, level 1
|
|
|
|
|
|
|
|
(shrub-tex0 19)
|
|
|
|
(shrub0 20)
|
|
|
|
;; 21 (likely shrub near)
|
|
|
|
(shrub-billboard0 22)
|
|
|
|
(shrub-trans0 23)
|
|
|
|
(shrub-generic0 24) ;; note: all shrub seems to go in shrub-generic1
|
|
|
|
|
|
|
|
(shrub-tex1 25)
|
|
|
|
(shrub1 26)
|
|
|
|
;; 27 (likely shrub near)
|
|
|
|
(shrub-billboard1 28)
|
|
|
|
(shrub-trans1 29)
|
|
|
|
(shrub-generic1 30)
|
|
|
|
|
|
|
|
(alpha-tex0 31)
|
|
|
|
(tfrag-trans-0 32) ;; also sky blend
|
|
|
|
(tfrag-trans-near-0 33)
|
|
|
|
(tfrag-dirt-0 34)
|
|
|
|
(tfrag-dirt-near-0 35)
|
|
|
|
(tfrag-ice-0 36)
|
|
|
|
(tfrag-ice-near-0 37)
|
2022-04-24 15:15:16 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(alpha-tex1 38)
|
|
|
|
(tfrag-trans-1 39) ;; also sky blend
|
|
|
|
(tfrag-trans-near-1 40)
|
|
|
|
(tfrag-dirt-1 41)
|
|
|
|
(tfrag-dirt-near-1 42)
|
|
|
|
(tfrag-ice-1 43)
|
|
|
|
(tfrag-ice-near-1 44)
|
2022-04-24 15:15:16 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(merc-alpha-tex 45)
|
|
|
|
(generic-alpha-tex 46)
|
2021-06-19 14:24:55 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(shadow 47)
|
2021-06-19 14:24:55 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(pris-tex0 48)
|
|
|
|
(merc-pris0 49)
|
|
|
|
(generic-pris0 50)
|
2022-04-24 15:15:16 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(pris-tex1 51)
|
|
|
|
(merc-pris1 52)
|
|
|
|
(generic-pris1 53)
|
2021-06-19 14:24:55 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(eyes 54)
|
2022-04-24 15:15:16 -04:00
|
|
|
|
2022-06-05 18:51:19 -04:00
|
|
|
(merc-pris-common 55)
|
|
|
|
(generic-pris-common 56)
|
2021-08-01 17:11:32 -04:00
|
|
|
|
2021-06-19 14:24:55 -04:00
|
|
|
(water-tex0 57)
|
2022-06-05 18:51:19 -04:00
|
|
|
(merc-water0 58)
|
|
|
|
(generic-water0 59)
|
2021-06-19 14:24:55 -04:00
|
|
|
|
|
|
|
(water-tex1 60)
|
2022-06-05 18:51:19 -04:00
|
|
|
(merc-water1 61)
|
|
|
|
(generic-water1 62)
|
|
|
|
|
|
|
|
(ocean-near 63) ; ocean
|
2021-07-26 20:02:16 -04:00
|
|
|
(depth-cue 64)
|
2022-06-05 18:51:19 -04:00
|
|
|
(common-page-tex 65)
|
2021-07-25 15:30:37 -04:00
|
|
|
(sprite 66)
|
2022-04-24 15:15:16 -04:00
|
|
|
(debug 67)
|
|
|
|
(debug-no-zbuf 68)
|
|
|
|
|
|
|
|
;; extra buckets for pc port
|
|
|
|
(subtitle 69)
|
2021-06-19 14:24:55 -04:00
|
|
|
)
|
|
|
|
|
2022-02-05 16:30:50 -05:00
|
|
|
;; A DMA bucket is a way of sorting data within a dma buffer.
|
2021-02-21 11:02:28 -05:00
|
|
|
;; The buckets themselves live inside in the dma buffer.
|
|
|
|
;; the addr field of their tag should point to the next bucket.
|
|
|
|
;; This is not a PS2 hardware thing
|
|
|
|
(deftype dma-bucket (structure)
|
|
|
|
((tag dma-tag :offset-assert 0) ;; the DMA tag to transfer the bucket's data
|
2021-04-17 18:35:50 -04:00
|
|
|
(last (pointer dma-tag) :offset-assert 8) ;; the last tag of this bucket.
|
2021-02-21 11:02:28 -05:00
|
|
|
(dummy uint32 :offset-assert 12) ;; empty space.
|
|
|
|
(next uint32 :offset 4) ;; this overlaps with the addr bit-field of the dma-tag
|
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x10
|
|
|
|
:flag-assert #x900000010
|
|
|
|
)
|
|
|
|
|
2021-04-16 18:36:19 -04:00
|
|
|
;; guess - VIF_MASK register?
|
2021-02-21 11:02:28 -05:00
|
|
|
(deftype vif-mask (uint32)
|
2021-04-16 18:36:19 -04:00
|
|
|
((m0 uint8 :offset 0 :size 2)
|
|
|
|
(m1 uint8 :offset 2 :size 2)
|
|
|
|
(m2 uint8 :offset 4 :size 2)
|
|
|
|
(m3 uint8 :offset 6 :size 2)
|
|
|
|
(m4 uint8 :offset 8 :size 2)
|
|
|
|
(m5 uint8 :offset 10 :size 2)
|
|
|
|
(m6 uint8 :offset 12 :size 2)
|
|
|
|
(m7 uint8 :offset 14 :size 2)
|
|
|
|
(m8 uint8 :offset 16 :size 2)
|
|
|
|
(m9 uint8 :offset 18 :size 2)
|
|
|
|
(m10 uint8 :offset 20 :size 2)
|
|
|
|
(m11 uint8 :offset 22 :size 2)
|
|
|
|
(m12 uint8 :offset 24 :size 2)
|
|
|
|
(m13 uint8 :offset 26 :size 2)
|
|
|
|
(m14 uint8 :offset 28 :size 2)
|
|
|
|
(m15 uint8 :offset 30 :size 2)
|
|
|
|
)
|
2021-02-21 11:02:28 -05:00
|
|
|
:flag-assert #x900000004
|
|
|
|
)
|
|
|
|
|
2021-04-16 18:36:19 -04:00
|
|
|
;; the IMM field of a VIF STCYCL instruction
|
2021-02-21 11:02:28 -05:00
|
|
|
(deftype vif-stcycl-imm (uint16)
|
2021-04-16 18:36:19 -04:00
|
|
|
((cl uint8 :offset 0 :size 8)
|
|
|
|
(wl uint8 :offset 8 :size 8)
|
|
|
|
)
|
2021-02-21 11:02:28 -05:00
|
|
|
:flag-assert #x900000002
|
|
|
|
)
|
|
|
|
|
2021-04-16 18:36:19 -04:00
|
|
|
;; the IMM field of a VIF UNPACK instruction
|
2021-02-21 11:02:28 -05:00
|
|
|
(deftype vif-unpack-imm (uint16)
|
2021-04-16 18:36:19 -04:00
|
|
|
((addr uint16 :offset 0 :size 10)
|
|
|
|
(usn uint8 :offset 14 :size 1)
|
|
|
|
(flg uint8 :offset 15 :size 1)
|
|
|
|
)
|
2021-02-21 11:02:28 -05:00
|
|
|
:flag-assert #x900000002
|
|
|
|
)
|
|
|
|
|
2021-04-17 18:35:50 -04:00
|
|
|
|
2021-04-23 20:29:15 -04:00
|
|
|
;; all these have mask (only applies to unpacks) and interrupt not set.
|
2021-04-17 18:35:50 -04:00
|
|
|
(defenum vif-cmd
|
|
|
|
:bitfield #f
|
2021-04-23 20:29:15 -04:00
|
|
|
:type uint8
|
|
|
|
(nop 0) ;; no-op, can still have irq set.
|
|
|
|
(stcycl 1) ;; set write recycle register
|
|
|
|
(offset 2) ;; set offset register
|
|
|
|
(base 3) ;; set base register
|
|
|
|
(itop 4) ;; set data pointer register (itops)
|
|
|
|
(stmod 5) ;; set mode register
|
|
|
|
(mskpath3 6) ;; set path 3 mask
|
|
|
|
(mark 7) ;; set mark register
|
2021-09-26 11:41:58 -04:00
|
|
|
(pc-port 8) ;; special tag for PC Port data.
|
2021-04-23 20:29:15 -04:00
|
|
|
(flushe 16) ;; wait for end of microprogram
|
|
|
|
(flush 17) ;; wait for end of microprogram and transfer (path1/path2)
|
|
|
|
(flusha 19) ;; wait for end of microprogram and transfer (path1/path2/path3)
|
|
|
|
(mscal 20) ;; activate microprogram (call)
|
|
|
|
(mscalf 21) ;; flushe and activate (call)
|
|
|
|
(mscnt 23) ;; activate microprogram (continue)
|
|
|
|
(stmask 32) ;; set MASK register.
|
|
|
|
(strow 48) ;; set filling data
|
|
|
|
(stcol 49) ;; set filling data
|
|
|
|
(mpg 74) ;; transfer microprogram
|
|
|
|
(direct 80) ;; straight to GIF.
|
|
|
|
(directhl 81)
|
|
|
|
(unpack-s-32 96)
|
|
|
|
(unpack-s-16 97)
|
|
|
|
(unpack-s-8 98)
|
|
|
|
;; 99 is invllid
|
|
|
|
(unpack-v2-32 100)
|
|
|
|
(unpack-v2-16 101)
|
|
|
|
(unpack-v2-8 102)
|
|
|
|
;; 103 is invalid
|
|
|
|
(unpack-v3-32 104)
|
|
|
|
(unpack-v3-16 105)
|
|
|
|
(unpack-v3-8 106)
|
|
|
|
;; 107 is invalid
|
|
|
|
(unpack-v4-32 108)
|
|
|
|
(unpack-v4-16 109)
|
|
|
|
(unpack-v4-8 110)
|
|
|
|
(unpack-v4-5 111)
|
2021-04-25 14:48:54 -04:00
|
|
|
(cmd-mask 239) ;; not sure what this is.
|
2021-04-23 20:29:15 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
;; this makes a copy of the above type, but uses a uint32.
|
|
|
|
(defenum vif-cmd-32
|
|
|
|
:bitfield #f
|
|
|
|
:type uint32
|
|
|
|
:copy-entries vif-cmd
|
2021-04-17 18:35:50 -04:00
|
|
|
)
|
|
|
|
|
2021-02-21 11:02:28 -05:00
|
|
|
;; The VIF also has tags to control it.
|
2021-08-01 17:11:32 -04:00
|
|
|
;; Different VIF commands (called VIFcode) have different tag layouts.
|
2021-02-21 11:02:28 -05:00
|
|
|
(deftype vif-tag (uint32)
|
2021-04-23 20:29:15 -04:00
|
|
|
((imm uint16 :offset 0 :size 16)
|
|
|
|
(num uint8 :offset 16 :size 8)
|
|
|
|
(cmd vif-cmd :offset 24 :size 7)
|
|
|
|
(irq uint8 :offset 31 :size 1)
|
|
|
|
(msk uint8 :offset 28 :size 1)
|
2021-02-21 11:02:28 -05:00
|
|
|
)
|
|
|
|
:method-count-assert 9
|
|
|
|
:size-assert #x4
|
|
|
|
:flag-assert #x900000004
|
|
|
|
)
|
|
|
|
|
|
|
|
(defmethod inspect vif-tag ((obj vif-tag))
|
|
|
|
(format #t "~Timm: #x~X~%" (-> obj imm))
|
|
|
|
(format #t "~Tnum: ~D~%" (-> obj num))
|
|
|
|
(format #t "~Tcmd: ~D~%" (-> obj cmd))
|
|
|
|
(format #t "~Tirq: ~D~%" (-> obj irq))
|
|
|
|
(format #t "~Tmsk: ~D~%" (-> obj msk))
|
|
|
|
obj
|
|
|
|
)
|
|
|
|
|
|
|
|
;; NOTE: these functions are never called
|
|
|
|
;; so they are not really modified for x86-64
|
|
|
|
;; they were inline assembly originally
|
|
|
|
|
|
|
|
(defun dma-sync-fast ((bank dma-bank))
|
|
|
|
"Wait for chcr str to go to 0, indicating DMA
|
|
|
|
is complete."
|
|
|
|
(declare (inline))
|
|
|
|
(#cond
|
|
|
|
(INSTANT_DMA
|
|
|
|
;; nothing to do.
|
|
|
|
0
|
|
|
|
)
|
|
|
|
(#t
|
|
|
|
(while (nonzero? (-> bank chcr str))
|
|
|
|
;; they had a precise number of nops here.
|
|
|
|
;; it turns out that spamming the DMA registers is not a good idea
|
|
|
|
;; because it uses the main bus that the DMA is possibly also trying to use.
|
|
|
|
(nop!)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
(none)
|
|
|
|
)
|
|
|
|
|
|
|
|
(defun dma-send-no-scratch ((bank dma-bank)
|
|
|
|
(madr uint32)
|
|
|
|
(qwc uint32))
|
|
|
|
"Begin a DMA transfer, directly to the bank.
|
|
|
|
Makes sure any ongoing transfer on the channel is done
|
|
|
|
Flushes the cache. Sets dir to 0, so I don't expect
|
|
|
|
this to be used for VIF1 transfers.
|
2021-04-11 16:07:01 -04:00
|
|
|
Madr should not be a scratchpad address.
|
|
|
|
This function is unused."
|
2021-02-21 11:02:28 -05:00
|
|
|
((inline dma-sync-fast) bank)
|
|
|
|
(flush-cache 0)
|
2021-04-16 18:36:19 -04:00
|
|
|
(.sync.l)
|
2021-02-21 11:02:28 -05:00
|
|
|
(set! (-> bank madr) madr)
|
|
|
|
(set! (-> bank qwc) qwc)
|
2021-04-16 18:36:19 -04:00
|
|
|
(.sync.l)
|
2021-02-21 11:02:28 -05:00
|
|
|
|
2021-04-16 18:36:19 -04:00
|
|
|
;; this seems wrong, they set everything to 0,
|
2021-02-21 11:02:28 -05:00
|
|
|
;; including dir, which is the to-memory direction
|
|
|
|
(set! (-> bank chcr)
|
|
|
|
(new 'static 'dma-chcr :str 1)
|
|
|
|
)
|
|
|
|
(none)
|
|
|
|
)
|
|
|
|
|
|
|
|
(defun dma-sync-with-count ((bank dma-bank)
|
|
|
|
(count (pointer int32)))
|
|
|
|
"Wait for DMA to finish, incrementing count.
|
|
|
|
This doesn't seem like a very accurate way
|
2021-04-11 16:07:01 -04:00
|
|
|
to find out how long it takes...
|
|
|
|
This function is unused."
|
2021-02-21 11:02:28 -05:00
|
|
|
(#cond
|
|
|
|
(INSTANT_DMA
|
|
|
|
(set! (-> count) INSTANT_DMA_COUNT)
|
|
|
|
0
|
|
|
|
)
|
|
|
|
(#t
|
|
|
|
(when (nonzero? (-> bank chcr str))
|
|
|
|
(let ((x (-> count)))
|
|
|
|
(while (nonzero? (-> bank chcr str))
|
|
|
|
(+! x 1)
|
|
|
|
(set! (-> count) x)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
0
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
(defun dma-count-until-done ((bank dma-bank)
|
|
|
|
(count (pointer int32)))
|
2021-04-11 16:07:01 -04:00
|
|
|
"Like the previous one, kinda.
|
|
|
|
This function is unused."
|
2021-02-21 11:02:28 -05:00
|
|
|
(#cond
|
|
|
|
(INSTANT_DMA
|
|
|
|
(set! (-> count) INSTANT_DMA_COUNT)
|
|
|
|
0
|
|
|
|
)
|
|
|
|
(#t
|
|
|
|
(while (nonzero? (-> bank chcr str))
|
|
|
|
(set! (-> count) (+ 1 (-> count)))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|