m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kbuild1
-rw-r--r--harddoom.h951
-rw-r--r--harddoom_main.c (renamed from harddoom.c)12
-rw-r--r--pci.c74
-rw-r--r--pci.h7
5 files changed, 1045 insertions, 0 deletions
diff --git a/Kbuild b/Kbuild
index 9916bfb..d4a3e64 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1 +1,2 @@
obj-m := harddoom.o
+harddoom-objs := harddoom_main.o pci.o
diff --git a/harddoom.h b/harddoom.h
new file mode 100644
index 0000000..119016c
--- /dev/null
+++ b/harddoom.h
@@ -0,0 +1,951 @@
+#ifndef HARDDOOM_H
+#define HARDDOOM_H
+
+/* PCI ids */
+
+#define HARDDOOM_VENDOR_ID 0x0666
+#define HARDDOOM_DEVICE_ID 0x1993
+
+/* Registers */
+
+/* Enables active units of the device. TLB is passive and doesn't have
+ * an enable (disable XY or TEX instead). FIFOs other than the main one
+ * also don't have enables -- disable the source and/or destination unit
+ * instead. */
+#define HARDDOOM_ENABLE 0x000
+#define HARDDOOM_ENABLE_FETCH_CMD 0x00000001
+#define HARDDOOM_ENABLE_FIFO 0x00000002
+#define HARDDOOM_ENABLE_FE 0x00000004
+#define HARDDOOM_ENABLE_XY 0x00000008
+#define HARDDOOM_ENABLE_TEX 0x00000010
+#define HARDDOOM_ENABLE_FLAT 0x00000020
+#define HARDDOOM_ENABLE_FUZZ 0x00000040
+#define HARDDOOM_ENABLE_SR 0x00000080
+#define HARDDOOM_ENABLE_OG 0x00000100
+#define HARDDOOM_ENABLE_SW 0x00000200
+#define HARDDOOM_ENABLE_ALL 0x000003ff
+/* Status of device units -- 1 means they have work to do. */
+#define HARDDOOM_STATUS 0x004
+#define HARDDOOM_STATUS_FETCH_CMD 0x00000001
+#define HARDDOOM_STATUS_FIFO 0x00000002
+#define HARDDOOM_STATUS_FE 0x00000004
+#define HARDDOOM_STATUS_XY 0x00000008
+#define HARDDOOM_STATUS_TEX 0x00000010
+#define HARDDOOM_STATUS_FLAT 0x00000020
+#define HARDDOOM_STATUS_FUZZ 0x00000040
+#define HARDDOOM_STATUS_SR 0x00000080
+#define HARDDOOM_STATUS_OG 0x00000100
+#define HARDDOOM_STATUS_SW 0x00000200
+#define HARDDOOM_STATUS_FE2XY 0x00000400
+#define HARDDOOM_STATUS_FE2TEX 0x00000800
+#define HARDDOOM_STATUS_FE2FLAT 0x00001000
+#define HARDDOOM_STATUS_FE2FUZZ 0x00002000
+#define HARDDOOM_STATUS_FE2OG 0x00004000
+#define HARDDOOM_STATUS_XY2SW 0x00008000
+#define HARDDOOM_STATUS_XY2SR 0x00010000
+#define HARDDOOM_STATUS_SR2OG 0x00020000
+#define HARDDOOM_STATUS_TEX2OG 0x00040000
+#define HARDDOOM_STATUS_FLAT2OG 0x00080000
+#define HARDDOOM_STATUS_FUZZ2OG 0x00100000
+#define HARDDOOM_STATUS_OG2SW 0x00200000
+#define HARDDOOM_STATUS_OG2SW_C 0x00400000
+#define HARDDOOM_STATUS_SW2XY 0x00800000
+/* The reset register. Punching 1 will clear all pending work. There is
+ * no reset for FETCH_CMD (initialize CMD_*_PTR instead). */
+#define HARDDOOM_RESET 0x004
+#define HARDDOOM_RESET_FIFO 0x00000002
+#define HARDDOOM_RESET_FE 0x00000004
+#define HARDDOOM_RESET_XY 0x00000008
+#define HARDDOOM_RESET_TEX 0x00000010
+#define HARDDOOM_RESET_FLAT 0x00000020
+#define HARDDOOM_RESET_FUZZ 0x00000040
+#define HARDDOOM_RESET_SR 0x00000080
+#define HARDDOOM_RESET_OG 0x00000100
+#define HARDDOOM_RESET_SW 0x00000200
+#define HARDDOOM_RESET_FE2XY 0x00000400
+#define HARDDOOM_RESET_FE2TEX 0x00000800
+#define HARDDOOM_RESET_FE2FLAT 0x00001000
+#define HARDDOOM_RESET_FE2FUZZ 0x00002000
+#define HARDDOOM_RESET_FE2OG 0x00004000
+#define HARDDOOM_RESET_XY2SW 0x00008000
+#define HARDDOOM_RESET_XY2SR 0x00010000
+#define HARDDOOM_RESET_SR2OG 0x00020000
+#define HARDDOOM_RESET_TEX2OG 0x00040000
+#define HARDDOOM_RESET_FLAT2OG 0x00080000
+#define HARDDOOM_RESET_FUZZ2OG 0x00100000
+#define HARDDOOM_RESET_OG2SW 0x00200000
+#define HARDDOOM_RESET_OG2SW_C 0x00400000
+#define HARDDOOM_RESET_SW2XY 0x00800000
+#define HARDDOOM_RESET_STATS 0x01000000
+#define HARDDOOM_RESET_TLB 0x02000000
+#define HARDDOOM_RESET_TEX_CACHE 0x04000000
+#define HARDDOOM_RESET_FLAT_CACHE 0x08000000
+#define HARDDOOM_RESET_ALL 0x0ffffffe
+/* Interrupt status. */
+#define HARDDOOM_INTR 0x008
+#define HARDDOOM_INTR_FENCE 0x00000001
+#define HARDDOOM_INTR_PONG_SYNC 0x00000002
+#define HARDDOOM_INTR_PONG_ASYNC 0x00000004
+#define HARDDOOM_INTR_FE_ERROR 0x00000008
+#define HARDDOOM_INTR_FIFO_OVERFLOW 0x00000010
+#define HARDDOOM_INTR_SURF_DST_OVERFLOW 0x00000020
+#define HARDDOOM_INTR_SURF_SRC_OVERFLOW 0x00000040
+#define HARDDOOM_INTR_PAGE_FAULT_SURF_DST 0x00000080
+#define HARDDOOM_INTR_PAGE_FAULT_SURF_SRC 0x00000100
+#define HARDDOOM_INTR_PAGE_FAULT_TEXTURE 0x00000200
+#define HARDDOOM_INTR_MASK 0x000003ff
+/* And enable (same bitfields). */
+#define HARDDOOM_INTR_ENABLE 0x00c
+/* The last value of processed FENCE command. */
+#define HARDDOOM_FENCE_LAST 0x010
+#define HARDDOOM_FENCE_MASK 0x03ffffff
+/* The value that will trigger a FENCE interrupt when used in FENCE command. */
+#define HARDDOOM_FENCE_WAIT 0x014
+/* Command read pointer -- whenever not equal to CMD_WRITE_PTR, FETCH_CMD will
+ * fetch command from here and increment. */
+#define HARDDOOM_CMD_READ_PTR 0x018
+/* Command write pointer -- FETCH_CMD halts when it hits this address. */
+#define HARDDOOM_CMD_WRITE_PTR 0x01c
+
+
+/* The FE (Front End) unit. Its task is to digest FIFO commands into simple
+ * commands for individual blocks (XY, TEX, FLAT, FUZZ, OG). Since this is
+ * quite a complicated task, it is a microcoded engine. */
+
+/* Front End microcode window. Any access to _DATA will access the code RAM
+ * cell selected by _ADDR and bump _ADDR by one. Each cell is one 30-bit
+ * instruction. */
+#define HARDDOOM_FE_CODE_ADDR 0x020
+#define HARDDOOM_FE_CODE_WINDOW 0x024
+#define HARDDOOM_FE_CODE_SIZE 0x00001000
+/* Front End error reporting -- when the microcode detects an error in the
+ * command stream, it triggers the FE_ERROR interrupt, writes the offending
+ * command to _CMD, and writes the error code to _CODE. */
+#define HARDDOOM_FE_ERROR_CODE 0x028
+/* Unknown command type. */
+#define HARDDOOM_FE_ERROR_CODE_RESERVED_TYPE 0x00000000
+/* Known command type with non-0 value in reserved bits. */
+#define HARDDOOM_FE_ERROR_CODE_RESERVED_BITS 0x00000001
+/* SURF_DIMS with WIDTH == 0. */
+#define HARDDOOM_FE_ERROR_CODE_SURF_WIDTH_ZERO 0x00000002
+/* SURF_DIMS with HEIGHT == 0. */
+#define HARDDOOM_FE_ERROR_CODE_SURF_HEIGHT_ZERO 0x00000003
+/* SURF_DIMS with WIDTH > 2048. */
+#define HARDDOOM_FE_ERROR_CODE_SURF_WIDTH_OVF 0x00000004
+/* SURF_DIMS with HEIGHT > 2048. */
+#define HARDDOOM_FE_ERROR_CODE_SURF_HEIGHT_OVF 0x00000005
+/* COPY_RECT or FILL_RECT destination X+WIDTH > SURF_DIMS.WIDTH. */
+#define HARDDOOM_FE_ERROR_CODE_RECT_DST_X_OVF 0x00000006
+/* COPY_RECT or FILL_RECT destionation Y+HEIGHT > SURF_DIMS.HEIGHT. */
+#define HARDDOOM_FE_ERROR_CODE_RECT_DST_Y_OVF 0x00000007
+/* COPY_RECT source X+WIDTH > SURF_DIMS.WIDTH. */
+#define HARDDOOM_FE_ERROR_CODE_RECT_SRC_X_OVF 0x00000008
+/* COPY_RECT source Y+HEIGHT > SURF_DIMS.HEIGHT. */
+#define HARDDOOM_FE_ERROR_CODE_RECT_SRC_Y_OVF 0x00000009
+/* DRAW_COLUMN XY_A.Y > XY_B.Y. */
+#define HARDDOOM_FE_ERROR_CODE_DRAW_COLUMN_REV 0x0000000a
+/* DRAW_SPAN XY_A.X > XY_B.X. */
+#define HARDDOOM_FE_ERROR_CODE_DRAW_SPAN_REV 0x0000000b
+#define HARDDOOM_FE_ERROR_CODE_MASK 0x00000fff
+#define HARDDOOM_FE_ERROR_CMD 0x02c
+/* Direct command submission (goes to FIFO bypassing FETCH_CMD). */
+#define HARDDOOM_FIFO_SEND 0x030
+/* Read-only number of free slots in FIFO. */
+#define HARDDOOM_FIFO_FREE 0x030
+/* The FE state -- microcode program counter and "waiting for FIFO" flag. */
+#define HARDDOOM_FE_STATE 0x034
+#define HARDDOOM_FE_STATE_PC_MASK 0x00000fff
+#define HARDDOOM_FE_STATE_WAIT_FIFO 0x00001000
+#define HARDDOOM_FE_STATE_MASK 0x00001fff
+/* Internal state of the main FIFO -- read and write pointers.
+ * There are 0x200 entries, indexed by 10-bit indices (each entry is visible
+ * under two indices). Bits 0-9 is read pointer (index of the next entry to
+ * be read by DRAW), 16-25 is write pointer (index of the next entry to be
+ * written by FIFO_SEND). FIFO is empty iff read == write, full iff read ==
+ * write ^ 0x200. Situations where ((write - read) & 0x3ff) > 0x200
+ * are illegal and won't be reached in proper operation of the device.
+ * Other FIFOs are similar, but with different sizes and entry types.
+ */
+#define HARDDOOM_FIFO_STATE 0x038
+/* The window to the FIFO (internal). When read, reads from READ_PTR,
+ * and increments it. When written, writes to WRITE_PTR, and increments
+ * it. If this causes a FIFO overflow/underflow, so be it. */
+#define HARDDOOM_FIFO_WINDOW 0x03c
+#define HARDDOOM_FIFO_SIZE 0x00000200
+/* The FE data memory window -- behaves like the code window. Used by
+ * the microcode to store data arrays. */
+#define HARDDOOM_FE_DATA_ADDR 0x040
+#define HARDDOOM_FE_DATA_WINDOW 0x044
+#define HARDDOOM_FE_DATA_SIZE 0x00000200
+/* The FE -> XY command FIFO (see XYCMD definitions below). */
+#define HARDDOOM_FE2XY_STATE 0x048
+#define HARDDOOM_FE2XY_WINDOW 0x04c
+#define HARDDOOM_FE2XY_SIZE 0x00000080
+/* The FE -> TEX command FIFO (see TEXCMD definitions below). */
+#define HARDDOOM_FE2TEX_STATE 0x050
+#define HARDDOOM_FE2TEX_WINDOW 0x054
+#define HARDDOOM_FE2TEX_SIZE 0x00000080
+/* The FE -> FLAT command FIFO (see FLCMD definitions below). */
+#define HARDDOOM_FE2FLAT_STATE 0x058
+#define HARDDOOM_FE2FLAT_WINDOW 0x05c
+#define HARDDOOM_FE2FLAT_SIZE 0x00000080
+/* The FE -> FUZZ command FIFO (see FZCMD definitions below). */
+#define HARDDOOM_FE2FUZZ_STATE 0x060
+#define HARDDOOM_FE2FUZZ_WINDOW 0x064
+#define HARDDOOM_FE2FUZZ_SIZE 0x00000080
+/* The FE -> OG command FIFO (see OGCMD definitions below). */
+#define HARDDOOM_FE2OG_STATE 0x068
+#define HARDDOOM_FE2OG_WINDOW 0x06c
+#define HARDDOOM_FE2OG_SIZE 0x00000080
+/* The FE registers, for use as variables by the microcode. */
+#define HARDDOOM_FE_REG(i) (0x080 + (i) * 4)
+#define HARDDOOM_FE_REG_NUM 0x20
+
+
+/* The STATS unit. */
+
+/* The indices are listed below. */
+#define HARDDOOM_STATS(i) (0x100 + (i) * 4)
+#define HARDDOOM_STATS_NUM 0x40
+
+/* The FE stats (counted by microcode). */
+/* A COPY_RECT command was processed as a series of horizontally drawn lines. */
+#define HARDDOOM_STAT_FE_COPY_RECT_HORIZONTAL 0x00
+/* A line was drawn as part of the above. */
+#define HARDDOOM_STAT_FE_COPY_RECT_LINE 0x01
+/* A COPY_RECT command was processed as a vertical series of blocks. */
+#define HARDDOOM_STAT_FE_COPY_RECT_VERTICAL 0x02
+/* Like the above 3, but for FILL_RECT. */
+#define HARDDOOM_STAT_FE_FILL_RECT_HORIZONTAL 0x03
+#define HARDDOOM_STAT_FE_FILL_RECT_LINE 0x04
+#define HARDDOOM_STAT_FE_FILL_RECT_VERTICAL 0x05
+/* A DRAW_LINE command was processed as mostly-horizontal. */
+#define HARDDOOM_STAT_FE_DRAW_LINE_HORIZONTAL 0x06
+/* Ditto, mostly-vertical. */
+#define HARDDOOM_STAT_FE_DRAW_LINE_VERTICAL 0x07
+/* A chunk of pixels (X×1 rectangle) was drawn for
+ * a mostly-horizontal line. */
+#define HARDDOOM_STAT_FE_DRAW_LINE_H_CHUNK 0x08
+/* A chunk of pixels (1×X rectangle) was drawn for
+ * a mostly-vertical line. */
+#define HARDDOOM_STAT_FE_DRAW_LINE_V_CHUNK 0x09
+/* A pixel was drawn for a mostly-horizontal line. */
+#define HARDDOOM_STAT_FE_DRAW_LINE_H_PIXEL 0x0a
+/* A pixel was drawn for a mostly-vertical line. */
+#define HARDDOOM_STAT_FE_DRAW_LINE_V_PIXEL 0x0b
+/* A DRAW_BACKGROUND command was processed. */
+#define HARDDOOM_STAT_FE_DRAW_BACKGROUND 0x0c
+/* A batch of DRAW_COLUMN commands without FUZZ was processed (to count
+ * invididual columns, see TEX_COLUMN counter). */
+#define HARDDOOM_STAT_FE_DRAW_COLUMN_TEX_BATCH 0x0d
+/* A batch of DRAW_COLUMN commands with FUZZ was processed (to count
+ * individual columns, see FUZZ_COLUMN counter). */
+#define HARDDOOM_STAT_FE_DRAW_COLUMN_FUZZ_BATCH 0x0e
+/* A DRAW_SPAN command was processed. */
+#define HARDDOOM_STAT_FE_DRAW_SPAN 0x0f
+
+/* Various FIFO flow statistics. */
+/* A command was sent to FE (from FIFO_SEND or FETCH_CMD). */
+#define HARDDOOM_STAT_FE_CMD 0x10
+/* A command was sent to XY by FE. */
+#define HARDDOOM_STAT_XY_CMD 0x11
+/* A command was sent to TEX by FE. */
+#define HARDDOOM_STAT_TEX_CMD 0x12
+/* A command was sent to FLAT by FE. */
+#define HARDDOOM_STAT_FLAT_CMD 0x13
+/* A command was sent to FUZZ by FE. */
+#define HARDDOOM_STAT_FUZZ_CMD 0x14
+/* A command was sent to OG by FE. */
+#define HARDDOOM_STAT_OG_CMD 0x15
+/* A command was sent to SW by OG. */
+#define HARDDOOM_STAT_SW_CMD 0x16
+/* A block of pixels was read from a surface by SR and sent to OG. */
+#define HARDDOOM_STAT_SR_BLOCK 0x17
+/* A block of pixels was textured by TEX and sent to OG. */
+#define HARDDOOM_STAT_TEX_BLOCK 0x18
+/* A block of pixels was read or textured by FLAT and sent to OG. */
+#define HARDDOOM_STAT_FLAT_BLOCK 0x19
+/* A block mask was prepared by FUZZ and sent to OG. */
+#define HARDDOOM_STAT_FUZZ_BLOCK 0x1a
+/* A block of pixels was prepared by OG and sent to SW to be written to a surface. */
+#define HARDDOOM_STAT_SW_BLOCK 0x1b
+
+/* TLB statistics. */
+/* TLB hits and misses for all 3 TLBs. */
+#define HARDDOOM_STAT_TLB_SURF_DST_HIT 0x1c
+#define HARDDOOM_STAT_TLB_SURF_DST_MISS 0x1d
+#define HARDDOOM_STAT_TLB_SURF_SRC_HIT 0x1e
+#define HARDDOOM_STAT_TLB_SURF_SRC_MISS 0x1f
+#define HARDDOOM_STAT_TLB_TEXTURE_HIT 0x20
+#define HARDDOOM_STAT_TLB_TEXTURE_MISS 0x21
+/* A SURF_*_PT command was processed by XY. */
+#define HARDDOOM_STAT_TLB_REBIND_SURF_DST 0x22
+#define HARDDOOM_STAT_TLB_REBIND_SURF_SRC 0x23
+/* A TEXTURE_PT command was processed by TEX. */
+#define HARDDOOM_STAT_TLB_REBIND_TEXTURE 0x24
+
+/* XY statistics. */
+/* An INTERLOCK command was processed by XY. */
+#define HARDDOOM_STAT_XY_INTERLOCK 0x25
+
+/* TEX statistics. */
+/* A START_COLUMN command was processed by TEX (equivalent to count of front
+ * DRAW_COLUMN commands without FUZZ). */
+#define HARDDOOM_STAT_TEX_COLUMN 0x26
+/* A pixel was textured by the TEX unit. */
+#define HARDDOOM_STAT_TEX_PIXEL 0x27
+/* A texture cache hit on the currently textured pixel. */
+#define HARDDOOM_STAT_TEX_CACHE_HIT 0x28
+/* A texture cache hit on a speculative pixel (causing it to be pre-textured). */
+#define HARDDOOM_STAT_TEX_CACHE_SPEC_HIT 0x29
+/* A texture cache miss on the currently textured pixel (ie. a cache fill). */
+#define HARDDOOM_STAT_TEX_CACHE_MISS 0x2a
+/* A texture cache miss on a speculative pixel (no cache fill). */
+#define HARDDOOM_STAT_TEX_CACHE_SPEC_MISS 0x2b
+
+/* FLAT statistics. */
+/* A FLAT_ADDR command was processed by FLAT. */
+#define HARDDOOM_STAT_FLAT_REBIND 0x2c
+/* A block was sent to OG by the READ_FLAT command. */
+#define HARDDOOM_STAT_FLAT_READ_BLOCK 0x2d
+/* A block was sent to OG by the DRAW_SPAN command. */
+#define HARDDOOM_STAT_FLAT_SPAN_BLOCK 0x2e
+/* A pixel was textured by the DRAW_SPAN command. */
+#define HARDDOOM_STAT_FLAT_SPAN_PIXEL 0x2f
+/* A flat cache hit. */
+#define HARDDOOM_STAT_FLAT_CACHE_HIT 0x30
+/* A flat cache miss (and fill). */
+#define HARDDOOM_STAT_FLAT_CACHE_MISS 0x31
+
+/* FUZZ statistics. */
+/* A SET_COLUMN command was processed by FUZZ (equivalent to count of front
+ * DRAW_COLUMN commands with FUZZ). */
+#define HARDDOOM_STAT_FUZZ_COLUMN 0x32
+
+/* OG statistics. */
+/* A COLORMAP_ADDR command was processed by OG (ie. the main color map was
+ * read from memory. */
+#define HARDDOOM_STAT_OG_COLORMAP_FETCH 0x33
+/* A TRANSLATION_ADDR command was processed by OG (ie. the translation color
+ * map was read from memory. */
+#define HARDDOOM_STAT_OG_TRANSLATION_FETCH 0x34
+/* A block was sent to SW by the DRAW_BUF_* command. */
+#define HARDDOOM_STAT_OG_DRAW_BUF_BLOCK 0x35
+/* A pixel was sent to SW by the DRAW_BUF_* command. */
+#define HARDDOOM_STAT_OG_DRAW_BUF_PIXEL 0x36
+/* A block was sent to SW by the COPY_* command. */
+#define HARDDOOM_STAT_OG_COPY_BLOCK 0x37
+/* A pixel was sent to SW by the COPY_* command. */
+#define HARDDOOM_STAT_OG_COPY_PIXEL 0x38
+/* A pixel was sent to SW by the DRAW_FUZZ command. */
+#define HARDDOOM_STAT_OG_FUZZ_PIXEL 0x39
+/* A block was processed by the translation color map. */
+#define HARDDOOM_STAT_OG_TRANSLATE_BLOCK 0x3a
+/* A block was processed by the main color map, not including the FUZZ effect. */
+#define HARDDOOM_STAT_OG_COLORMAP_BLOCK 0x3b
+
+/* SW statistics. */
+/* A FENCE command was processed by SW. */
+#define HARDDOOM_STAT_SW_FENCE 0x3c
+/* A FENCE command was processed by SW that matched the FENCE_WAIT register. */
+#define HARDDOOM_STAT_SW_FENCE_INTR 0x3d
+/* A pixel was written to memory by SW. */
+#define HARDDOOM_STAT_SW_PIXEL 0x3e
+/* A contiguous group of pixels was written to memory by SW. */
+#define HARDDOOM_STAT_SW_XFER 0x3f
+
+
+/* The XY unit. Its responsibility is to translate (X, Y) coordinates in
+ * the surfaces into physical addresses and to send them to SR and SW
+ * units. Since SR and SW operate on 64-pixel blocks, the X coordinates
+ * here are 5-bit and are counted in blocks. Widths are likewise 6-bit and
+ * counted in blocks. The FE unit requests translation in horizontal
+ * or vertical batches, by giving the starting (X, Y) coordinate and
+ * width or height of the batch. The XY unit can have two batches
+ * active at a moment -- one for the source surface and one for the
+ * destination surface. Also, the XY unit handles one half of the INTERLOCK
+ * command (by listening on the SW2XY interface for receipt of the other
+ * half by SW and blocking all operations until then). */
+
+/* Copy of the last processed SURF_DIMS command. */
+#define HARDDOOM_XY_SURF_DIMS 0x200
+#define HARDDOOM_XY_SURF_DIMS_MASK 0x000fff3f
+/* The command currently pending. */
+#define HARDDOOM_XY_CMD 0x204
+/* The destination address command currently being executed. */
+#define HARDDOOM_XY_DST_CMD 0x208
+/* The source address command currently being executed. */
+#define HARDDOOM_XY_SRC_CMD 0x20c
+/* The XY -> SW FIFO (with physical addresses to be written by SW with data
+ * prepared by OG). */
+#define HARDDOOM_XY2SW_STATE 0x240
+#define HARDDOOM_XY2SW_WINDOW 0x244
+#define HARDDOOM_XY2SW_SIZE 0x00000080
+/* The XY -> SR FIFO (with physical addresses to be read by SR and sent
+ * to OG for processing). */
+#define HARDDOOM_XY2SR_STATE 0x248
+#define HARDDOOM_XY2SR_WINDOW 0x24c
+#define HARDDOOM_XY2SR_SIZE 0x00000080
+
+
+/* The SR (Surface Read) unit. It takes physical addresses from the XY unit,
+ * reads full blocks from them, and then submits them to the OG unit for
+ * processing. Stateless. Used to read source data for COPY_RECT and to
+ * read current data from the destination framebuffer to be modified by the
+ * FUZZ effect. */
+
+/* The SR -> OG FIFO. Each element is a 64-pixel block. */
+#define HARDDOOM_SR2OG_STATE 0x280
+/* The window is 64 bytes long. */
+#define HARDDOOM_SR2OG_WINDOW 0x2c0
+#define HARDDOOM_SR2OG_SIZE 0x00000020
+
+
+/* The TLB unit. Called by the XY and TEX units to translate virtual
+ * addresses to physical. */
+
+/* The current page table for each buffer. */
+#define HARDDOOM_TLB_PT_SURF_DST 0x300
+#define HARDDOOM_TLB_PT_SURF_SRC 0x304
+#define HARDDOOM_TLB_PT_TEXTURE 0x308
+#define HARDDOOM_TLB_PT_MASK 0xffffffc0
+/* The single-entry TLBs, one for each paged buffer. Bits 0 and 12+ are taken
+ * straight from the PTE. Bits 2-11 are the tag (bits 12-21 of the virtual
+ * address, ie. page table index). Bit 1 is the TLB valid bit.
+ */
+#define HARDDOOM_TLB_ENTRY_SURF_DST 0x310
+#define HARDDOOM_TLB_ENTRY_SURF_SRC 0x314
+#define HARDDOOM_TLB_ENTRY_TEXTURE 0x318
+#define HARDDOOM_TLB_ENTRY_MASK 0xffffffff
+#define HARDDOOM_TLB_ENTRY_PTE_VALID 0x00000001
+#define HARDDOOM_TLB_ENTRY_VALID 0x00000002
+#define HARDDOOM_TLB_ENTRY_IDX_MASK 0x00000ffc
+#define HARDDOOM_TLB_ENTRY_IDX_SHIFT 2
+#define HARDDOOM_TLB_ENTRY_PAGE_MASK 0xfffff000
+/* The last virtual address looked up in the TLB -- useful in case of
+ * page faults. */
+#define HARDDOOM_TLB_VADDR_SURF_DST 0x320
+#define HARDDOOM_TLB_VADDR_SURF_SRC 0x324
+#define HARDDOOM_TLB_VADDR_TEXTURE 0x328
+#define HARDDOOM_TLB_VADDR_MASK 0x003fffc0
+#define HARDDOOM_TLB_IDX_MASK 0x000003ff
+
+/* The FLAT unit. Gets flat coordinates and pixel count from the FE unit,
+ * reads the texels from the flat, and outputs textured pixels to the OG unit.
+ * The FE can request a single horizontal span at a time. Also, can bypass
+ * raw blocks from the flat directly to the OG (used for DRAW_BACKGROUND). */
+
+/* The current U and V coordinates (updated as pixels are textured). */
+#define HARDDOOM_FLAT_UCOORD 0x360
+#define HARDDOOM_FLAT_VCOORD 0x364
+/* The USTEP and VSTEP params are stored here. */
+#define HARDDOOM_FLAT_USTEP 0x368
+#define HARDDOOM_FLAT_VSTEP 0x36c
+#define HARDDOOM_FLAT_COORD_MASK 0x003fffff
+/* The address of the current flat. */
+#define HARDDOOM_FLAT_ADDR 0x370
+#define HARDDOOM_FLAT_ADDR_MASK 0xfffff000
+/* The command in progress. */
+#define HARDDOOM_FLAT_CMD 0x374
+/* The flat cache state. It has one 64-byte cache line. */
+#define HARDDOOM_FLAT_CACHE_STATE 0x378
+#define HARDDOOM_FLAT_CACHE_STATE_TAG_MASK 0x0000003f
+#define HARDDOOM_FLAT_CACHE_STATE_VALID 0x00000100
+#define HARDDOOM_FLAT_CACHE_STATE_MASK 0x0000013f
+/* The FLAT -> OG FIFO. Each element is a 64-pixel block. If the DRAW_SPAN
+ * width is not a multiple of 64, the last block is padded with random data. */
+#define HARDDOOM_FLAT2OG_STATE 0x37c
+#define HARDDOOM_FLAT2OG_WINDOW 0x380
+#define HARDDOOM_FLAT2OG_SIZE 0x00000020
+#define HARDDOOM_FLAT_CACHE 0x3c0
+#define HARDDOOM_FLAT_CACHE_SIZE 64
+
+
+/* The SW unit. Gets final pixel data and write masks from the OG unit,
+ * and stores it to addresses received from the XY unit. Also, as the last
+ * unit in the pipeline, handles synchronization commands. */
+
+/* The command currently being processed. */
+#define HARDDOOM_SW_CMD 0x400
+/* The SW -> XY pseudo-FIFO used for INTERLOCKs. There is no actual data
+ * payload being transmitted -- the FIFO state is simply the number of
+ * INTERLOCKs sent by SW and not yet received by XY. */
+#define HARDDOOM_SW2XY_STATE 0x404
+#define HARDDOOM_SW2XY_STATE_MASK 0x000000ff
+
+
+/* The OG (output gather) unit. Responsible for gathering pixel data from
+ * FE, SR, TEX and FLAT, applying effects, preparing write masks, and sending
+ * the final pixel data to SW. The heart of this unit is a 4-block buffer.
+ * The buffer blocks are aligned with destination surface blocks -- blocks
+ * from SR and FLAT are rotated on input to match the destination alignment. */
+
+/* The write mask of the block to be rendered (64-bit register). */
+#define HARDDOOM_OG_MASK 0x480
+/* The FUZZ effect mask received from the FUZZ unit (64-bit register). */
+#define HARDDOOM_OG_FUZZ_MASK 0x488
+/* The command currently being processed. */
+#define HARDDOOM_OG_CMD 0x490
+/* Misc state. */
+#define HARDDOOM_OG_MISC 0x494
+/* The value of the last SRC_OFFSET command. */
+#define HARDDOOM_OG_MISC_SRC_OFFSET_MASK 0x0000003f
+/* The current position in the buffer (exact interpretation depends
+ * on the command). */
+#define HARDDOOM_OG_MISC_BUF_POS_MASK 0x0000ff00
+#define HARDDOOM_OG_MISC_BUF_POS_SHIFT 8
+/* The current state in the command execution state machine. Every command
+ * starts in the INIT state. The exact interpretation depends on the command. */
+#define HARDDOOM_OG_MISC_STATE_INIT 0x00000000
+#define HARDDOOM_OG_MISC_STATE_PREFILL 0x00010000
+#define HARDDOOM_OG_MISC_STATE_RUNNING 0x00020000
+#define HARDDOOM_OG_MISC_STATE_FILLED 0x00030000
+#define HARDDOOM_OG_MISC_STATE_MASK 0x00030000
+#define HARDDOOM_OG_MISC_MASK 0x0003ff3f
+/* The OG -> SW command FIFO (contains 32-bit commands). */
+#define HARDDOOM_OG2SW_C_STATE 0x4a0
+#define HARDDOOM_OG2SW_C_WINDOW 0x4a4
+#define HARDDOOM_OG2SW_C_SIZE 0x00000020
+/* The OG -> SW pixel data FIFO (each entry consists of a 64-byte block and
+ * a 64-bit write mask. */
+#define HARDDOOM_OG2SW_STATE 0x4b4
+#define HARDDOOM_OG2SW_M_WINDOW 0x4b8
+#define HARDDOOM_OG2SW_D_WINDOW 0x4c0
+#define HARDDOOM_OG2SW_SIZE 0x00000020
+/* The buffer. */
+#define HARDDOOM_OG_BUF 0x500
+#define HARDDOOM_OG_BUF_SIZE 0x00000100
+/* The current color maps (they are eagerly read in their entirety when FE
+ * requests so). */
+#define HARDDOOM_OG_COLORMAP 0x600
+#define HARDDOOM_OG_TRANSLATION 0x700
+
+
+/* The FUZZ unit. Responsible for generating pixel masks for the FUZZ
+ * effect. Capable of operating on a block of columns at once, with
+ * independent fuzz positions for each column. The FE unit computes
+ * and sets the initial fuzz position for each column, then sends FUZZ
+ * the number of masks to generate, letting it step the positions while
+ * the batch is being drawn. */
+
+/* The fuzz position for every column (64 single-byte registers). */
+#define HARDDOOM_FUZZ_POSITION 0x800
+/* The command in progress. */
+#define HARDDOOM_FUZZ_CMD 0x840
+/* The FUZZ -> OG FIFO. Each entry is a 64-bit mask. */
+#define HARDDOOM_FUZZ2OG_STATE 0x844
+#define HARDDOOM_FUZZ2OG_WINDOW 0x848
+#define HARDDOOM_FUZZ2OG_SIZE 0x00000020
+
+
+/* The TEX unit. Can handle 64 DRAW_COLUMN commands concurrently, merging
+ * them to a single stream of textured blocks. To optimize cache usage,
+ * when a pixel is textured, up to 0x10 pixels below it are speculatively
+ * textured as well if the required texels are on the currently active
+ * cache line. */
+
+/* A copy of the last submitted TEXTURE_DIMS command. */
+#define HARDDOOM_TEX_DIMS 0x850
+#define HARDDOOM_TEX_DIMS_MASK 0x03fff3ff
+/* The last submitted USTART command (will be copied to TEX_COLUMN_STATE
+ * by START_COLUMN). */
+#define HARDDOOM_TEX_USTART 0x854
+/* The last submitted USTEP command (will be copied to TEX_COLUMN_STEP
+ * by START_COLUMN). */
+#define HARDDOOM_TEX_USTEP 0x858
+#define HARDDOOM_TEX_COORD_MASK 0x03ffffff
+/* The command currently being executed. */
+#define HARDDOOM_TEX_CMD 0x85c
+/* The mask of currently active columns (64-bit register). */
+#define HARDDOOM_TEX_MASK 0x860
+/* The texture cache -- a single 64-byte line. */
+#define HARDDOOM_TEX_CACHE_STATE 0x868
+#define HARDDOOM_TEX_CACHE_STATE_TAG_MASK 0x0000ffff
+#define HARDDOOM_TEX_CACHE_STATE_VALID 0x00010000
+#define HARDDOOM_TEX_CACHE_STATE_MASK 0x0001ffff
+/* The position of the current block in the speculative texturing buffers. */
+#define HARDDOOM_TEX_CACHE_STATE_SPEC_POS_MASK 0x00f00000
+#define HARDDOOM_TEX_CACHE_STATE_SPEC_POS_SHIFT 20
+/* The TEX -> OG FIFO. Each entry consists of a 64-byte block and a 64-bit
+ * active column mask. */
+#define HARDDOOM_TEX2OG_STATE 0x874
+#define HARDDOOM_TEX2OG_M_WINDOW 0x878
+#define HARDDOOM_TEX2OG_D_WINDOW 0x880
+#define HARDDOOM_TEX2OG_SIZE 0x00000020
+#define HARDDOOM_TEX_CACHE 0x8c0
+#define HARDDOOM_TEX_CACHE_SIZE 64
+/* The current texture coordinate for each column, and the number of
+ * speculatively textured pixels available in the buffer. */
+#define HARDDOOM_TEX_COLUMN_STATE(i) (0x900 + (i) * 4)
+#define HARDDOOM_TEX_COLUMN_STATE_COORD_MASK 0x03ffffff
+#define HARDDOOM_TEX_COLUMN_STATE_SPEC_MASK 0x7c000000
+#define HARDDOOM_TEX_COLUMN_STATE_SPEC_SHIFT 26
+#define HARDDOOM_TEX_COLUMN_STATE_MASK 0x7fffffff
+/* The coordinate step for each column. */
+#define HARDDOOM_TEX_COLUMN_STEP(i) (0xa00 + (i) * 4)
+/* The starting texture offset for each column. */
+#define HARDDOOM_TEX_COLUMN_OFFSET(i) (0xb00 + (i) * 4)
+#define HARDDOOM_TEX_OFFSET_MASK 0x003fffff
+/* The speculatively textured pixels for each column. */
+#define HARDDOOM_TEX_COLUMN_SPEC_DATA(i) (0xc00 + (i) * 0x10)
+#define HARDDOOM_TEX_COLUMN_SPEC_DATA_SIZE 0x10
+
+
+/* The FETCH_CMD / FIFO / FE Commands. */
+
+/* Jump in the command buffer (only valid for FETCH_CMD). */
+#define HARDDOOM_CMD_TYPE_HI_JUMP 0x0
+
+/* Surface to render to, all commands. */
+#define HARDDOOM_CMD_TYPE_SURF_DST_PT 0x20
+/* Source surface for COPY_RECT, */
+#define HARDDOOM_CMD_TYPE_SURF_SRC_PT 0x21
+/* Texture for DRAW_COLUMN. */
+#define HARDDOOM_CMD_TYPE_TEXTURE_PT 0x22
+/* The flat for DRAW_BACKGROUND and DRAW_SPAN. */
+#define HARDDOOM_CMD_TYPE_FLAT_ADDR 0x23
+/* Fade/effect color map for DRAW_COLUMN and DRAW_SPAN, used iff DRAW_PARAMS_COLORMAP set. */
+#define HARDDOOM_CMD_TYPE_COLORMAP_ADDR 0x24
+/* Palette translation color map for DRAW_COLUMN and DRAW_SPAN, used iff DRAW_PARAMS_TRANSLATE set. */
+#define HARDDOOM_CMD_TYPE_TRANSLATION_ADDR 0x25
+/* Dimensions of all SURFs in use. */
+#define HARDDOOM_CMD_TYPE_SURF_DIMS 0x26
+/* Height and byte size of the texture for DRAW_COLUMN. */
+#define HARDDOOM_CMD_TYPE_TEXTURE_DIMS 0x27
+/* Solid fill color for FILL_RECT and DRAW_LINE. */
+#define HARDDOOM_CMD_TYPE_FILL_COLOR 0x28
+/* Flags for DRAW_COLUMN and DRAW_SPAN (FUZZ, TRANSLATE, COLORMAP).
+ */
+#define HARDDOOM_CMD_TYPE_DRAW_PARAMS 0x29
+/* Destination rect top left corner for COPY_RECT, FILL_RECT.
+ * First end point for DRAW_LINE.
+ * Top end point for DRAW_COLUMN.
+ * Left end point for DRAW_SPAN.
+ */
+#define HARDDOOM_CMD_TYPE_XY_A 0x2a
+/* Source rect corner top left for COPY_RECT.
+ * Second end point for DRAW_LINE.
+ * Botoom end point for DRAW_COLUMN.
+ * Right end point for DRAW_SPAN.
+ */
+#define HARDDOOM_CMD_TYPE_XY_B 0x2b
+/* Tex coord start for DRAW_COLUMN (U), DRAW_SPAN (U+V). */
+#define HARDDOOM_CMD_TYPE_USTART 0x2c
+#define HARDDOOM_CMD_TYPE_VSTART 0x2d
+/* Tex coord derivative for DRAW_COLUMN (U), DRAW_SPAN (U+V). */
+#define HARDDOOM_CMD_TYPE_USTEP 0x2e
+#define HARDDOOM_CMD_TYPE_VSTEP 0x2f
+
+/* V_CopyRect: The usual blit. Rectangle size passed directly. */
+#define HARDDOOM_CMD_TYPE_COPY_RECT 0x30
+/* V_FillRect: The usual solid fill. Rectangle size passed directly. */
+#define HARDDOOM_CMD_TYPE_FILL_RECT 0x31
+/* V_DrawLine: The usual solid line. */
+#define HARDDOOM_CMD_TYPE_DRAW_LINE 0x32
+/* V_DrawBackground: Fill whole FB with repeated flat. */
+#define HARDDOOM_CMD_TYPE_DRAW_BACKGROUND 0x33
+/* R_DrawColumn. */
+#define HARDDOOM_CMD_TYPE_DRAW_COLUMN 0x34
+/* R_DrawSpan. */
+#define HARDDOOM_CMD_TYPE_DRAW_SPAN 0x35
+
+/* Set the sync counter. */
+#define HARDDOOM_CMD_TYPE_FENCE 0x3c
+/* Trigger an interrupt once we're done with current work. */
+#define HARDDOOM_CMD_TYPE_PING_SYNC 0x3d
+/* Trigger an interrupt nowr. */
+#define HARDDOOM_CMD_TYPE_PING_ASYNC 0x3e
+/* Block further surface reads until inflight surface writes are complete. */
+#define HARDDOOM_CMD_TYPE_INTERLOCK 0x3f
+
+#define HARDDOOM_DRAW_PARAMS_FUZZ 0x1
+#define HARDDOOM_DRAW_PARAMS_TRANSLATE 0x2
+#define HARDDOOM_DRAW_PARAMS_COLORMAP 0x4
+
+#define HARDDOOM_CMD_JUMP(addr) (HARDDOOM_CMD_TYPE_HI_JUMP << 30 | (addr) >> 2)
+#define HARDDOOM_CMD_COPY_RECT(w, h) (HARDDOOM_CMD_TYPE_COPY_RECT << 26 | (h) << 12 | (w))
+#define HARDDOOM_CMD_FILL_RECT(w, h) (HARDDOOM_CMD_TYPE_FILL_RECT << 26 | (h) << 12 | (w))
+#define HARDDOOM_CMD_DRAW_LINE (HARDDOOM_CMD_TYPE_DRAW_LINE << 26)
+#define HARDDOOM_CMD_DRAW_BACKGROUND (HARDDOOM_CMD_TYPE_DRAW_BACKGROUND << 26)
+#define HARDDOOM_CMD_DRAW_COLUMN(iscale) (HARDDOOM_CMD_TYPE_DRAW_COLUMN << 26 | (iscale))
+#define HARDDOOM_CMD_DRAW_SPAN (HARDDOOM_CMD_TYPE_DRAW_SPAN << 26)
+#define HARDDOOM_CMD_SURF_DST_PT(addr) (HARDDOOM_CMD_TYPE_SURF_DST_PT << 26 | (addr) >> 6)
+#define HARDDOOM_CMD_SURF_SRC_PT(addr) (HARDDOOM_CMD_TYPE_SURF_SRC_PT << 26 | (addr) >> 6)
+#define HARDDOOM_CMD_TEXTURE_PT(addr) (HARDDOOM_CMD_TYPE_TEXTURE_PT << 26 | (addr) >> 6)
+#define HARDDOOM_CMD_FLAT_ADDR(addr) (HARDDOOM_CMD_TYPE_FLAT_ADDR << 26 | (addr) >> 12)
+#define HARDDOOM_CMD_COLORMAP_ADDR(addr) (HARDDOOM_CMD_TYPE_COLORMAP_ADDR << 26 | (addr) >> 8)
+#define HARDDOOM_CMD_TRANSLATION_ADDR(addr) (HARDDOOM_CMD_TYPE_TRANSLATION_ADDR << 26 | (addr) >> 8)
+#define HARDDOOM_CMD_SURF_DIMS(w, h) (HARDDOOM_CMD_TYPE_SURF_DIMS << 26 | (w) >> 6 | (h) << 8)
+#define HARDDOOM_CMD_TEXTURE_DIMS(sz, h) (HARDDOOM_CMD_TYPE_TEXTURE_DIMS << 26 | ((sz) - 1) >> 8 << 12 | (h))
+#define HARDDOOM_CMD_FILL_COLOR(color) (HARDDOOM_CMD_TYPE_FILL_COLOR << 26 | (color))
+#define HARDDOOM_CMD_DRAW_PARAMS(flags ) (HARDDOOM_CMD_TYPE_DRAW_PARAMS << 26 | (flags))
+#define HARDDOOM_CMD_XY_A(x, y) (HARDDOOM_CMD_TYPE_XY_A << 26 | (y) << 12 | (x))
+#define HARDDOOM_CMD_XY_B(x, y) (HARDDOOM_CMD_TYPE_XY_B << 26 | (y) << 12 | (x))
+#define HARDDOOM_CMD_USTART(arg) (HARDDOOM_CMD_TYPE_USTART << 26 | (arg))
+#define HARDDOOM_CMD_VSTART(arg) (HARDDOOM_CMD_TYPE_VSTART << 26 | (arg))
+#define HARDDOOM_CMD_USTEP(arg) (HARDDOOM_CMD_TYPE_USTEP << 26 | (arg))
+#define HARDDOOM_CMD_VSTEP(arg) (HARDDOOM_CMD_TYPE_VSTEP << 26 | (arg))
+#define HARDDOOM_CMD_FENCE(arg) (HARDDOOM_CMD_TYPE_FENCE << 26 | (arg))
+#define HARDDOOM_CMD_PING_SYNC (HARDDOOM_CMD_TYPE_PING_SYNC << 26)
+#define HARDDOOM_CMD_PING_ASYNC (HARDDOOM_CMD_TYPE_PING_ASYNC << 26)
+#define HARDDOOM_CMD_INTERLOCK (HARDDOOM_CMD_TYPE_INTERLOCK << 26)
+
+#define HARDDOOM_CMD_EXTR_TYPE_HI(cmd) ((cmd) >> 30 & 0x3)
+#define HARDDOOM_CMD_EXTR_JUMP_ADDR(cmd) ((cmd) << 2 & 0xfffffffc)
+#define HARDDOOM_CMD_EXTR_TYPE(cmd) ((cmd) >> 26 & 0x3f)
+#define HARDDOOM_CMD_EXTR_RECT_WIDTH(cmd) ((cmd) & 0xfff)
+#define HARDDOOM_CMD_EXTR_RECT_HEIGHT(cmd) ((cmd) >> 12 & 0xfff)
+#define HARDDOOM_CMD_EXTR_COLUMN_OFFSET(cmd) ((cmd) & 0x3fffff)
+#define HARDDOOM_CMD_EXTR_PT(cmd) (((cmd) & 0x3ffffff) << 6)
+#define HARDDOOM_CMD_EXTR_SURF_DIMS_WIDTH(cmd) (((cmd) & 0x3f) << 6)
+#define HARDDOOM_CMD_EXTR_SURF_DIMS_HEIGHT(cmd) (((cmd) & 0xfff00) >> 8)
+#define HARDDOOM_CMD_EXTR_TEXTURE_SIZE(cmd) ((((cmd) >> 12 & 0x3fff) + 1) << 8)
+#define HARDDOOM_CMD_EXTR_TEXTURE_HEIGHT(cmd) ((cmd) & 0x3ff)
+#define HARDDOOM_CMD_EXTR_FLAT_ADDR(cmd) (((cmd) & 0xfffff) << 12)
+#define HARDDOOM_CMD_EXTR_COLORMAP_ADDR(cmd) (((cmd) & 0xffffff) << 8)
+#define HARDDOOM_CMD_EXTR_FILL_COLOR(cmd) ((cmd) & 0xff)
+#define HARDDOOM_CMD_EXTR_XY_X(cmd) ((cmd) & 0x7ff)
+#define HARDDOOM_CMD_EXTR_XY_Y(cmd) ((cmd) >> 12 & 0x7ff)
+#define HARDDOOM_CMD_EXTR_TEX_COORD(cmd) ((cmd) & 0x3ffffff)
+#define HARDDOOM_CMD_EXTR_FENCE(cmd) ((cmd) & 0x3ffffff)
+
+
+/* XY unit internal commands. */
+
+#define HARDDOOM_XYCMD_PARAMS_MASK 0x0fffffff
+#define HARDDOOM_XYCMD_TYPE_SHIFT 28
+/* These 3 correspond directly to the FE commands. */
+#define HARDDOOM_XYCMD_TYPE_SURF_DST_PT 0x1
+#define HARDDOOM_XYCMD_TYPE_SURF_SRC_PT 0x2
+#define HARDDOOM_XYCMD_TYPE_SURF_DIMS 0x3
+/* Emits a series of addresses for a horizontal write to DST. */
+#define HARDDOOM_XYCMD_TYPE_WRITE_DST_H 0x4
+/* Emits a series of addresses for a vertical write to DST. */
+#define HARDDOOM_XYCMD_TYPE_WRITE_DST_V 0x5
+/* Emits a series of addresses for a horizontal read from SRC. */
+#define HARDDOOM_XYCMD_TYPE_READ_SRC_H 0x6
+/* Emits a series of addresses for a vertical read from SRC. */
+#define HARDDOOM_XYCMD_TYPE_READ_SRC_V 0x7
+/* Emits a series of addresses for a vertical read from DST. */
+#define HARDDOOM_XYCMD_TYPE_READ_DST_V 0x8
+/* Emits a series of addresses for a vertical read and write to DST (sending
+ * the same address stream to both SR and SW). */
+#define HARDDOOM_XYCMD_TYPE_RMW_DST_V 0x9
+/* One half of the interlock -- makes XY wait for the interlock signal from SW. */
+#define HARDDOOM_XYCMD_TYPE_INTERLOCK 0xa
+
+#define HARDDOOM_XYCMD_WRITE_DST_H(x, y, w) (HARDDOOM_XYCMD_TYPE_WRITE_DST_H << 28 | ((w) & 0x3f) << 16 | ((y) & 0x7ff) << 5 | ((x) & 0x1f))
+#define HARDDOOM_XYCMD_WRITE_DST_V(x, y, h) (HARDDOOM_XYCMD_TYPE_WRITE_DST_V << 28 | ((h) & 0xfff) << 16 | ((y) & 0x7ff) << 5 | ((x) & 0x1f))
+#define HARDDOOM_XYCMD_READ_DST_V(x, y, h) (HARDDOOM_XYCMD_TYPE_READ_DST_V << 28 | ((h) & 0xfff) << 16 | ((y) & 0x7ff) << 5 | ((x) & 0x1f))
+#define HARDDOOM_XYCMD_RMW_DST_V(x, y, h) (HARDDOOM_XYCMD_TYPE_RMW_DST_V << 28 | ((h) & 0xfff) << 16 | ((y) & 0x7ff) << 5 | ((x) & 0x1f))
+#define HARDDOOM_XYCMD_READ_SRC_H(x, y, w) (HARDDOOM_XYCMD_TYPE_READ_SRC_H << 28 | ((w) & 0x3f) << 16 | ((y) & 0x7ff) << 5 | ((x) & 0x1f))
+#define HARDDOOM_XYCMD_READ_SRC_V(x, y, h) (HARDDOOM_XYCMD_TYPE_READ_SRC_V << 28 | ((h) & 0xfff) << 16 | ((y) & 0x7ff) << 5 | ((x) & 0x1f))
+
+#define HARDDOOM_XYCMD_EXTR_TYPE(cmd) ((cmd) >> HARDDOOM_XYCMD_TYPE_SHIFT)
+/* For all READ/WRITE/RMW commands -- start X coordinate in blocks. */
+#define HARDDOOM_XYCMD_EXTR_X(cmd) ((cmd) & 0x1f)
+/* For all READ/WRITE/RMW commands -- start Y coordinate. */
+#define HARDDOOM_XYCMD_EXTR_Y(cmd) ((cmd) >> 5 & 0x7ff)
+/* For horizontal READ/WRITE commands -- width in blocks. */
+#define HARDDOOM_XYCMD_EXTR_WIDTH(cmd) ((cmd) >> 16 & 0x3f)
+/* For vertical READ/WRITE commands -- height. */
+#define HARDDOOM_XYCMD_EXTR_HEIGHT(cmd) ((cmd) >> 16 & 0xfff)
+
+
+/* TEX unit internal commands. */
+
+#define HARDDOOM_TEXCMD_PARAMS_MASK 0x0fffffff
+#define HARDDOOM_TEXCMD_TYPE_SHIFT 28
+/* These correspond directly to the FE commands. */
+#define HARDDOOM_TEXCMD_TYPE_TEXTURE_PT 0x1
+#define HARDDOOM_TEXCMD_TYPE_TEXTURE_DIMS 0x2
+#define HARDDOOM_TEXCMD_TYPE_USTART 0x3
+#define HARDDOOM_TEXCMD_TYPE_USTEP 0x4
+/* Enables given column slot, sets its texture offset, copies the last
+ * submitted USTEP value, and initializes current coordinate to the last
+ * submitted USTART value. */
+#define HARDDOOM_TEXCMD_TYPE_START_COLUMN 0x5
+/* Disables given column slot. */
+#define HARDDOOM_TEXCMD_TYPE_END_COLUMN 0x6
+/* Emits a given number of blocks to OG. The X parameter should always be 0
+ * -- it is incremented internally by TEX afterwards, to keep track of which
+ * pixels of a block have already been textured. */
+#define HARDDOOM_TEXCMD_TYPE_DRAW_TEX 0x7
+
+#define HARDDOOM_TEXCMD_TEXTURE_PT(addr) (HARDDOOM_TEXCMD_TYPE_TEXTURE_PT << 28 | (addr) >> 6)
+#define HARDDOOM_TEXCMD_TEXTURE_DIMS(sz, h) (HARDDOOM_TEXCMD_TYPE_TEXTURE_DIMS << 28 | ((sz) - 1) >> 8 << 12 | (h))
+#define HARDDOOM_TEXCMD_USTART(arg) (HARDDOOM_TEXCMD_TYPE_USTART << 28 | (arg))
+#define HARDDOOM_TEXCMD_USTEP(arg) (HARDDOOM_TEXCMD_TYPE_USTEP << 28 | (arg))
+#define HARDDOOM_TEXCMD_START_COLUMN(x, offset) (HARDDOOM_TEXCMD_TYPE_START_COLUMN << 28 | (offset) | (x) << 22)
+#define HARDDOOM_TEXCMD_END_COLUMN(x) (HARDDOOM_TEXCMD_TYPE_END_COLUMN << 28 | (x))
+#define HARDDOOM_TEXCMD_DRAW_TEX(h, x) (HARDDOOM_TEXCMD_TYPE_DRAW_TEX << 28 | (h) | (x) << 12)
+
+#define HARDDOOM_TEXCMD_EXTR_TYPE(cmd) ((cmd) >> HARDDOOM_TEXCMD_TYPE_SHIFT)
+#define HARDDOOM_TEXCMD_EXTR_START_X(cmd) ((cmd) >> 22 & 0x3f)
+#define HARDDOOM_TEXCMD_EXTR_END_X(cmd) ((cmd) & 0x3f)
+#define HARDDOOM_TEXCMD_EXTR_DRAW_X(cmd) ((cmd) >> 12 & 0x3f)
+#define HARDDOOM_TEXCMD_EXTR_DRAW_HEIGHT(cmd) ((cmd) & 0xfff)
+
+
+/* FLAT unit internal commands. */
+
+#define HARDDOOM_FLCMD_PARAMS_MASK 0x0fffffff
+#define HARDDOOM_FLCMD_TYPE_SHIFT 28
+/* Like the FE command. */
+#define HARDDOOM_FLCMD_TYPE_FLAT_ADDR 0x1
+/* Like the FE commands, but will be destroyed by rendering (need to be re-submitted). */
+#define HARDDOOM_FLCMD_TYPE_USTART 0x2
+#define HARDDOOM_FLCMD_TYPE_VSTART 0x3
+/* Like the FE commands. */
+#define HARDDOOM_FLCMD_TYPE_USTEP 0x4
+#define HARDDOOM_FLCMD_TYPE_VSTEP 0x5
+/* Reads N lines of a flat in a loop, starting from the given Y coordinate. */
+#define HARDDOOM_FLCMD_TYPE_READ_FLAT 0x6
+/* Emits a given number of textured pixels to the OG. The X parameter should
+ * always be 0 (it is incremented internally by the FLAT unit to keep track
+ * of how many pixels of a block have been textured so far). */
+#define HARDDOOM_FLCMD_TYPE_DRAW_SPAN 0x7
+
+#define HARDDOOM_FLCMD_FLAT_ADDR(addr) (HARDDOOM_FLCMD_TYPE_FLAT_ADDR << 28 | (addr) >> 12)
+#define HARDDOOM_FLCMD_USTART(arg) (HARDDOOM_FLCMD_TYPE_USTART << 28 | (arg))
+#define HARDDOOM_FLCMD_VSTART(arg) (HARDDOOM_FLCMD_TYPE_VSTART << 28 | (arg))
+#define HARDDOOM_FLCMD_USTEP(arg) (HARDDOOM_FLCMD_TYPE_USTEP << 28 | (arg))
+#define HARDDOOM_FLCMD_VSTEP(arg) (HARDDOOM_FLCMD_TYPE_VSTEP << 28 | (arg))
+#define HARDDOOM_FLCMD_READ_FLAT(h, y) (HARDDOOM_FLCMD_TYPE_READ_FLAT << 28 | (h) | (y) << 12)
+#define HARDDOOM_FLCMD_DRAW_SPAN(w, x) (HARDDOOM_FLCMD_TYPE_DRAW_SPAN << 28 | (w) | (x) << 12)
+
+#define HARDDOOM_FLCMD_EXTR_TYPE(cmd) ((cmd) >> HARDDOOM_FLCMD_TYPE_SHIFT)
+#define HARDDOOM_FLCMD_EXTR_COORD(cmd) ((cmd) & 0x3fffff)
+#define HARDDOOM_FLCMD_EXTR_READ_HEIGHT(cmd) ((cmd) & 0xfff)
+#define HARDDOOM_FLCMD_EXTR_READ_Y(cmd) ((cmd) >> 12 & 0x3f)
+#define HARDDOOM_FLCMD_EXTR_DRAW_WIDTH(cmd) ((cmd) & 0xfff)
+#define HARDDOOM_FLCMD_EXTR_DRAW_X(cmd) ((cmd) >> 12 & 0x3f)
+
+
+/* FUZZ unit internal commands. */
+
+#define HARDDOOM_FZCMD_PARAMS_MASK 0x0fffffff
+#define HARDDOOM_FZCMD_TYPE_SHIFT 28
+/* Sets the fuzz position for a given column. */
+#define HARDDOOM_FZCMD_TYPE_SET_COLUMN 0x1
+/* Emits a given number of block masks to the OG. */
+#define HARDDOOM_FZCMD_TYPE_DRAW_FUZZ 0x2
+
+#define HARDDOOM_FZCMD_SET_COLUMN(x, p) (HARDDOOM_FZCMD_TYPE_SET_COLUMN << 28 | (x) << 6 | (p))
+#define HARDDOOM_FZCMD_DRAW_FUZZ(h) (HARDDOOM_FZCMD_TYPE_DRAW_FUZZ << 28 | (h))
+
+#define HARDDOOM_FZCMD_EXTR_TYPE(cmd) ((cmd) >> HARDDOOM_FZCMD_TYPE_SHIFT)
+#define HARDDOOM_FZCMD_EXTR_X(cmd) ((cmd) >> 6 & 0x3f)
+#define HARDDOOM_FZCMD_EXTR_POS(cmd) ((cmd) & 0x3f)
+#define HARDDOOM_FZCMD_EXTR_HEIGHT(cmd) ((cmd) & 0xfff)
+
+
+/* OG unit internal commands. */
+
+#define HARDDOOM_OGCMD_PARAMS_MASK 0x03ffffff
+#define HARDDOOM_OGCMD_TYPE_SHIFT 26
+/* Tells SW to send the interlock signal on SW2XY. */
+#define HARDDOOM_OGCMD_TYPE_INTERLOCK 0x01
+/* Like the FE command, passed to SW. */
+#define HARDDOOM_OGCMD_TYPE_FENCE 0x02
+/* Like the FE PING_SYNC command, passed to SW. */
+#define HARDDOOM_OGCMD_TYPE_PING 0x03
+/* Fills the buffer with a solid color. */
+#define HARDDOOM_OGCMD_TYPE_FILL_COLOR 0x04
+/* Fetches the color map from the given address. */
+#define HARDDOOM_OGCMD_TYPE_COLORMAP_ADDR 0x05
+/* Fetches the translation map from the given address. */
+#define HARDDOOM_OGCMD_TYPE_TRANSLATION_ADDR 0x06
+/* Draws a horizontal stripe of pixels from buffer. */
+#define HARDDOOM_OGCMD_TYPE_DRAW_BUF_H 0x07
+/* Draws a vertical stripe of pixels from buffer. */
+#define HARDDOOM_OGCMD_TYPE_DRAW_BUF_V 0x08
+/* Draws a horizontal stripe of pixels from SR. */
+#define HARDDOOM_OGCMD_TYPE_COPY_H 0x09
+/* Draws a vertical stripe of pixels from SR. */
+#define HARDDOOM_OGCMD_TYPE_COPY_V 0x0a
+/* Sets the SR read offset. */
+#define HARDDOOM_OGCMD_TYPE_SRC_OFFSET 0x0b
+/* Reads a block from FLAT to the buffer */
+#define HARDDOOM_OGCMD_TYPE_READ_FLAT 0x0c
+/* Draws a horizontal stripe of pixels from FLAT. */
+#define HARDDOOM_OGCMD_TYPE_DRAW_SPAN 0x0d
+/* Reads pixels from SR, applies FUZZ effect, draws them. */
+#define HARDDOOM_OGCMD_TYPE_DRAW_FUZZ 0x0e
+/* Prepares for the above. */
+#define HARDDOOM_OGCMD_TYPE_INIT_FUZZ 0x0f
+/* Flips the given column in FUZZ draw mask. */
+#define HARDDOOM_OGCMD_TYPE_FUZZ_COLUMN 0x10
+/* Draws blocks straight from TEX. */
+#define HARDDOOM_OGCMD_TYPE_DRAW_TEX 0x11
+
+#define HARDDOOM_OGCMD_INTERLOCK (HARDDOOM_OGCMD_TYPE_INTERLOCK << 26)
+#define HARDDOOM_OGCMD_FENCE(f) (HARDDOOM_OGCMD_TYPE_FENCE << 26 | (f))
+#define HARDDOOM_OGCMD_PING (HARDDOOM_OGCMD_TYPE_PING << 26)
+#define HARDDOOM_OGCMD_FILL_COLOR(color) (HARDDOOM_OGCMD_TYPE_FILL_COLOR << 26 | (color))
+#define HARDDOOM_OGCMD_COLORMAP_ADDR(addr) (HARDDOOM_OGCMD_TYPE_COLORMAP_ADDR << 26 | (addr) >> 8)
+#define HARDDOOM_OGCMD_TRANSLATION_ADDR(addr) (HARDDOOM_OGCMD_TYPE_TRANSLATION_ADDR << 26 | (addr) >> 8)
+#define HARDDOOM_OGCMD_DRAW_BUF_H(x, w) (HARDDOOM_OGCMD_TYPE_DRAW_BUF_H << 26 | (x) | (w) << 6)
+#define HARDDOOM_OGCMD_DRAW_BUF_V(x, w, h) (HARDDOOM_OGCMD_TYPE_DRAW_BUF_V << 26 | (x) | (w) << 6 | (h) << 12)
+#define HARDDOOM_OGCMD_COPY_H(x, w) (HARDDOOM_OGCMD_TYPE_COPY_H << 26 | (x) | (w) << 6)
+#define HARDDOOM_OGCMD_COPY_V(x, w, h) (HARDDOOM_OGCMD_TYPE_COPY_V << 26 | (x) | (w) << 6 | (h) << 12)
+#define HARDDOOM_OGCMD_SRC_OFFSET(x) (HARDDOOM_OGCMD_TYPE_SRC_OFFSET << 26 | (x))
+#define HARDDOOM_OGCMD_READ_FLAT (HARDDOOM_OGCMD_TYPE_READ_FLAT << 26)
+#define HARDDOOM_OGCMD_DRAW_SPAN(x, w, f) (HARDDOOM_OGCMD_TYPE_DRAW_SPAN << 26 | (x) | (w) << 6 | (f) << 24)
+#define HARDDOOM_OGCMD_DRAW_FUZZ(h, f) (HARDDOOM_OGCMD_TYPE_DRAW_FUZZ << 26 | (h) | (f) << 24)
+#define HARDDOOM_OGCMD_INIT_FUZZ (HARDDOOM_OGCMD_TYPE_INIT_FUZZ << 26)
+#define HARDDOOM_OGCMD_FUZZ_COLUMN(x) (HARDDOOM_OGCMD_TYPE_FUZZ_COLUMN << 26 | (x))
+#define HARDDOOM_OGCMD_DRAW_TEX(h, f) (HARDDOOM_OGCMD_TYPE_DRAW_TEX << 26 | (h) | (f) << 24)
+
+#define HARDDOOM_OGCMD_EXTR_TYPE(cmd) ((cmd) >> HARDDOOM_OGCMD_TYPE_SHIFT)
+#define HARDDOOM_OGCMD_EXTR_X(cmd) ((cmd) & 0x3f)
+#define HARDDOOM_OGCMD_EXTR_H_WIDTH(cmd) ((cmd) >> 6 & 0xfff)
+#define HARDDOOM_OGCMD_EXTR_V_WIDTH(cmd) ((cmd) >> 6 & 0x3f)
+#define HARDDOOM_OGCMD_EXTR_V_HEIGHT(cmd) ((cmd) >> 12 & 0xfff)
+#define HARDDOOM_OGCMD_EXTR_TF_HEIGHT(cmd) ((cmd) & 0xfff)
+#define HARDDOOM_OGCMD_EXTR_FLAGS(cmd) ((cmd) >> 24 & 3)
+
+#define HARDDOOM_OGCMD_FLAG_TRANSLATE 1
+#define HARDDOOM_OGCMD_FLAG_COLORMAP 2
+
+
+/* SW unit internal commands. */
+
+#define HARDDOOM_SWCMD_PARAMS_MASK 0x03ffffff
+#define HARDDOOM_SWCMD_TYPE_SHIFT 26
+/* Will send the interlock signal on SW2XY. */
+#define HARDDOOM_SWCMD_TYPE_INTERLOCK 0x1
+/* Like the FE command. */
+#define HARDDOOM_SWCMD_TYPE_FENCE 0x2
+/* Like the FE PING_SYNC command. */
+#define HARDDOOM_SWCMD_TYPE_PING 0x3
+/* Draws a given number of blocks. */
+#define HARDDOOM_SWCMD_TYPE_DRAW 0x4
+
+#define HARDDOOM_SWCMD_INTERLOCK (HARDDOOM_SWCMD_TYPE_INTERLOCK << 26)
+#define HARDDOOM_SWCMD_FENCE(f) (HARDDOOM_SWCMD_TYPE_FENCE << 26 | (f))
+#define HARDDOOM_SWCMD_PING (HARDDOOM_SWCMD_TYPE_PING << 26)
+#define HARDDOOM_SWCMD_DRAW(b) (HARDDOOM_SWCMD_TYPE_DRAW << 26 | (b))
+
+#define HARDDOOM_SWCMD_EXTR_TYPE(cmd) ((cmd) >> HARDDOOM_SWCMD_TYPE_SHIFT)
+#define HARDDOOM_SWCMD_EXTR_BLOCKS(cmd) ((cmd) & 0xfff)
+
+
+/* Page tables */
+
+#define HARDDOOM_PTE_VALID 0x00000001
+#define HARDDOOM_PTE_PHYS_MASK 0xfffff000
+#define HARDDOOM_PAGE_SHIFT 12
+#define HARDDOOM_PAGE_SIZE 0x1000
+
+/* Misc */
+
+#define HARDDOOM_COORD_MASK 0x7ff
+#define HARDDOOM_COLORMAP_SIZE 0x100
+#define HARDDOOM_FLAT_SIZE 0x1000
+/* The block size in pixels / columns -- the source and destination surfaces
+ * are written in blocks of this many pixels, and texture/fuzz column batches
+ * are made of this many columns. Also happens to be the width of a flat. */
+#define HARDDOOM_BLOCK_SIZE 0x40
+
+#endif
diff --git a/harddoom.c b/harddoom_main.c
index fc4f5a0..9ffe62f 100644
--- a/harddoom.c
+++ b/harddoom_main.c
@@ -1,17 +1,29 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include "pci.h"
+
MODULE_LICENSE("GPL");
int harddoom_init(void)
{
+ int err = 0;
printk(KERN_INFO "Initializing harddoom\n");
+ err = pci_init();
+ if (err < 0) {
+ goto error;
+ }
+
return 0;
+
+error:
+ return err;
}
void harddoom_cleanup(void)
{
printk(KERN_INFO "Removing harddoom\n");
+ pci_cleanup();
}
module_init(harddoom_init);
diff --git a/pci.c b/pci.c
new file mode 100644
index 0000000..36f1ad8
--- /dev/null
+++ b/pci.c
@@ -0,0 +1,74 @@
+#include "pci.h"
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include "harddoom.h"
+
+int doom_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ printk(KERN_INFO "In probe\n");
+ return 0;
+}
+
+void doom_remove (struct pci_dev *dev)
+{
+ printk(KERN_INFO "In remove\n");
+}
+
+int doom_suspend (struct pci_dev *dev, pm_message_t state)
+{
+ printk(KERN_INFO "In suspend\n");
+ return 0;
+}
+
+int doom_suspend_late (struct pci_dev *dev, pm_message_t state)
+{
+ printk(KERN_INFO "In suspend_late\n");
+ return 0;
+}
+
+int doom_resume_early (struct pci_dev *dev)
+{
+ printk(KERN_INFO "In resume_early\n");
+ return 0;
+}
+
+int doom_resume (struct pci_dev *dev)
+{
+ printk(KERN_INFO "In resume\n");
+ return 0;
+}
+
+void doom_shutdown (struct pci_dev *dev)
+{
+ printk(KERN_INFO "In shutdown\n");
+}
+
+struct pci_device_id device_ids[1] = {
+ { PCI_DEVICE(HARDDOOM_VENDOR_ID, HARDDOOM_DEVICE_ID) }
+};
+
+struct pci_driver driver = {
+ .name = "harddoom",
+ .id_table = device_ids,
+ .probe = doom_probe,
+ .remove = doom_remove,
+ .suspend = doom_suspend,
+ .suspend_late = doom_suspend_late,
+ .resume_early = doom_resume_early,
+ .resume = doom_resume,
+ .shutdown = doom_shutdown
+};
+
+int pci_init(void)
+{
+ printk(KERN_INFO "In pci init\n");
+ return pci_register_driver(&driver);
+}
+
+void pci_cleanup(void)
+{
+ printk(KERN_INFO "In pci cleanup\n");
+ pci_unregister_driver(&driver);
+}
diff --git a/pci.h b/pci.h
new file mode 100644
index 0000000..377530e
--- /dev/null
+++ b/pci.h
@@ -0,0 +1,7 @@
+#ifndef PCI_H
+#define PCI_H
+
+int pci_init(void);
+void pci_cleanup(void);
+
+#endif