diff --git a/README.md b/README.md index 88eb080..18d7bac 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ **If you're looking for a functional Xbox emulator, check out [XQEMU](http://xqemu.com/) or [Cxbx-Reloaded](https://github.com/Cxbx-Reloaded/Cxbx-Reloaded).** +**This project is on an indefinite hold as the two above projects are much more +complete and functional.** + --- # StrikeBox @@ -66,16 +69,10 @@ $ ./strikebox-cli -m -b -d - macOS is currently unsupported. Feel free to submit a pull request to add support for this platform! -## Debugging Guest Code +## Kernel Debugging -The guest can be debugged using the GDB debugger. Once enabled, the emulator -will open a TCP socket upon startup and wait for the GDB debugger to connect. -Once connected, you can examine the CPU state, set breakpoints, single-step -instructions, etc. A sample .gdbinit file is provided with useful GDB default -settings to be loaded when you start GDB in this directory. - -Alternatively, on Windows, you can perform kernel debugging of the virtual Xbox -by creating a linked pair of virtual null-modem serial ports with [com0com](http://com0com.sourceforge.net/). +On Windows, you can perform kernel debugging of the virtual Xbox by creating a +linked pair of virtual null-modem serial ports with [com0com](http://com0com.sourceforge.net/). Use a Debug BIOS ROM and attach one side of the pair to the first Super I/O serial port, then connect [WinDbg or KD](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/) to the other side to begin kernel debugging. diff --git a/apps/cli/src/main.cpp b/apps/cli/src/main.cpp index 479b201..8f841a8 100644 --- a/apps/cli/src/main.cpp +++ b/apps/cli/src/main.cpp @@ -14,9 +14,9 @@ using namespace virt86; #ifdef _WIN32 char *basename(char *path) { - char name[MAX_PATH]; - char ext[MAX_PATH]; - if (_splitpath_s(path, NULL, 0, NULL, 0, name, MAX_PATH, ext, MAX_PATH)) { + char name[260]; + char ext[260]; + if (_splitpath_s(path, NULL, 0, NULL, 0, name, std::size(name), ext, std::size(ext))) { return NULL; } size_t len = strlen(name) + strlen(ext) + 1; @@ -81,7 +81,7 @@ int main(int argc, const char *argv[]) { bool foundPlatform = false; size_t platformIndex = 0; - for (size_t i = 0; i < ARRAYSIZE(PlatformFactories); i++) { + for (size_t i = 0; i < std::size(PlatformFactories); i++) { Platform& platform = PlatformFactories[i](); if (platform.GetInitStatus() == PlatformInitStatus::OK) { printf("%s loaded successfully\n", platform.GetName().c_str()); diff --git a/modules/core/include/strikebox/cxbxtimer.h b/modules/core/include/strikebox/cxbxtimer.h deleted file mode 100644 index 4557330..0000000 --- a/modules/core/include/strikebox/cxbxtimer.h +++ /dev/null @@ -1,67 +0,0 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->CxbxKrnl->Timer.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#ifndef TIMER_H -#define TIMER_H - -#include - -namespace strikebox { - -/* typedef of the timer object and the callback function */ -typedef void(*pTimerCB)(void*); -typedef struct _TimerObject { - int Type; // timer type (virtual or real) - std::atomic ExpireTime_MS; // when the timer expires (ms) - std::atomic_bool Exit; // indicates that the timer should be destroyed - pTimerCB Callback; // function to call when the timer expires - void* Opaque; // opaque argument to pass to the callback - unsigned int SlowdownFactor; // how much the time is slowed down (virtual clocks only) -} -TimerObject; - - -/* Timer exported functions */ -TimerObject* Timer_Create(pTimerCB Callback, void* Arg, unsigned int Factor); -void Timer_Start(TimerObject* Timer, uint64_t Expire_MS); -void Timer_Exit(TimerObject* Timer); -void Timer_ChangeExpireTime(TimerObject* Timer, uint64_t Expire_ms); -uint64_t GetTime_NS(TimerObject* Timer); -void Timer_Init(); - -#endif - -} diff --git a/modules/core/include/strikebox/gdbserver.h b/modules/core/include/strikebox/gdbserver.h deleted file mode 100644 index d80ae6c..0000000 --- a/modules/core/include/strikebox/gdbserver.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2017 Matt Borgerson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#pragma once - -#include -#ifdef _WIN32 -# define _WIN32_LEAN_AND_MEAN -//# include -# include -# pragma comment (lib, "ws2_32.lib") -#else -# include -# include -# include -# include -# include -#endif -#include -#include -#include -#include -#include -#include - -#include "virt86/virt86.hpp" - -namespace strikebox { - -#ifdef _WIN32 - typedef int socklen_t; - typedef int ssize_t; - - #define SOCKET_T SOCKET - inline int inet_aton(const char *cp, struct in_addr *inp); - inline int close(SOCKET socket); -#else - #define SOCKET_T int -#endif - -typedef uint32_t address; -typedef uint32_t reg; - -enum DBG_REGISTER { - DBG_CPU_I386_REG_EAX = 0, - DBG_CPU_I386_REG_ECX = 1, - DBG_CPU_I386_REG_EDX = 2, - DBG_CPU_I386_REG_EBX = 3, - DBG_CPU_I386_REG_ESP = 4, - DBG_CPU_I386_REG_EBP = 5, - DBG_CPU_I386_REG_ESI = 6, - DBG_CPU_I386_REG_EDI = 7, - DBG_CPU_I386_REG_PC = 8, - DBG_CPU_I386_REG_PS = 9, - DBG_CPU_I386_REG_CS = 10, - DBG_CPU_I386_REG_SS = 11, - DBG_CPU_I386_REG_DS = 12, - DBG_CPU_I386_REG_ES = 13, - DBG_CPU_I386_REG_FS = 14, - DBG_CPU_I386_REG_GS = 15, - DBG_CPU_I386_NUM_REGISTERS = 16 -}; - -struct dbg_state { - int signum; - reg registers[DBG_CPU_I386_NUM_REGISTERS]; -}; - -typedef int (*dbg_enc_func)(char *buf, size_t buf_len, const char *data, size_t data_len); -typedef int (*dbg_dec_func)(const char *buf, size_t buf_len, char *data, size_t data_len); - -class GdbServer { -protected: - virt86::VirtualProcessor& m_vp; - const char *m_bind_host; - int m_bind_port; - struct sockaddr_in m_bind_addr; - struct sockaddr_in m_peer_addr; - socklen_t m_peer_addr_len; - SOCKET_T m_sockfd, m_peer_sockfd; - struct dbg_state m_dbg_state; - - int dbg_sys_getc(void); - int dbg_sys_putchar(int ch); - int dbg_sys_mem_readb(address addr, char *val); - int dbg_sys_mem_writeb(address addr, char val); - int dbg_sys_continue(); - int dbg_sys_step(); - - // Communication functions - int dbg_write(const char *buf, size_t len); - int dbg_read(char *buf, size_t buf_len, size_t len); - - // String processing helper functions - static int dbg_is_printable_char(char ch); - static char dbg_get_digit(int val); - static int dbg_get_val(char digit, int base); - static int dbg_strtol(const char *str, size_t len, int base, const char **endptr); - - // Data encoding/decoding - static int dbg_enc_hex(char *buf, size_t buf_len, const char *data, size_t data_len); - static int dbg_dec_hex(const char *buf, size_t buf_len, char *data, size_t data_len); - static int dbg_enc_bin(char *buf, size_t buf_len, const char *data, size_t data_len); - static int dbg_dec_bin(const char *buf, size_t buf_len, char *data, size_t data_len); - - // Packet functions - int dbg_send_packet(const char *pkt, size_t pkt_len); - int dbg_recv_packet(char *pkt_buf, size_t pkt_buf_len, size_t *pkt_len); - int dbg_checksum(const char *buf, size_t len); - int dbg_recv_ack(void); - - // Packet creation helpers - int dbg_send_ok_packet(char *buf, size_t buf_len); - int dbg_send_conmsg_packet(char *buf, size_t buf_len, const char *msg); - int dbg_send_signal_packet(char *buf, size_t buf_len, char signal); - int dbg_send_error_packet(char *buf, size_t buf_len, char error); - - // Command functions - int dbg_mem_read(char *buf, size_t buf_len, address addr, size_t len, dbg_enc_func enc); - int dbg_mem_write(const char *buf, size_t buf_len, address addr, size_t len, dbg_dec_func dec); - - int dbg_main(); - -public: - GdbServer(virt86::VirtualProcessor& vp, const char *bind_host, int bind_port); - ~GdbServer(); - int Initialize(); - int WaitForConnection(); - int Debug(int signal); - int Shutdown(); -}; - -} diff --git a/modules/core/include/strikebox/hw/nv2a/defs.h b/modules/core/include/strikebox/hw/nv2a/defs.h deleted file mode 100644 index c571011..0000000 --- a/modules/core/include/strikebox/hw/nv2a/defs.h +++ /dev/null @@ -1,405 +0,0 @@ -#pragma once - -#include -#include -#include -#include "nv2a_int.h" - -namespace strikebox { - -#define NV2A_SIZE 0x01000000 - -#define NV_PMC_ADDR 0x00000000 -#define NV_PMC_SIZE 0x001000 -#define NV_PBUS_ADDR 0x00001000 -#define NV_PBUS_SIZE 0x001000 -#define NV_PFIFO_ADDR 0x00002000 -#define NV_PFIFO_SIZE 0x002000 -#define NV_PRMA_ADDR 0x00007000 -#define NV_PRMA_SIZE 0x001000 -#define NV_PVIDEO_ADDR 0x00008000 -#define NV_PVIDEO_SIZE 0x001000 -#define NV_PTIMER_ADDR 0x00009000 -#define NV_PTIMER_SIZE 0x001000 -#define NV_PCOUNTER_ADDR 0x0000A000 -#define NV_PCOUNTER_SIZE 0x001000 -#define NV_PVPE_ADDR 0x0000B000 -#define NV_PVPE_SIZE 0x001000 -#define NV_PTV_ADDR 0x0000D000 -#define NV_PTV_SIZE 0x001000 -#define NV_PRMFB_ADDR 0x000A0000 -#define NV_PRMFB_SIZE 0x020000 -#define NV_PRMVIO_ADDR 0x000C0000 -#define NV_PRMVIO_SIZE 0x001000 -#define NV_PFB_ADDR 0x00100000 -#define NV_PFB_SIZE 0x001000 -#define NV_PSTRAPS_ADDR 0x00101000 -#define NV_PSTRAPS_SIZE 0x001000 -#define NV_PGRAPH_ADDR 0x00400000 -#define NV_PGRAPH_SIZE 0x002000 -#define NV_PCRTC_ADDR 0x00600000 -#define NV_PCRTC_SIZE 0x001000 -#define NV_PRMCIO_ADDR 0x00601000 -#define NV_PRMCIO_SIZE 0x001000 -#define NV_PRAMDAC_ADDR 0x00680000 -#define NV_PRAMDAC_SIZE 0x001000 -#define NV_PRMDIO_ADDR 0x00681000 -#define NV_PRMDIO_SIZE 0x001000 -#define NV_PRAMIN_ADDR 0x00700000 -#define NV_PRAMIN_SIZE 0x100000 -#define NV_USER_ADDR 0x00800000 -#define NV_USER_SIZE 0x800000 - -class NV2ADevice; - -enum FifoMode { - FIFO_PIO = 0, - FIFO_DMA = 1, -}; - -enum FIFOEngine { - ENGINE_SOFTWARE = 0, - ENGINE_GRAPHICS = 1, - ENGINE_DVD = 2, -}; - -typedef struct VGACommonState { - uint8_t st00; // Status Register 0 - uint8_t st01; // Status Register 1 -} VGACommonState; - -typedef struct ImageBlitState { - uint32_t context_surfaces; - unsigned int operation; - unsigned int in_x, in_y; - unsigned int out_x, out_y; - unsigned int width, height; -} ImageBlitState; - -typedef struct KelvinState { - uint32_t dma_notifies; - uint32_t dma_state; - uint32_t dma_semaphore; - unsigned int semaphore_offset; -} KelvinState; - -typedef struct ContextSurfaces2DState { - uint32_t dma_image_source; - uint32_t dma_image_dest; - unsigned int color_format; - unsigned int source_pitch, dest_pitch; - uint32_t source_offset, dest_offset; -} ContextSurfaces2DState; - -typedef struct DMAObject { - unsigned int dma_class = 0; - unsigned int dma_target = 0; - uint32_t address = 0; - uint32_t limit = 0; -} DMAObject; - -typedef struct GraphicsObject { - uint8_t graphics_class = 0; - union { - ContextSurfaces2DState context_surfaces_2d; - - ImageBlitState image_blit; - - KelvinState kelvin; - } data; -} GraphicsObject; - -typedef struct GraphicsSubchannel { - uint32_t object_instance = 0; - GraphicsObject object; - uint32_t object_cache[5] = { 0 }; -} GraphicsSubchannel; - -typedef struct GraphicsContext { - bool channel_3d = false; - unsigned int subchannel = 0; -} GraphicsContext; - -typedef struct RAMHTEntry { - uint32_t handle = 0; - uint32_t instance = 0; - enum FIFOEngine engine = ENGINE_SOFTWARE; - unsigned int channel_id : 5; - bool valid = false; -} RAMHTEntry; - -typedef struct { - uint32_t offset; - uint32_t size; - void (*read)(NV2ADevice* nv2a, uint32_t addr, uint32_t *value, uint8_t size); - void (*write)(NV2ADevice* nv2a, uint32_t addr, uint32_t value, uint8_t size); -} NV2ABlockInfo; - -typedef struct { - uint32_t regs[NV_PVIDEO_SIZE]; -} NV2APVIDEO; - -typedef struct { - uint8_t cr_index = 0; - uint8_t cr[256] = { 0 }; /* CRT registers */ -} NV2APRMCIO; - -typedef struct { - // Interrupt status. Bits 0-30 are hardware interrupts, bit 31 is software interrupt. - // 1 if the relevant input interrupt line is active. - // Bits 0-30 are read-only, bit 31 can be written to set/clear the software interrupt. - // Bit 31 can only be set to 1 if software interrupts are enabled in INTR_MASK_*. - uint32_t pendingInterrupts = 0; - - // bit 0: hardware interrupt enable - if 1, and any of bits 0-30 of INTR_* are active, the corresponding output interrupt line will be asserted. - // bit 1: software interrupt enable - if 1, bit 31 of INTR_* is active, the corresponding output interrupt line will be asserted. - uint32_t enabledInterrupts = 0; -} NV2APMC; - -typedef struct Surface { - bool draw_dirty = false; - bool buffer_dirty = false; - bool write_enabled_cache = false; - unsigned int pitch = 0; - - uint32_t offset = 0; -} Surface; - -typedef struct SurfaceShape { - unsigned int z_format = 0; - unsigned int color_format = 0; - unsigned int zeta_format = 0; - unsigned int log_width = 0, log_height = 0; - unsigned int clip_x = 0, clip_y = 0; - unsigned int clip_width = 0, clip_height = 0; - unsigned int anti_aliasing = 0; -} SurfaceShape; - -typedef struct TextureShape { - bool cubemap = false; - unsigned int dimensionality = 0; - unsigned int color_format = 0; - unsigned int levels = 0; - unsigned int width = 0, height = 0, depth = 0; - - unsigned int min_mipmap_level = 0; - unsigned int max_mipmap_level = 0; - unsigned int pitch = 0; -} TextureShape; - -typedef struct TextureKey { - TextureShape state; - uint64_t data_hash = 0; - uint8_t* texture_data = nullptr; - uint8_t* palette_data = nullptr; -} TextureKey; - -typedef struct TextureBinding { - // FIXME: no OpenGL allowed here - //GLenum gl_target; - //GLuint gl_texture; - unsigned int refcnt = 0; -} TextureBinding; - -typedef struct NV2APGRAPH { - std::mutex mutex; - - uint32_t pending_interrupts = 0; - uint32_t enabled_interrupts = 0; - std::condition_variable interrupt_cond; - - uint32_t context_table = 0; - uint32_t context_address = 0; - - - unsigned int trapped_method = 0; - unsigned int trapped_subchannel = 0; - unsigned int trapped_channel_id = 0; - uint32_t trapped_data[2] = { 0 }; - uint32_t notify_source = 0; - - bool fifo_access = false; - std::condition_variable fifo_access_cond; - std::condition_variable flip_3d; - - unsigned int channel_id = 0; - bool channel_valid = false; - GraphicsContext context[NV2A_NUM_CHANNELS]; - - uint32_t dma_color = 0; - uint32_t dma_zeta = 0; - Surface surface_color; - Surface surface_zeta; - unsigned int surface_type = 0; - SurfaceShape surface_shape; - SurfaceShape last_surface_shape; - - uint32_t dma_a = 0; - uint32_t dma_b = 0; - //GLruCache *texture_cache; - bool texture_dirty[NV2A_MAX_TEXTURES] = { false }; - TextureBinding *texture_binding[NV2A_MAX_TEXTURES] = { nullptr }; - - //GHashTable *shader_cache; - //ShaderBinding *shader_binding; - - bool texture_matrix_enable[NV2A_MAX_TEXTURES] = { false }; - - /* FIXME: Move to NV_PGRAPH_BUMPMAT... */ - float bump_env_matrix[NV2A_MAX_TEXTURES - 1][4]; /* 3 allowed stages with 2x2 matrix each */ - - // FIXME: no OpenGL allowed here - ////wglContext *gl_context; - //GLuint gl_framebuffer; - //GLuint gl_color_buffer, gl_zeta_buffer; - GraphicsSubchannel subchannel_data[NV2A_NUM_SUBCHANNELS]; - - uint32_t dma_report = 0; - uint32_t report_offset = 0; - bool zpass_pixel_count_enable = 0; - unsigned int zpass_pixel_count_result = 0; - unsigned int gl_zpass_pixel_count_query_count = 0; - // FIXME: no OpenGL allowed here - //GLuint* gl_zpass_pixel_count_queries; - - uint32_t dma_vertex_a = 0; - uint32_t dma_vertex_b = 0; - - unsigned int primitive_mode = 0; - - bool enable_vertex_program_write = false; - - //uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE]; - - uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4] = { { 0 } }; - bool vsh_constants_dirty[NV2A_VERTEXSHADER_CONSTANTS] = { 0 }; - - /* lighting constant arrays */ - uint32_t ltctxa[NV2A_LTCTXA_COUNT][4] = { { 0 } }; - bool ltctxa_dirty[NV2A_LTCTXA_COUNT] = { false }; - uint32_t ltctxb[NV2A_LTCTXB_COUNT][4] = { { 0 } }; - bool ltctxb_dirty[NV2A_LTCTXB_COUNT] = { false }; - uint32_t ltc1[NV2A_LTC1_COUNT][4] = { { 0 } }; - bool ltc1_dirty[NV2A_LTC1_COUNT] = { false }; - - // should figure out where these are in lighting context - float light_infinite_half_vector[NV2A_MAX_LIGHTS][3] = { { 0 } }; - float light_infinite_direction[NV2A_MAX_LIGHTS][3] = { { 0 } }; - float light_local_position[NV2A_MAX_LIGHTS][3] = { { 0 } }; - float light_local_attenuation[NV2A_MAX_LIGHTS][3] = { { 0 } }; - - //VertexAttribute vertex_attributes[NV2A_VERTEXSHADER_ATTRIBUTES]; - - unsigned int inline_array_length = 0; - uint32_t inline_array[NV2A_MAX_BATCH_LENGTH] = { 0 }; - // FIXME: no OpenGL allowed here - //GLuint gl_inline_array_buffer; - - unsigned int inline_elements_length = 0; - uint32_t inline_elements[NV2A_MAX_BATCH_LENGTH] = { 0 }; - - unsigned int inline_buffer_length = 0; - - unsigned int draw_arrays_length = 0; - unsigned int draw_arrays_max_count = 0; - - // FIXME: no OpenGL allowed here - /* FIXME: Unknown size, possibly endless, 1000 will do for now */ - //GLint gl_draw_arrays_start[1000]; - //GLsizei gl_draw_arrays_count[1000]; - - //GLuint gl_element_buffer; - //GLuint gl_memory_buffer; - //GLuint gl_vertex_array; - - uint32_t regs[NV_PGRAPH_SIZE] = { 0 }; // TODO : union -} NV2APGRAPH; - -typedef struct { - uint32_t pendingInterrupts = 0; - uint32_t enabledInterrupts = 0; - uint32_t start = 0; - uint32_t regs[NV_PCRTC_SIZE] = { 0 }; // TODO : union -} NV2APCRTC; - -typedef struct { - uint32_t pending_interrupts = 0; - uint32_t enabled_interrupts = 0; - uint32_t numerator = 0; - uint32_t denominator = 0; - uint32_t alarm_time = 0; - uint32_t regs[NV_PTIMER_SIZE] = { 0 }; -} NV2APTIMER; - -typedef struct { - uint32_t core_clock_coeff = 0; - uint64_t core_clock_freq = 0; - uint32_t memory_clock_coeff = 0; - uint32_t video_clock_coeff = 0; - uint32_t regs[NV_PRAMDAC_SIZE] = { 0 }; -} NV2APRAMDAC; - -typedef struct CacheEntry { - unsigned int method : 14; - unsigned int subchannel : 3; - bool nonincreasing = false; - uint32_t parameter = 0; -} CacheEntry; - -typedef struct Cache1State { - unsigned int channel_id = 0; - FifoMode mode = FIFO_PIO; - - /* Pusher state */ - bool push_enabled = false; - bool dma_push_enabled = false; - bool dma_push_suspended = false; - uint32_t dma_instance = 0; - - bool method_nonincreasing = false; - unsigned int method : 14; - unsigned int subchannel : 3; - unsigned int method_count : 24; - uint32_t dcount = 0; - - bool subroutine_active = false; - uint32_t subroutine_return = 0; - uint32_t get_jmp_shadow = 0; - uint32_t rsvd_shadow = 0; - uint32_t data_shadow = 0; - uint32_t error = 0; - - bool pull_enabled = false; - enum FIFOEngine bound_engines[NV2A_NUM_SUBCHANNELS] = { ENGINE_SOFTWARE }; - enum FIFOEngine last_engine = ENGINE_SOFTWARE; - - /* The actual command queue */ - std::mutex mutex; - std::condition_variable cache_cond; - std::queue cache; - std::queue working_cache; -} Cache1State; - -typedef struct { - uint32_t pending_interrupts = 0; - uint32_t enabled_interrupts = 0; - Cache1State cache1; - uint32_t regs[NV_PFIFO_SIZE] = { 0 }; - std::thread puller_thread; -} NV2APFIFO; - -typedef struct { - uint32_t registers[NV_PFB_SIZE] = { 0 }; -} NV2APFB; - -typedef struct ChannelControl { - uint32_t dma_put = 0; - uint32_t dma_get = 0; - uint32_t ref = 0; -} ChannelControl; - -typedef struct { - ChannelControl channel_control[NV2A_NUM_CHANNELS]; -} NV2AUSER; - -} diff --git a/modules/core/include/strikebox/hw/nv2a/nv2a_int.h b/modules/core/include/strikebox/hw/nv2a/nv2a_int.h deleted file mode 100644 index cabd215..0000000 --- a/modules/core/include/strikebox/hw/nv2a/nv2a_int.h +++ /dev/null @@ -1,1291 +0,0 @@ -/* - * Portions of the code are based on XQEMU's Geforce NV2A implementation. - * The original copyright header is included below. - * - * Additional work by Ivan "StrikerX3" Oliveira. - */ -/* - * QEMU Geforce NV2A internal definitions - * - * Copyright (c) 2012 espes - * Copyright (c) 2015 Jannik Vogel - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#define NV_NUM_BLOCKS 21 -#define NV_PMC 0 /* card master control */ -#define NV_PBUS 1 /* bus control */ -#define NV_PFIFO 2 /* MMIO and DMA FIFO submission to PGRAPH and VPE */ -#define NV_PFIFO_CACHE 3 -#define NV_PRMA 4 /* access to BAR0/BAR1 from real mode */ -#define NV_PVIDEO 5 /* video overlay */ -#define NV_PTIMER 6 /* time measurement and time-based alarms */ -#define NV_PCOUNTER 7 /* performance monitoring counters */ -#define NV_PVPE 8 /* MPEG2 decoding engine */ -#define NV_PTV 9 /* TV encoder */ -#define NV_PRMFB 10 /* aliases VGA memory window */ -#define NV_PRMVIO 11 /* aliases VGA sequencer and graphics controller registers */ -#define NV_PFB 12 /* memory interface */ -#define NV_PSTRAPS 13 /* straps readout / override */ -#define NV_PGRAPH 14 /* accelerated 2d/3d drawing engine */ -#define NV_PCRTC 15 /* more CRTC controls */ -#define NV_PRMCIO 16 /* aliases VGA CRTC and attribute controller registers */ -#define NV_PRAMDAC 17 /* RAMDAC, cursor, and PLL control */ -#define NV_PRMDIO 18 /* aliases VGA palette registers */ -#define NV_PRAMIN 19 /* RAMIN access */ -#define NV_USER 20 /* PFIFO MMIO and DMA submission area */ - -#define NV_PMC_BOOT_0 0x00000000 -#define NV_PMC_INTR_0 0x00000100 -# define NV_PMC_INTR_0_PFIFO (1 << 8) -# define NV_PMC_INTR_0_PGRAPH (1 << 12) -# define NV_PMC_INTR_0_PTIMER (1 << 20) -# define NV_PMC_INTR_0_PCRTC (1 << 24) -# define NV_PMC_INTR_0_PBUS (1 << 28) -# define NV_PMC_INTR_0_SOFTWARE (1 << 31) -#define NV_PMC_INTR_EN_0 0x00000140 -# define NV_PMC_INTR_EN_0_HARDWARE 1 -# define NV_PMC_INTR_EN_0_SOFTWARE 2 -#define NV_PMC_ENABLE 0x00000200 -# define NV_PMC_ENABLE_PFIFO (1 << 8) -# define NV_PMC_ENABLE_PGRAPH (1 << 12) - - -/* These map approximately to the pci registers */ -#define NV_PBUS_PCI_NV_0 0x00000800 -# define NV_PBUS_PCI_NV_0_VENDOR_ID 0x0000FFFF -# define NV_CONFIG_PCI_NV_0_DEVICE_ID 0xFFFF0000 -#define NV_PBUS_PCI_NV_1 0x00000804 -#define NV_PBUS_PCI_NV_2 0x00000808 -# define NV_PBUS_PCI_NV_2_REVISION_ID 0x000000FF -# define NV_PBUS_PCI_NV_2_CLASS_CODE 0xFFFFFF00 - - -#define NV_PFIFO_INTR_0 0x00000100 -# define NV_PFIFO_INTR_0_CACHE_ERROR (1 << 0) -# define NV_PFIFO_INTR_0_RUNOUT (1 << 4) -# define NV_PFIFO_INTR_0_RUNOUT_OVERFLOW (1 << 8) -# define NV_PFIFO_INTR_0_DMA_PUSHER (1 << 12) -# define NV_PFIFO_INTR_0_DMA_PT (1 << 16) -# define NV_PFIFO_INTR_0_SEMAPHORE (1 << 20) -# define NV_PFIFO_INTR_0_ACQUIRE_TIMEOUT (1 << 24) -#define NV_PFIFO_INTR_EN_0 0x00000140 -# define NV_PFIFO_INTR_EN_0_CACHE_ERROR (1 << 0) -# define NV_PFIFO_INTR_EN_0_RUNOUT (1 << 4) -# define NV_PFIFO_INTR_EN_0_RUNOUT_OVERFLOW (1 << 8) -# define NV_PFIFO_INTR_EN_0_DMA_PUSHER (1 << 12) -# define NV_PFIFO_INTR_EN_0_DMA_PT (1 << 16) -# define NV_PFIFO_INTR_EN_0_SEMAPHORE (1 << 20) -# define NV_PFIFO_INTR_EN_0_ACQUIRE_TIMEOUT (1 << 24) -#define NV_PFIFO_RAMHT 0x00000210 -# define NV_PFIFO_RAMHT_BASE_ADDRESS 0x000001F0 -# define NV_PFIFO_RAMHT_SIZE 0x00030000 -# define NV_PFIFO_RAMHT_SIZE_4K 0 -# define NV_PFIFO_RAMHT_SIZE_8K 1 -# define NV_PFIFO_RAMHT_SIZE_16K 2 -# define NV_PFIFO_RAMHT_SIZE_32K 3 -# define NV_PFIFO_RAMHT_SEARCH 0x03000000 -# define NV_PFIFO_RAMHT_SEARCH_16 0 -# define NV_PFIFO_RAMHT_SEARCH_32 1 -# define NV_PFIFO_RAMHT_SEARCH_64 2 -# define NV_PFIFO_RAMHT_SEARCH_128 3 -#define NV_PFIFO_RAMFC 0x00000214 -# define NV_PFIFO_RAMFC_BASE_ADDRESS1 0x000001FC -# define NV_PFIFO_RAMFC_SIZE 0x00010000 -# define NV_PFIFO_RAMFC_BASE_ADDRESS2 0x00FE0000 -#define NV_PFIFO_RAMRO 0x00000218 -# define NV_PFIFO_RAMRO_BASE_ADDRESS 0x000001FE -# define NV_PFIFO_RAMRO_SIZE 0x00010000 -#define NV_PFIFO_RUNOUT_STATUS 0x00000400 -# define NV_PFIFO_RUNOUT_STATUS_RANOUT (1 << 0) -# define NV_PFIFO_RUNOUT_STATUS_LOW_MARK (1 << 4) -# define NV_PFIFO_RUNOUT_STATUS_HIGH_MARK (1 << 8) -#define NV_PFIFO_MODE 0x00000504 -#define NV_PFIFO_DMA 0x00000508 -#define NV_PFIFO_CACHE1_PUSH0 0x00001200 -# define NV_PFIFO_CACHE1_PUSH0_ACCESS (1 << 0) -#define NV_PFIFO_CACHE1_PUSH1 0x00001204 -# define NV_PFIFO_CACHE1_PUSH1_CHID 0x0000001F -# define NV_PFIFO_CACHE1_PUSH1_MODE 0x00000100 -# define NV_PFIFO_CACHE1_PUSH1_MODE_PIO 0 -# define NV_PFIFO_CACHE1_PUSH1_MODE_DMA 1 -#define NV_PFIFO_CACHE1_PUT 0x00001210 -#define NV_PFIFO_CACHE1_STATUS 0x00001214 -# define NV_PFIFO_CACHE1_STATUS_LOW_MARK (1 << 4) -# define NV_PFIFO_CACHE1_STATUS_HIGH_MARK (1 << 8) -#define NV_PFIFO_CACHE1_DMA_PUSH 0x00001220 -# define NV_PFIFO_CACHE1_DMA_PUSH_ACCESS (1 << 0) -# define NV_PFIFO_CACHE1_DMA_PUSH_STATE (1 << 4) -# define NV_PFIFO_CACHE1_DMA_PUSH_BUFFER (1 << 8) -# define NV_PFIFO_CACHE1_DMA_PUSH_STATUS (1 << 12) -# define NV_PFIFO_CACHE1_DMA_PUSH_ACQUIRE (1 << 16) -#define NV_PFIFO_CACHE1_DMA_FETCH 0x00001224 -# define NV_PFIFO_CACHE1_DMA_FETCH_TRIG 0x000000F8 -# define NV_PFIFO_CACHE1_DMA_FETCH_SIZE 0x0000E000 -# define NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS 0x001F0000 -#define NV_PFIFO_CACHE1_DMA_STATE 0x00001228 -# define NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE (1 << 0) -# define NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE_INC 0 -# define NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE_NON_INC 1 -# define NV_PFIFO_CACHE1_DMA_STATE_METHOD 0x00001FFC -# define NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL 0x0000E000 -# define NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT 0x1FFC0000 -# define NV_PFIFO_CACHE1_DMA_STATE_ERROR 0xE0000000 -# define NV_PFIFO_CACHE1_DMA_STATE_ERROR_NONE 0 -# define NV_PFIFO_CACHE1_DMA_STATE_ERROR_CALL 1 -# define NV_PFIFO_CACHE1_DMA_STATE_ERROR_NON_CACHE 2 -# define NV_PFIFO_CACHE1_DMA_STATE_ERROR_RETURN 3 -# define NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD 4 -# define NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION 6 -#define NV_PFIFO_CACHE1_DMA_INSTANCE 0x0000122C -# define NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS 0x0000FFFF -#define NV_PFIFO_CACHE1_DMA_PUT 0x00001240 -#define NV_PFIFO_CACHE1_DMA_GET 0x00001244 -#define NV_PFIFO_CACHE1_REF 0x00001248 -#define NV_PFIFO_CACHE1_DMA_SUBROUTINE 0x0000124C -# define NV_PFIFO_CACHE1_DMA_SUBROUTINE_RETURN_OFFSET 0x1FFFFFFC -# define NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE (1 << 0) -#define NV_PFIFO_CACHE1_PULL0 0x00001250 -# define NV_PFIFO_CACHE1_PULL0_ACCESS (1 << 0) -#define NV_PFIFO_CACHE1_PULL1 0x00001254 -# define NV_PFIFO_CACHE1_PULL1_ENGINE 0x00000003 -#define NV_PFIFO_CACHE1_GET 0x00001270 -#define NV_PFIFO_CACHE1_ENGINE 0x00001280 -#define NV_PFIFO_CACHE1_DMA_DCOUNT 0x000012A0 -# define NV_PFIFO_CACHE1_DMA_DCOUNT_VALUE 0x00001FFC -#define NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW 0x000012A4 -# define NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW_OFFSET 0x1FFFFFFC -#define NV_PFIFO_CACHE1_DMA_RSVD_SHADOW 0x000012A8 -#define NV_PFIFO_CACHE1_DMA_DATA_SHADOW 0x000012AC -#define NV_PFIFO_CACHE1_METHOD 0x00001800 -# define NV_PFIFO_CACHE1_METHOD_TYPE (1 << 0) -# define NV_PFIFO_CACHE1_METHOD_ADDRESS 0x00001FFC -# define NV_PFIFO_CACHE1_METHOD_SUBCHANNEL 0x0000E000 -#define NV_PFIFO_CACHE1_DATA 0x00001804 - -#define NV_PGRAPH_DEBUG_3 0x0000008C -# define NV_PGRAPH_DEBUG_3_HW_CONTEXT_SWITCH (1 << 2) -#define NV_PGRAPH_INTR 0x00000100 -# define NV_PGRAPH_INTR_NOTIFY (1 << 0) -# define NV_PGRAPH_INTR_MISSING_HW (1 << 4) -# define NV_PGRAPH_INTR_TLB_PRESENT_DMA_R (1 << 6) -# define NV_PGRAPH_INTR_TLB_PRESENT_DMA_W (1 << 7) -# define NV_PGRAPH_INTR_TLB_PRESENT_TEX_A (1 << 8) -# define NV_PGRAPH_INTR_TLB_PRESENT_TEX_B (1 << 9) -# define NV_PGRAPH_INTR_TLB_PRESENT_VTX (1 << 10) -# define NV_PGRAPH_INTR_CONTEXT_SWITCH (1 << 12) -# define NV_PGRAPH_INTR_STATE3D (1 << 13) -# define NV_PGRAPH_INTR_BUFFER_NOTIFY (1 << 16) -# define NV_PGRAPH_INTR_ERROR (1 << 20) -# define NV_PGRAPH_INTR_SINGLE_STEP (1 << 24) -#define NV_PGRAPH_NSOURCE 0x00000108 -# define NV_PGRAPH_NSOURCE_NOTIFICATION (1 << 0) -#define NV_PGRAPH_INTR_EN 0x00000140 -# define NV_PGRAPH_INTR_EN_NOTIFY (1 << 0) -# define NV_PGRAPH_INTR_EN_MISSING_HW (1 << 4) -# define NV_PGRAPH_INTR_EN_TLB_PRESENT_DMA_R (1 << 6) -# define NV_PGRAPH_INTR_EN_TLB_PRESENT_DMA_W (1 << 7) -# define NV_PGRAPH_INTR_EN_TLB_PRESENT_TEX_A (1 << 8) -# define NV_PGRAPH_INTR_EN_TLB_PRESENT_TEX_B (1 << 9) -# define NV_PGRAPH_INTR_EN_TLB_PRESENT_VTX (1 << 10) -# define NV_PGRAPH_INTR_EN_CONTEXT_SWITCH (1 << 12) -# define NV_PGRAPH_INTR_EN_STATE3D (1 << 13) -# define NV_PGRAPH_INTR_EN_BUFFER_NOTIFY (1 << 16) -# define NV_PGRAPH_INTR_EN_ERROR (1 << 20) -# define NV_PGRAPH_INTR_EN_SINGLE_STEP (1 << 24) -#define NV_PGRAPH_CTX_CONTROL 0x00000144 -# define NV_PGRAPH_CTX_CONTROL_MINIMUM_TIME 0x00000003 -# define NV_PGRAPH_CTX_CONTROL_TIME (1 << 8) -# define NV_PGRAPH_CTX_CONTROL_CHID (1 << 16) -# define NV_PGRAPH_CTX_CONTROL_CHANGE (1 << 20) -# define NV_PGRAPH_CTX_CONTROL_SWITCHING (1 << 24) -# define NV_PGRAPH_CTX_CONTROL_DEVICE (1 << 28) -#define NV_PGRAPH_CTX_USER 0x00000148 -# define NV_PGRAPH_CTX_USER_CHANNEL_3D (1 << 0) -# define NV_PGRAPH_CTX_USER_CHANNEL_3D_VALID (1 << 4) -# define NV_PGRAPH_CTX_USER_SUBCH 0x0000E000 -# define NV_PGRAPH_CTX_USER_CHID 0x1F000000 -# define NV_PGRAPH_CTX_USER_SINGLE_STEP (1 << 31) -#define NV_PGRAPH_CTX_SWITCH1 0x0000014C -# define NV_PGRAPH_CTX_SWITCH1_GRCLASS 0x000000FF -# define NV_PGRAPH_CTX_SWITCH1_CHROMA_KEY (1 << 12) -# define NV_PGRAPH_CTX_SWITCH1_SWIZZLE (1 << 14) -# define NV_PGRAPH_CTX_SWITCH1_PATCH_CONFIG 0x00038000 -# define NV_PGRAPH_CTX_SWITCH1_SYNCHRONIZE (1 << 18) -# define NV_PGRAPH_CTX_SWITCH1_ENDIAN_MODE (1 << 19) -# define NV_PGRAPH_CTX_SWITCH1_CLASS_TYPE (1 << 22) -# define NV_PGRAPH_CTX_SWITCH1_SINGLE_STEP (1 << 23) -# define NV_PGRAPH_CTX_SWITCH1_PATCH_STATUS (1 << 24) -# define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE0 (1 << 25) -# define NV_PGRAPH_CTX_SWITCH1_CONTEXT_SURFACE1 (1 << 26) -# define NV_PGRAPH_CTX_SWITCH1_CONTEXT_PATTERN (1 << 27) -# define NV_PGRAPH_CTX_SWITCH1_CONTEXT_ROP (1 << 28) -# define NV_PGRAPH_CTX_SWITCH1_CONTEXT_BETA1 (1 << 29) -# define NV_PGRAPH_CTX_SWITCH1_CONTEXT_BETA4 (1 << 30) -# define NV_PGRAPH_CTX_SWITCH1_VOLATILE_RESET (1 << 31) -#define NV_PGRAPH_CTX_SWITCH2 0x00000150 -#define NV_PGRAPH_CTX_SWITCH3 0x00000154 -#define NV_PGRAPH_CTX_SWITCH4 0x00000158 -# define NV_PGRAPH_CTX_SWITCH4_USER_INSTANCE 0x0000FFFF -#define NV_PGRAPH_CTX_SWITCH5 0x0000015C -#define NV_PGRAPH_CTX_CACHE1 0x00000160 -#define NV_PGRAPH_CTX_CACHE2 0x00000180 -#define NV_PGRAPH_CTX_CACHE3 0x000001A0 -#define NV_PGRAPH_CTX_CACHE4 0x000001C0 -#define NV_PGRAPH_CTX_CACHE5 0x000001E0 -#define NV_PGRAPH_TRAPPED_ADDR 0x00000704 -# define NV_PGRAPH_TRAPPED_ADDR_MTHD 0x00001FFF -# define NV_PGRAPH_TRAPPED_ADDR_SUBCH 0x00070000 -# define NV_PGRAPH_TRAPPED_ADDR_CHID 0x01F00000 -# define NV_PGRAPH_TRAPPED_ADDR_DHV 0x10000000 -#define NV_PGRAPH_TRAPPED_DATA_LOW 0x00000708 -#define NV_PGRAPH_SURFACE 0x00000710 -# define NV_PGRAPH_SURFACE_WRITE_3D 0x00700000 -# define NV_PGRAPH_SURFACE_READ_3D 0x07000000 -# define NV_PGRAPH_SURFACE_MODULO_3D 0x70000000 -#define NV_PGRAPH_INCREMENT 0x0000071C -# define NV_PGRAPH_INCREMENT_READ_BLIT (1 << 0) -# define NV_PGRAPH_INCREMENT_READ_3D (1 << 1) -#define NV_PGRAPH_FIFO 0x00000720 -# define NV_PGRAPH_FIFO_ACCESS (1 << 0) -#define NV_PGRAPH_CHANNEL_CTX_TABLE 0x00000780 -# define NV_PGRAPH_CHANNEL_CTX_TABLE_INST 0x0000FFFF -#define NV_PGRAPH_CHANNEL_CTX_POINTER 0x00000784 -# define NV_PGRAPH_CHANNEL_CTX_POINTER_INST 0x0000FFFF -#define NV_PGRAPH_CHANNEL_CTX_TRIGGER 0x00000788 -# define NV_PGRAPH_CHANNEL_CTX_TRIGGER_READ_IN (1 << 0) -# define NV_PGRAPH_CHANNEL_CTX_TRIGGER_WRITE_OUT (1 << 1) -#define NV_PGRAPH_CSV0_D 0x00000FB4 -# define NV_PGRAPH_CSV0_D_LIGHTS 0x0000FFFF -# define NV_PGRAPH_CSV0_D_LIGHT0 0x00000003 -# define NV_PGRAPH_CSV0_D_LIGHT0_OFF 0 -# define NV_PGRAPH_CSV0_D_LIGHT0_INFINITE 1 -# define NV_PGRAPH_CSV0_D_LIGHT0_LOCAL 2 -# define NV_PGRAPH_CSV0_D_LIGHT0_SPOT 3 -# define NV_PGRAPH_CSV0_D_RANGE_MODE (1 << 18) -# define NV_PGRAPH_CSV0_D_FOGENABLE (1 << 19) -# define NV_PGRAPH_CSV0_D_TEXGEN_REF (1 << 20) -# define NV_PGRAPH_CSV0_D_TEXGEN_REF_LOCAL_VIEWER 0 -# define NV_PGRAPH_CSV0_D_TEXGEN_REF_INFINITE_VIEWER 1 -# define NV_PGRAPH_CSV0_D_FOG_MODE (1 << 21) -# define NV_PGRAPH_CSV0_D_FOG_MODE_LINEAR 0 -# define NV_PGRAPH_CSV0_D_FOG_MODE_EXP 1 -# define NV_PGRAPH_CSV0_D_FOGGENMODE 0x01C00000 -# define NV_PGRAPH_CSV0_D_FOGGENMODE_SPEC_ALPHA 0 -# define NV_PGRAPH_CSV0_D_FOGGENMODE_RADIAL 1 -# define NV_PGRAPH_CSV0_D_FOGGENMODE_PLANAR 2 -# define NV_PGRAPH_CSV0_D_FOGGENMODE_ABS_PLANAR 3 -# define NV_PGRAPH_CSV0_D_FOGGENMODE_FOG_X 4 -# define NV_PGRAPH_CSV0_D_MODE 0xC0000000 -# define NV_PGRAPH_CSV0_D_SKIN 0x1C000000 -# define NV_PGRAPH_CSV0_D_SKIN_OFF 0 -# define NV_PGRAPH_CSV0_D_SKIN_2G 1 -# define NV_PGRAPH_CSV0_D_SKIN_2 2 -# define NV_PGRAPH_CSV0_D_SKIN_3G 3 -# define NV_PGRAPH_CSV0_D_SKIN_3 4 -# define NV_PGRAPH_CSV0_D_SKIN_4G 5 -# define NV_PGRAPH_CSV0_D_SKIN_4 6 -#define NV_PGRAPH_CSV0_C 0x00000FB8 -# define NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START 0x0000FF00 -# define NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE (1 << 27) -# define NV_PGRAPH_CSV0_C_LIGHTING (1 << 31) -#define NV_PGRAPH_CSV1_B 0x00000FBC -#define NV_PGRAPH_CSV1_A 0x00000FC0 -# define NV_PGRAPH_CSV1_A_T0_ENABLE (1 << 0) -# define NV_PGRAPH_CSV1_A_T0_MODE (1 << 1) -# define NV_PGRAPH_CSV1_A_T0_TEXTURE (1 << 2) -# define NV_PGRAPH_CSV1_A_T0_TEXTURE_2D 0 -# define NV_PGRAPH_CSV1_A_T0_TEXTURE_3D 1 -# define NV_PGRAPH_CSV1_A_T0_S 0x00000070 -# define NV_PGRAPH_CSV1_A_T0_S_DISABLE 0 -# define NV_PGRAPH_CSV1_A_T0_S_NORMAL_MAP 4 -# define NV_PGRAPH_CSV1_A_T0_S_REFLECTION_MAP 5 -# define NV_PGRAPH_CSV1_A_T0_S_EYE_LINEAR 1 -# define NV_PGRAPH_CSV1_A_T0_S_OBJECT_LINEAR 2 -# define NV_PGRAPH_CSV1_A_T0_S_SPHERE_MAP 3 -# define NV_PGRAPH_CSV1_A_T0_T 0x00000380 -# define NV_PGRAPH_CSV1_A_T0_R 0x00001C00 -# define NV_PGRAPH_CSV1_A_T0_Q 0x0000E000 -# define NV_PGRAPH_CSV1_A_T1_ENABLE (1 << 16) -# define NV_PGRAPH_CSV1_A_T1_MODE (1 << 17) -# define NV_PGRAPH_CSV1_A_T1_TEXTURE (1 << 18) -# define NV_PGRAPH_CSV1_A_T1_S 0x00700000 -# define NV_PGRAPH_CSV1_A_T1_T 0x03800000 -# define NV_PGRAPH_CSV1_A_T1_R 0x1C000000 -# define NV_PGRAPH_CSV1_A_T1_Q 0xE0000000 -#define NV_PGRAPH_CHEOPS_OFFSET 0x00000FC4 -# define NV_PGRAPH_CHEOPS_OFFSET_PROG_LD_PTR 0x000000FF -# define NV_PGRAPH_CHEOPS_OFFSET_CONST_LD_PTR 0x0000FF00 -#define NV_PGRAPH_DMA_STATE 0x00001034 -#define NV_PGRAPH_BLEND 0x00001804 -# define NV_PGRAPH_BLEND_EQN 0x00000007 -# define NV_PGRAPH_BLEND_EN (1 << 3) -# define NV_PGRAPH_BLEND_SFACTOR 0x000000F0 -# define NV_PGRAPH_BLEND_SFACTOR_ZERO 0 -# define NV_PGRAPH_BLEND_SFACTOR_ONE 1 -# define NV_PGRAPH_BLEND_SFACTOR_SRC_COLOR 2 -# define NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_SRC_COLOR 3 -# define NV_PGRAPH_BLEND_SFACTOR_SRC_ALPHA 4 -# define NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_SRC_ALPHA 5 -# define NV_PGRAPH_BLEND_SFACTOR_DST_ALPHA 6 -# define NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_DST_ALPHA 7 -# define NV_PGRAPH_BLEND_SFACTOR_DST_COLOR 8 -# define NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_DST_COLOR 9 -# define NV_PGRAPH_BLEND_SFACTOR_SRC_ALPHA_SATURATE 10 -# define NV_PGRAPH_BLEND_SFACTOR_CONSTANT_COLOR 12 -# define NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_CONSTANT_COLOR 13 -# define NV_PGRAPH_BLEND_SFACTOR_CONSTANT_ALPHA 14 -# define NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_CONSTANT_ALPHA 15 -# define NV_PGRAPH_BLEND_DFACTOR 0x00000F00 -# define NV_PGRAPH_BLEND_DFACTOR_ZERO 0 -# define NV_PGRAPH_BLEND_DFACTOR_ONE 1 -# define NV_PGRAPH_BLEND_DFACTOR_SRC_COLOR 2 -# define NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_SRC_COLOR 3 -# define NV_PGRAPH_BLEND_DFACTOR_SRC_ALPHA 4 -# define NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_SRC_ALPHA 5 -# define NV_PGRAPH_BLEND_DFACTOR_DST_ALPHA 6 -# define NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_DST_ALPHA 7 -# define NV_PGRAPH_BLEND_DFACTOR_DST_COLOR 8 -# define NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_DST_COLOR 9 -# define NV_PGRAPH_BLEND_DFACTOR_SRC_ALPHA_SATURATE 10 -# define NV_PGRAPH_BLEND_DFACTOR_CONSTANT_COLOR 12 -# define NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_CONSTANT_COLOR 13 -# define NV_PGRAPH_BLEND_DFACTOR_CONSTANT_ALPHA 14 -# define NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_CONSTANT_ALPHA 15 -# define NV_PGRAPH_BLEND_LOGICOP_ENABLE (1 << 16) -# define NV_PGRAPH_BLEND_LOGICOP 0x0000F000 -#define NV_PGRAPH_BLENDCOLOR 0x00001808 -#define NV_PGRAPH_BORDERCOLOR0 0x0000180C -#define NV_PGRAPH_BORDERCOLOR1 0x00001810 -#define NV_PGRAPH_BORDERCOLOR2 0x00001814 -#define NV_PGRAPH_BORDERCOLOR3 0x00001818 -#define NV_PGRAPH_BUMPOFFSET1 0x0000184C -#define NV_PGRAPH_BUMPSCALE1 0x00001858 -#define NV_PGRAPH_CLEARRECTX 0x00001864 -# define NV_PGRAPH_CLEARRECTX_XMIN 0x00000FFF -# define NV_PGRAPH_CLEARRECTX_XMAX 0x0FFF0000 -#define NV_PGRAPH_CLEARRECTY 0x00001868 -# define NV_PGRAPH_CLEARRECTY_YMIN 0x00000FFF -# define NV_PGRAPH_CLEARRECTY_YMAX 0x0FFF0000 -#define NV_PGRAPH_COLORCLEARVALUE 0x0000186C -#define NV_PGRAPH_COMBINEFACTOR0 0x00001880 -#define NV_PGRAPH_COMBINEFACTOR1 0x000018A0 -#define NV_PGRAPH_COMBINEALPHAI0 0x000018C0 -#define NV_PGRAPH_COMBINEALPHAO0 0x000018E0 -#define NV_PGRAPH_COMBINECOLORI0 0x00001900 -#define NV_PGRAPH_COMBINECOLORO0 0x00001920 -#define NV_PGRAPH_COMBINECTL 0x00001940 -#define NV_PGRAPH_COMBINESPECFOG0 0x00001944 -#define NV_PGRAPH_COMBINESPECFOG1 0x00001948 -#define NV_PGRAPH_CONTROL_0 0x0000194C -# define NV_PGRAPH_CONTROL_0_ALPHAREF 0x000000FF -# define NV_PGRAPH_CONTROL_0_ALPHAFUNC 0x00000F00 -# define NV_PGRAPH_CONTROL_0_ALPHATESTENABLE (1 << 12) -# define NV_PGRAPH_CONTROL_0_ZENABLE (1 << 14) -# define NV_PGRAPH_CONTROL_0_ZFUNC 0x000F0000 -# define NV_PGRAPH_CONTROL_0_ZFUNC_NEVER 0 -# define NV_PGRAPH_CONTROL_0_ZFUNC_LESS 1 -# define NV_PGRAPH_CONTROL_0_ZFUNC_EQUAL 2 -# define NV_PGRAPH_CONTROL_0_ZFUNC_LEQUAL 3 -# define NV_PGRAPH_CONTROL_0_ZFUNC_GREATER 4 -# define NV_PGRAPH_CONTROL_0_ZFUNC_NOTEQUAL 5 -# define NV_PGRAPH_CONTROL_0_ZFUNC_GEQUAL 6 -# define NV_PGRAPH_CONTROL_0_ZFUNC_ALWAYS 7 -# define NV_PGRAPH_CONTROL_0_DITHERENABLE (1 << 22) -# define NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE (1 << 23) -# define NV_PGRAPH_CONTROL_0_ZWRITEENABLE (1 << 24) -# define NV_PGRAPH_CONTROL_0_STENCIL_WRITE_ENABLE (1 << 25) -# define NV_PGRAPH_CONTROL_0_ALPHA_WRITE_ENABLE (1 << 26) -# define NV_PGRAPH_CONTROL_0_RED_WRITE_ENABLE (1 << 27) -# define NV_PGRAPH_CONTROL_0_GREEN_WRITE_ENABLE (1 << 28) -# define NV_PGRAPH_CONTROL_0_BLUE_WRITE_ENABLE (1 << 29) -#define NV_PGRAPH_CONTROL_1 0x00001950 -# define NV_PGRAPH_CONTROL_1_STENCIL_TEST_ENABLE (1 << 0) -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC 0x000000F0 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_NEVER 0 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_LESS 1 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_EQUAL 2 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_LEQUAL 3 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_GREATER 4 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_NOTEQUAL 5 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_GEQUAL 6 -# define NV_PGRAPH_CONTROL_1_STENCIL_FUNC_ALWAYS 7 -# define NV_PGRAPH_CONTROL_1_STENCIL_REF 0x0000FF00 -# define NV_PGRAPH_CONTROL_1_STENCIL_MASK_READ 0x00FF0000 -# define NV_PGRAPH_CONTROL_1_STENCIL_MASK_WRITE 0xFF000000 -#define NV_PGRAPH_CONTROL_2 0x00001954 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_FAIL 0x0000000F -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_ZFAIL 0x000000F0 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_ZPASS 0x00000F00 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_KEEP 1 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_ZERO 2 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_REPLACE 3 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INCRSAT 4 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_DECRSAT 5 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INVERT 6 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INCR 7 -# define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_DECR 8 -#define NV_PGRAPH_CONTROL_3 0x00001958 -# define NV_PGRAPH_CONTROL_3_FOGENABLE (1 << 8) -# define NV_PGRAPH_CONTROL_3_FOG_MODE 0x00070000 -# define NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR 0 -# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP 1 -# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2 3 -# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP_ABS 5 -# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2_ABS 7 -# define NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR_ABS 4 -#define NV_PGRAPH_FOGCOLOR 0x00001980 -# define NV_PGRAPH_FOGCOLOR_RED 0x00FF0000 -# define NV_PGRAPH_FOGCOLOR_GREEN 0x0000FF00 -# define NV_PGRAPH_FOGCOLOR_BLUE 0x000000FF -# define NV_PGRAPH_FOGCOLOR_ALPHA 0xFF000000 -#define NV_PGRAPH_FOGPARAM0 0x00001984 -#define NV_PGRAPH_FOGPARAM1 0x00001988 -#define NV_PGRAPH_SETUPRASTER 0x00001990 -# define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE 0x00000003 -# define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_FILL 0 -# define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_POINT 1 -# define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_LINE 2 -# define NV_PGRAPH_SETUPRASTER_BACKFACEMODE 0x0000000C -# define NV_PGRAPH_SETUPRASTER_POFFSETPOINTENABLE (1 << 6) -# define NV_PGRAPH_SETUPRASTER_POFFSETLINEENABLE (1 << 7) -# define NV_PGRAPH_SETUPRASTER_POFFSETFILLENABLE (1 << 8) -# define NV_PGRAPH_SETUPRASTER_CULLCTRL 0x00600000 -# define NV_PGRAPH_SETUPRASTER_CULLCTRL_FRONT 1 -# define NV_PGRAPH_SETUPRASTER_CULLCTRL_BACK 2 -# define NV_PGRAPH_SETUPRASTER_CULLCTRL_FRONT_AND_BACK 3 -# define NV_PGRAPH_SETUPRASTER_FRONTFACE (1 << 23) -# define NV_PGRAPH_SETUPRASTER_CULLENABLE (1 << 28) -# define NV_PGRAPH_SETUPRASTER_Z_FORMAT (1 << 29) -#define NV_PGRAPH_SHADERCLIPMODE 0x00001994 -#define NV_PGRAPH_SHADERCTL 0x00001998 -#define NV_PGRAPH_SHADERPROG 0x0000199C -#define NV_PGRAPH_SEMAPHOREOFFSET 0x000019A0 -#define NV_PGRAPH_SHADOWZSLOPETHRESHOLD 0x000019A8 -#define NV_PGRAPH_SPECFOGFACTOR0 0x000019AC -#define NV_PGRAPH_SPECFOGFACTOR1 0x000019B0 -#define NV_PGRAPH_TEXADDRESS0 0x000019BC -# define NV_PGRAPH_TEXADDRESS0_ADDRU 0x00000007 -# define NV_PGRAPH_TEXADDRESS0_ADDRU_WRAP 1 -# define NV_PGRAPH_TEXADDRESS0_ADDRU_MIRROR 2 -# define NV_PGRAPH_TEXADDRESS0_ADDRU_CLAMP_TO_EDGE 3 -# define NV_PGRAPH_TEXADDRESS0_ADDRU_BORDER 4 -# define NV_PGRAPH_TEXADDRESS0_ADDRU_CLAMP_OGL 5 -# define NV_PGRAPH_TEXADDRESS0_WRAP_U (1 << 4) -# define NV_PGRAPH_TEXADDRESS0_ADDRV 0x00000700 -# define NV_PGRAPH_TEXADDRESS0_WRAP_V (1 << 12) -# define NV_PGRAPH_TEXADDRESS0_ADDRP 0x00070000 -# define NV_PGRAPH_TEXADDRESS0_WRAP_P (1 << 20) -# define NV_PGRAPH_TEXADDRESS0_WRAP_Q (1 << 24) -#define NV_PGRAPH_TEXADDRESS1 0x000019C0 -#define NV_PGRAPH_TEXADDRESS2 0x000019C4 -#define NV_PGRAPH_TEXADDRESS3 0x000019C8 -#define NV_PGRAPH_TEXCTL0_0 0x000019CC -# define NV_PGRAPH_TEXCTL0_0_ALPHAKILLEN (1 << 2) -# define NV_PGRAPH_TEXCTL0_0_MAX_LOD_CLAMP 0x0003FFC0 -# define NV_PGRAPH_TEXCTL0_0_MIN_LOD_CLAMP 0x3FFC0000 -# define NV_PGRAPH_TEXCTL0_0_ENABLE (1 << 30) -#define NV_PGRAPH_TEXCTL0_1 0x000019D0 -#define NV_PGRAPH_TEXCTL0_2 0x000019D4 -#define NV_PGRAPH_TEXCTL0_3 0x000019D8 -#define NV_PGRAPH_TEXCTL1_0 0x000019DC -# define NV_PGRAPH_TEXCTL1_0_IMAGE_PITCH 0xFFFF0000 -#define NV_PGRAPH_TEXCTL1_1 0x000019E0 -#define NV_PGRAPH_TEXCTL1_2 0x000019E4 -#define NV_PGRAPH_TEXCTL1_3 0x000019E8 -#define NV_PGRAPH_TEXCTL2_0 0x000019EC -#define NV_PGRAPH_TEXCTL2_1 0x000019F0 -#define NV_PGRAPH_TEXFILTER0 0x000019F4 -# define NV_PGRAPH_TEXFILTER0_MIPMAP_LOD_BIAS 0x00001FFF -# define NV_PGRAPH_TEXFILTER0_MIN 0x003F0000 -# define NV_PGRAPH_TEXFILTER0_MIN_BOX_LOD0 1 -# define NV_PGRAPH_TEXFILTER0_MIN_TENT_LOD0 2 -# define NV_PGRAPH_TEXFILTER0_MIN_BOX_NEARESTLOD 3 -# define NV_PGRAPH_TEXFILTER0_MIN_TENT_NEARESTLOD 4 -# define NV_PGRAPH_TEXFILTER0_MIN_BOX_TENT_LOD 5 -# define NV_PGRAPH_TEXFILTER0_MIN_TENT_TENT_LOD 6 -# define NV_PGRAPH_TEXFILTER0_MIN_CONVOLUTION_2D_LOD0 7 -# define NV_PGRAPH_TEXFILTER0_MAG 0x0F000000 -# define NV_PGRAPH_TEXFILTER0_ASIGNED (1 << 28) -# define NV_PGRAPH_TEXFILTER0_RSIGNED (1 << 29) -# define NV_PGRAPH_TEXFILTER0_GSIGNED (1 << 30) -# define NV_PGRAPH_TEXFILTER0_BSIGNED (1 << 31) -#define NV_PGRAPH_TEXFILTER1 0x000019F8 -#define NV_PGRAPH_TEXFILTER2 0x000019FC -#define NV_PGRAPH_TEXFILTER3 0x00001A00 -#define NV_PGRAPH_TEXFMT0 0x00001A04 -# define NV_PGRAPH_TEXFMT0_CONTEXT_DMA (1 << 1) -# define NV_PGRAPH_TEXFMT0_CUBEMAPENABLE (1 << 2) -# define NV_PGRAPH_TEXFMT0_BORDER_SOURCE (1 << 3) -# define NV_PGRAPH_TEXFMT0_BORDER_SOURCE_TEXTURE 0 -# define NV_PGRAPH_TEXFMT0_BORDER_SOURCE_COLOR 1 -# define NV_PGRAPH_TEXFMT0_DIMENSIONALITY 0x000000C0 -# define NV_PGRAPH_TEXFMT0_COLOR 0x00007F00 -# define NV_PGRAPH_TEXFMT0_MIPMAP_LEVELS 0x000F0000 -# define NV_PGRAPH_TEXFMT0_BASE_SIZE_U 0x00F00000 -# define NV_PGRAPH_TEXFMT0_BASE_SIZE_V 0x0F000000 -# define NV_PGRAPH_TEXFMT0_BASE_SIZE_P 0xF0000000 -#define NV_PGRAPH_TEXFMT1 0x00001A08 -#define NV_PGRAPH_TEXFMT2 0x00001A0C -#define NV_PGRAPH_TEXFMT3 0x00001A10 -#define NV_PGRAPH_TEXIMAGERECT0 0x00001A14 -# define NV_PGRAPH_TEXIMAGERECT0_WIDTH 0x1FFF0000 -# define NV_PGRAPH_TEXIMAGERECT0_HEIGHT 0x00001FFF -#define NV_PGRAPH_TEXIMAGERECT1 0x00001A18 -#define NV_PGRAPH_TEXIMAGERECT2 0x00001A1C -#define NV_PGRAPH_TEXIMAGERECT3 0x00001A20 -#define NV_PGRAPH_TEXOFFSET0 0x00001A24 -#define NV_PGRAPH_TEXOFFSET1 0x00001A28 -#define NV_PGRAPH_TEXOFFSET2 0x00001A2C -#define NV_PGRAPH_TEXOFFSET3 0x00001A30 -#define NV_PGRAPH_TEXPALETTE0 0x00001A34 -# define NV_PGRAPH_TEXPALETTE0_CONTEXT_DMA (1 << 0) -# define NV_PGRAPH_TEXPALETTE0_LENGTH 0x0000000C -# define NV_PGRAPH_TEXPALETTE0_LENGTH_256 0 -# define NV_PGRAPH_TEXPALETTE0_LENGTH_128 1 -# define NV_PGRAPH_TEXPALETTE0_LENGTH_64 2 -# define NV_PGRAPH_TEXPALETTE0_LENGTH_32 3 -# define NV_PGRAPH_TEXPALETTE0_OFFSET 0xFFFFFFC0 -#define NV_PGRAPH_TEXPALETTE1 0x00001A38 -#define NV_PGRAPH_TEXPALETTE2 0x00001A3C -#define NV_PGRAPH_TEXPALETTE3 0x00001A40 -#define NV_PGRAPH_ZSTENCILCLEARVALUE 0x00001A88 -#define NV_PGRAPH_ZCLIPMIN 0x00001A90 -#define NV_PGRAPH_ZOFFSETBIAS 0x00001AA4 -#define NV_PGRAPH_ZOFFSETFACTOR 0x00001AA8 -#define NV_PGRAPH_EYEVEC0 0x00001AAC -#define NV_PGRAPH_EYEVEC1 0x00001AB0 -#define NV_PGRAPH_EYEVEC2 0x00001AB4 -#define NV_PGRAPH_ZCLIPMAX 0x00001ABC - - -#define NV_PCRTC_INTR_0 0x00000100 -# define NV_PCRTC_INTR_0_VBLANK (1 << 0) -#define NV_PCRTC_INTR_EN_0 0x00000140 -# define NV_PCRTC_INTR_EN_0_VBLANK (1 << 0) -#define NV_PCRTC_START 0x00000800 -#define NV_PCRTC_CONFIG 0x00000804 - - -#define NV_PVIDEO_INTR 0x00000100 -# define NV_PVIDEO_INTR_BUFFER_0 (1 << 0) -# define NV_PVIDEO_INTR_BUFFER_1 (1 << 4) -#define NV_PVIDEO_INTR_EN 0x00000140 -# define NV_PVIDEO_INTR_EN_BUFFER_0 (1 << 0) -# define NV_PVIDEO_INTR_EN_BUFFER_1 (1 << 4) -#define NV_PVIDEO_BUFFER 0x00000700 -# define NV_PVIDEO_BUFFER_0_USE (1 << 0) -# define NV_PVIDEO_BUFFER_1_USE (1 << 4) -#define NV_PVIDEO_STOP 0x00000704 -#define NV_PVIDEO_BASE 0x00000900 -#define NV_PVIDEO_LIMIT 0x00000908 -#define NV_PVIDEO_LUMINANCE 0x00000910 -#define NV_PVIDEO_CHROMINANCE 0x00000918 -#define NV_PVIDEO_OFFSET 0x00000920 -#define NV_PVIDEO_SIZE_IN 0x00000928 -# define NV_PVIDEO_SIZE_IN_WIDTH 0x000007FF -# define NV_PVIDEO_SIZE_IN_HEIGHT 0x07FF0000 -#define NV_PVIDEO_POINT_IN 0x00000930 -# define NV_PVIDEO_POINT_IN_S 0x00007FFF -# define NV_PVIDEO_POINT_IN_T 0xFFFE0000 -#define NV_PVIDEO_DS_DX 0x00000938 -#define NV_PVIDEO_DT_DY 0x00000940 -#define NV_PVIDEO_POINT_OUT 0x00000948 -# define NV_PVIDEO_POINT_OUT_X 0x00000FFF -# define NV_PVIDEO_POINT_OUT_Y 0x0FFF0000 -#define NV_PVIDEO_SIZE_OUT 0x00000950 -# define NV_PVIDEO_SIZE_OUT_WIDTH 0x00000FFF -# define NV_PVIDEO_SIZE_OUT_HEIGHT 0x0FFF0000 -#define NV_PVIDEO_FORMAT 0x00000958 -# define NV_PVIDEO_FORMAT_PITCH 0x00001FFF -# define NV_PVIDEO_FORMAT_COLOR 0x00030000 -# define NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8 1 -# define NV_PVIDEO_FORMAT_DISPLAY (1 << 20) - - -#define NV_PTIMER_INTR_0 0x00000100 -# define NV_PTIMER_INTR_0_ALARM (1 << 0) -#define NV_PTIMER_INTR_EN_0 0x00000140 -# define NV_PTIMER_INTR_EN_0_ALARM (1 << 0) -#define NV_PTIMER_NUMERATOR 0x00000200 -#define NV_PTIMER_DENOMINATOR 0x00000210 -#define NV_PTIMER_TIME_0 0x00000400 -#define NV_PTIMER_TIME_1 0x00000410 -#define NV_PTIMER_ALARM_0 0x00000420 - - -#define NV_PFB_CFG0 0x00000200 -# define NV_PFB_CFG0_PART 0x00000003 -#define NV_PFB_CSTATUS 0x0000020C -#define NV_PFB_WBC 0x00000410 -# define NV_PFB_WBC_FLUSH (1 << 16) - - -#define NV_PRAMDAC_NVPLL_COEFF 0x00000500 -# define NV_PRAMDAC_NVPLL_COEFF_MDIV 0x000000FF -# define NV_PRAMDAC_NVPLL_COEFF_NDIV 0x0000FF00 -# define NV_PRAMDAC_NVPLL_COEFF_PDIV 0x00070000 -#define NV_PRAMDAC_MPLL_COEFF 0x00000504 -# define NV_PRAMDAC_MPLL_COEFF_MDIV 0x000000FF -# define NV_PRAMDAC_MPLL_COEFF_NDIV 0x0000FF00 -# define NV_PRAMDAC_MPLL_COEFF_PDIV 0x00070000 -#define NV_PRAMDAC_VPLL_COEFF 0x00000508 -# define NV_PRAMDAC_VPLL_COEFF_MDIV 0x000000FF -# define NV_PRAMDAC_VPLL_COEFF_NDIV 0x0000FF00 -# define NV_PRAMDAC_VPLL_COEFF_PDIV 0x00070000 -#define NV_PRAMDAC_PLL_TEST_COUNTER 0x00000514 -# define NV_PRAMDAC_PLL_TEST_COUNTER_NOOFIPCLKS 0x000003FF -# define NV_PRAMDAC_PLL_TEST_COUNTER_VALUE 0x0000FFFF -# define NV_PRAMDAC_PLL_TEST_COUNTER_ENABLE (1 << 16) -# define NV_PRAMDAC_PLL_TEST_COUNTER_RESET (1 << 20) -# define NV_PRAMDAC_PLL_TEST_COUNTER_SOURCE 0x03000000 -# define NV_PRAMDAC_PLL_TEST_COUNTER_VPLL2_LOCK (1 << 27) -# define NV_PRAMDAC_PLL_TEST_COUNTER_PDIV_RST (1 << 28) -# define NV_PRAMDAC_PLL_TEST_COUNTER_NVPLL_LOCK (1 << 29) -# define NV_PRAMDAC_PLL_TEST_COUNTER_MPLL_LOCK (1 << 30) -# define NV_PRAMDAC_PLL_TEST_COUNTER_VPLL_LOCK (1 << 31) - - -#define NV_USER_DMA_PUT 0x40 -#define NV_USER_DMA_GET 0x44 -#define NV_USER_REF 0x48 - - - -/* DMA objects */ -#define NV_DMA_FROM_MEMORY_CLASS 0x02 -#define NV_DMA_TO_MEMORY_CLASS 0x03 -#define NV_DMA_IN_MEMORY_CLASS 0x3d - -#define NV_DMA_CLASS 0x00000FFF -#define NV_DMA_PAGE_TABLE (1 << 12) -#define NV_DMA_PAGE_ENTRY (1 << 13) -#define NV_DMA_FLAGS_ACCESS (1 << 14) -#define NV_DMA_FLAGS_MAPPING_COHERENCY (1 << 15) -#define NV_DMA_TARGET 0x00030000 -# define NV_DMA_TARGET_NVM 0x00000000 -# define NV_DMA_TARGET_NVM_TILED 0x00010000 -# define NV_DMA_TARGET_PCI 0x00020000 -# define NV_DMA_TARGET_AGP 0x00030000 -#define NV_DMA_ADJUST 0xFFF00000 - -#define NV_DMA_ADDRESS 0xFFFFF000 - - -#define NV_RAMHT_HANDLE 0xFFFFFFFF -#define NV_RAMHT_INSTANCE 0x0000FFFF -#define NV_RAMHT_ENGINE 0x00030000 -# define NV_RAMHT_ENGINE_SW 0x00000000 -# define NV_RAMHT_ENGINE_GRAPHICS 0x00010000 -# define NV_RAMHT_ENGINE_DVD 0x00020000 -#define NV_RAMHT_CHID 0x1F000000 -#define NV_RAMHT_STATUS 0x80000000 - - - -/* graphic classes and methods */ -#define NV_SET_OBJECT 0x00000000 - - -#define NV_CONTEXT_SURFACES_2D 0x0062 -# define NV062_SET_OBJECT 0x00000000 -# define NV062_SET_CONTEXT_DMA_IMAGE_SOURCE 0x00000184 -# define NV062_SET_CONTEXT_DMA_IMAGE_DESTIN 0x00000188 -# define NV062_SET_COLOR_FORMAT 0x00000300 -# define NV062_SET_COLOR_FORMAT_LE_Y8 0x01 -# define NV062_SET_COLOR_FORMAT_LE_R5G6B5 0x04 -# define NV062_SET_COLOR_FORMAT_LE_A8R8G8B8 0x0A -# define NV062_SET_PITCH 0x00000304 -# define NV062_SET_OFFSET_SOURCE 0x00000308 -# define NV062_SET_OFFSET_DESTIN 0x0000030C - -#define NV_IMAGE_BLIT 0x009F -# define NV09F_SET_OBJECT 0x00000000 -# define NV09F_SET_CONTEXT_SURFACES 0x0000019C -# define NV09F_SET_OPERATION 0x000002FC -# define NV09F_SET_OPERATION_SRCCOPY 3 -# define NV09F_CONTROL_POINT_IN 0x00000300 -# define NV09F_CONTROL_POINT_OUT 0x00000304 -# define NV09F_SIZE 0x00000308 - - -#define NV_KELVIN_PRIMITIVE 0x0097 -# define NV097_SET_OBJECT 0x00000000 -# define NV097_NO_OPERATION 0x00000100 -# define NV097_WAIT_FOR_IDLE 0x00000110 -# define NV097_SET_FLIP_READ 0x00000120 -# define NV097_SET_FLIP_WRITE 0x00000124 -# define NV097_SET_FLIP_MODULO 0x00000128 -# define NV097_FLIP_INCREMENT_WRITE 0x0000012C -# define NV097_FLIP_STALL 0x00000130 -# define NV097_SET_CONTEXT_DMA_NOTIFIES 0x00000180 -# define NV097_SET_CONTEXT_DMA_A 0x00000184 -# define NV097_SET_CONTEXT_DMA_B 0x00000188 -# define NV097_SET_CONTEXT_DMA_STATE 0x00000190 -# define NV097_SET_CONTEXT_DMA_COLOR 0x00000194 -# define NV097_SET_CONTEXT_DMA_ZETA 0x00000198 -# define NV097_SET_CONTEXT_DMA_VERTEX_A 0x0000019C -# define NV097_SET_CONTEXT_DMA_VERTEX_B 0x000001A0 -# define NV097_SET_CONTEXT_DMA_SEMAPHORE 0x000001A4 -# define NV097_SET_CONTEXT_DMA_REPORT 0x000001A8 -# define NV097_SET_SURFACE_CLIP_HORIZONTAL 0x00000200 -# define NV097_SET_SURFACE_CLIP_HORIZONTAL_X 0x0000FFFF -# define NV097_SET_SURFACE_CLIP_HORIZONTAL_WIDTH 0xFFFF0000 -# define NV097_SET_SURFACE_CLIP_VERTICAL 0x00000204 -# define NV097_SET_SURFACE_CLIP_VERTICAL_Y 0x0000FFFF -# define NV097_SET_SURFACE_CLIP_VERTICAL_HEIGHT 0xFFFF0000 -# define NV097_SET_SURFACE_FORMAT 0x00000208 -# define NV097_SET_SURFACE_FORMAT_COLOR 0x0000000F -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_X1R5G5B5_Z1R5G5B5 0x01 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_X1R5G5B5_O1R5G5B5 0x02 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_R5G6B5 0x03 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_X8R8G8B8_Z8R8G8B8 0x04 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_X8R8G8B8_O8R8G8B8 0x05 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_X1A7R8G8B8_Z1A7R8G8B8 0x06 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_X1A7R8G8B8_O1A7R8G8B8 0x07 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_A8R8G8B8 0x08 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_B8 0x09 -# define NV097_SET_SURFACE_FORMAT_COLOR_LE_G8B8 0x0A -# define NV097_SET_SURFACE_FORMAT_ZETA 0x000000F0 -# define NV097_SET_SURFACE_FORMAT_ZETA_Z16 1 -# define NV097_SET_SURFACE_FORMAT_ZETA_Z24S8 2 -# define NV097_SET_SURFACE_FORMAT_TYPE 0x00000F00 -# define NV097_SET_SURFACE_FORMAT_TYPE_PITCH 0x1 -# define NV097_SET_SURFACE_FORMAT_TYPE_SWIZZLE 0x2 -# define NV097_SET_SURFACE_FORMAT_ANTI_ALIASING 0x0000F000 -# define NV097_SET_SURFACE_FORMAT_ANTI_ALIASING_CENTER_1 0 -# define NV097_SET_SURFACE_FORMAT_ANTI_ALIASING_CENTER_CORNER_2 1 -# define NV097_SET_SURFACE_FORMAT_ANTI_ALIASING_SQUARE_OFFSET_4 2 -# define NV097_SET_SURFACE_FORMAT_WIDTH 0x00FF0000 -# define NV097_SET_SURFACE_FORMAT_HEIGHT 0xFF000000 -# define NV097_SET_SURFACE_PITCH 0x0000020C -# define NV097_SET_SURFACE_PITCH_COLOR 0x0000FFFF -# define NV097_SET_SURFACE_PITCH_ZETA 0xFFFF0000 -# define NV097_SET_SURFACE_COLOR_OFFSET 0x00000210 -# define NV097_SET_SURFACE_ZETA_OFFSET 0x00000214 -# define NV097_SET_COMBINER_ALPHA_ICW 0x00000260 -# define NV097_SET_COMBINER_SPECULAR_FOG_CW0 0x00000288 -# define NV097_SET_COMBINER_SPECULAR_FOG_CW1 0x0000028C -# define NV097_SET_CONTROL0 0x00000290 -# define NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE (1 << 0) -# define NV097_SET_CONTROL0_Z_FORMAT (1 << 12) -# define NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE (1 << 16) -# define NV097_SET_FOG_MODE 0x0000029C -# define NV097_SET_FOG_MODE_V_LINEAR 0x2601 -# define NV097_SET_FOG_MODE_V_EXP 0x800 -# define NV097_SET_FOG_MODE_V_EXP2 0x801 -# define NV097_SET_FOG_MODE_V_EXP_ABS 0x802 -# define NV097_SET_FOG_MODE_V_EXP2_ABS 0x803 -# define NV097_SET_FOG_MODE_V_LINEAR_ABS 0x804 -# define NV097_SET_FOG_GEN_MODE 0x000002A0 -# define NV097_SET_FOG_GEN_MODE_V_SPEC_ALPHA 0 -# define NV097_SET_FOG_GEN_MODE_V_RADIAL 1 -# define NV097_SET_FOG_GEN_MODE_V_PLANAR 2 -# define NV097_SET_FOG_GEN_MODE_V_ABS_PLANAR 3 -# define NV097_SET_FOG_GEN_MODE_V_FOG_X 6 -# define NV097_SET_FOG_ENABLE 0x000002A4 -# define NV097_SET_FOG_COLOR 0x000002A8 -# define NV097_SET_FOG_COLOR_RED 0x000000FF -# define NV097_SET_FOG_COLOR_GREEN 0x0000FF00 -# define NV097_SET_FOG_COLOR_BLUE 0x00FF0000 -# define NV097_SET_FOG_COLOR_ALPHA 0xFF000000 -# define NV097_SET_ALPHA_TEST_ENABLE 0x00000300 -# define NV097_SET_BLEND_ENABLE 0x00000304 -# define NV097_SET_CULL_FACE_ENABLE 0x00000308 -# define NV097_SET_DEPTH_TEST_ENABLE 0x0000030C -# define NV097_SET_DITHER_ENABLE 0x00000310 -# define NV097_SET_LIGHTING_ENABLE 0x00000314 -# define NV097_SET_SKIN_MODE 0x00000328 -# define NV097_SET_SKIN_MODE_OFF 0 -# define NV097_SET_SKIN_MODE_2G 1 -# define NV097_SET_SKIN_MODE_2 2 -# define NV097_SET_SKIN_MODE_3G 3 -# define NV097_SET_SKIN_MODE_3 4 -# define NV097_SET_SKIN_MODE_4G 5 -# define NV097_SET_SKIN_MODE_4 6 -# define NV097_SET_STENCIL_TEST_ENABLE 0x0000032C -# define NV097_SET_POLY_OFFSET_POINT_ENABLE 0x00000330 -# define NV097_SET_POLY_OFFSET_LINE_ENABLE 0x00000334 -# define NV097_SET_POLY_OFFSET_FILL_ENABLE 0x00000338 -# define NV097_SET_ALPHA_FUNC 0x0000033C -# define NV097_SET_ALPHA_REF 0x00000340 -# define NV097_SET_BLEND_FUNC_SFACTOR 0x00000344 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ZERO 0x0000 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ONE 0x0001 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_COLOR 0x0300 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_SRC_COLOR 0x0301 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA 0x0302 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_SRC_ALPHA 0x0303 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_DST_ALPHA 0x0304 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_DST_ALPHA 0x0305 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_DST_COLOR 0x0306 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_DST_COLOR 0x0307 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA_SATURATE 0x0308 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_CONSTANT_COLOR 0x8001 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_CONSTANT_COLOR 0x8002 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_CONSTANT_ALPHA 0x8003 -# define NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_CONSTANT_ALPHA 0x8004 -# define NV097_SET_BLEND_FUNC_DFACTOR 0x00000348 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ZERO 0x0000 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ONE 0x0001 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_SRC_COLOR 0x0300 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_COLOR 0x0301 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_SRC_ALPHA 0x0302 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_ALPHA 0x0303 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_DST_ALPHA 0x0304 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_DST_ALPHA 0x0305 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_DST_COLOR 0x0306 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_DST_COLOR 0x0307 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_SRC_ALPHA_SATURATE 0x0308 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_CONSTANT_COLOR 0x8001 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_CONSTANT_COLOR 0x8002 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_CONSTANT_ALPHA 0x8003 -# define NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_CONSTANT_ALPHA 0x8004 -# define NV097_SET_BLEND_COLOR 0x0000034C -# define NV097_SET_BLEND_EQUATION 0x00000350 -# define NV097_SET_BLEND_EQUATION_V_FUNC_SUBTRACT 0x800A -# define NV097_SET_BLEND_EQUATION_V_FUNC_REVERSE_SUBTRACT 0x800B -# define NV097_SET_BLEND_EQUATION_V_FUNC_ADD 0x8006 -# define NV097_SET_BLEND_EQUATION_V_MIN 0x8007 -# define NV097_SET_BLEND_EQUATION_V_MAX 0x8008 -# define NV097_SET_BLEND_EQUATION_V_FUNC_REVERSE_SUBTRACT_SIGNED 0xF005 -# define NV097_SET_BLEND_EQUATION_V_FUNC_ADD_SIGNED 0xF006 -# define NV097_SET_DEPTH_FUNC 0x00000354 -# define NV097_SET_COLOR_MASK 0x00000358 -# define NV097_SET_COLOR_MASK_BLUE_WRITE_ENABLE (1 << 0) -# define NV097_SET_COLOR_MASK_GREEN_WRITE_ENABLE (1 << 8) -# define NV097_SET_COLOR_MASK_RED_WRITE_ENABLE (1 << 16) -# define NV097_SET_COLOR_MASK_ALPHA_WRITE_ENABLE (1 << 24) -# define NV097_SET_DEPTH_MASK 0x0000035C -# define NV097_SET_STENCIL_MASK 0x00000360 -# define NV097_SET_STENCIL_FUNC 0x00000364 -# define NV097_SET_STENCIL_FUNC_REF 0x00000368 -# define NV097_SET_STENCIL_FUNC_MASK 0x0000036C -# define NV097_SET_STENCIL_OP_FAIL 0x00000370 -# define NV097_SET_STENCIL_OP_ZFAIL 0x00000374 -# define NV097_SET_STENCIL_OP_ZPASS 0x00000378 -# define NV097_SET_STENCIL_OP_V_KEEP 0x1E00 -# define NV097_SET_STENCIL_OP_V_ZERO 0x0000 -# define NV097_SET_STENCIL_OP_V_REPLACE 0x1E01 -# define NV097_SET_STENCIL_OP_V_INCRSAT 0x1E02 -# define NV097_SET_STENCIL_OP_V_DECRSAT 0x1E03 -# define NV097_SET_STENCIL_OP_V_INVERT 0x150A -# define NV097_SET_STENCIL_OP_V_INCR 0x8507 -# define NV097_SET_STENCIL_OP_V_DECR 0x8508 -# define NV097_SET_POLYGON_OFFSET_SCALE_FACTOR 0x00000384 -# define NV097_SET_POLYGON_OFFSET_BIAS 0x00000388 -# define NV097_SET_FRONT_POLYGON_MODE 0x0000038C -# define NV097_SET_FRONT_POLYGON_MODE_V_POINT 0x1B00 -# define NV097_SET_FRONT_POLYGON_MODE_V_LINE 0x1B01 -# define NV097_SET_FRONT_POLYGON_MODE_V_FILL 0x1B02 -# define NV097_SET_BACK_POLYGON_MODE 0x00000390 -# define NV097_SET_CLIP_MIN 0x00000394 -# define NV097_SET_CLIP_MAX 0x00000398 -# define NV097_SET_CULL_FACE 0x0000039C -# define NV097_SET_CULL_FACE_V_FRONT 0x404 -# define NV097_SET_CULL_FACE_V_BACK 0x405 -# define NV097_SET_CULL_FACE_V_FRONT_AND_BACK 0x408 -# define NV097_SET_FRONT_FACE 0x000003A0 -# define NV097_SET_FRONT_FACE_V_CW 0x900 -# define NV097_SET_FRONT_FACE_V_CCW 0x901 -# define NV097_SET_NORMALIZATION_ENABLE 0x000003A4 -# define NV097_SET_LIGHT_ENABLE_MASK 0x000003BC -# define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_OFF 0 -# define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_INFINITE 1 -# define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_LOCAL 2 -# define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_SPOT 3 -# define NV097_SET_TEXGEN_S 0x000003C0 -# define NV097_SET_TEXGEN_S_DISABLE 0x0000 -# define NV097_SET_TEXGEN_S_EYE_LINEAR 0x2400 -# define NV097_SET_TEXGEN_S_OBJECT_LINEAR 0x2401 -# define NV097_SET_TEXGEN_S_SPHERE_MAP 0x2402 -# define NV097_SET_TEXGEN_S_REFLECTION_MAP 0x8512 -# define NV097_SET_TEXGEN_S_NORMAL_MAP 0x8511 -# define NV097_SET_TEXGEN_T 0x000003C4 -# define NV097_SET_TEXGEN_R 0x000003C8 -# define NV097_SET_TEXGEN_Q 0x000003CC -# define NV097_SET_TEXTURE_MATRIX_ENABLE 0x00000420 -# define NV097_SET_PROJECTION_MATRIX 0x00000440 -# define NV097_SET_MODEL_VIEW_MATRIX 0x00000480 -# define NV097_SET_INVERSE_MODEL_VIEW_MATRIX 0x00000580 -# define NV097_SET_COMPOSITE_MATRIX 0x00000680 -# define NV097_SET_TEXTURE_MATRIX 0x000006C0 -# define NV097_SET_FOG_PARAMS 0x000009C0 -# define NV097_SET_TEXGEN_PLANE_S 0x00000840 -# define NV097_SET_TEXGEN_PLANE_T 0x00000850 -# define NV097_SET_TEXGEN_PLANE_R 0x00000860 -# define NV097_SET_TEXGEN_PLANE_Q 0x00000870 -# define NV097_SET_TEXGEN_VIEW_MODEL 0x000009CC -# define NV097_SET_TEXGEN_VIEW_MODEL_LOCAL_VIEWER 0 -# define NV097_SET_TEXGEN_VIEW_MODEL_INFINITE_VIEWER 1 -# define NV097_SET_FOG_PLANE 0x000009D0 -# define NV097_SET_SCENE_AMBIENT_COLOR 0x00000A10 -# define NV097_SET_VIEWPORT_OFFSET 0x00000A20 -# define NV097_SET_EYE_POSITION 0x00000A50 -# define NV097_SET_COMBINER_FACTOR0 0x00000A60 -# define NV097_SET_COMBINER_FACTOR1 0x00000A80 -# define NV097_SET_COMBINER_ALPHA_OCW 0x00000AA0 -# define NV097_SET_COMBINER_COLOR_ICW 0x00000AC0 -# define NV097_SET_VIEWPORT_SCALE 0x00000AF0 -# define NV097_SET_TRANSFORM_PROGRAM 0x00000B00 -# define NV097_SET_TRANSFORM_CONSTANT 0x00000B80 -# define NV097_SET_VERTEX3F 0x00001500 -# define NV097_SET_BACK_LIGHT_AMBIENT_COLOR 0x00000C00 -# define NV097_SET_BACK_LIGHT_DIFFUSE_COLOR 0x00000C0C -# define NV097_SET_BACK_LIGHT_SPECULAR_COLOR 0x00000C18 -# define NV097_SET_LIGHT_AMBIENT_COLOR 0x00001000 -# define NV097_SET_LIGHT_DIFFUSE_COLOR 0x0000100C -# define NV097_SET_LIGHT_SPECULAR_COLOR 0x00001018 -# define NV097_SET_LIGHT_LOCAL_RANGE 0x00001024 -# define NV097_SET_LIGHT_INFINITE_HALF_VECTOR 0x00001028 -# define NV097_SET_LIGHT_INFINITE_DIRECTION 0x00001034 -# define NV097_SET_LIGHT_SPOT_FALLOFF 0x00001040 -# define NV097_SET_LIGHT_SPOT_DIRECTION 0x0000104C -# define NV097_SET_LIGHT_LOCAL_POSITION 0x0000105C -# define NV097_SET_LIGHT_LOCAL_ATTENUATION 0x00001068 -# define NV097_SET_VERTEX4F 0x00001518 -# define NV097_SET_VERTEX_DATA_ARRAY_OFFSET 0x00001720 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT 0x00001760 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE 0x0000000F -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_D3D 0 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S1 1 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_F 2 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_UB_OGL 4 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_S32K 5 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_TYPE_CMP 6 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_SIZE 0x000000F0 -# define NV097_SET_VERTEX_DATA_ARRAY_FORMAT_STRIDE 0xFFFFFF00 -# define NV097_SET_LOGIC_OP_ENABLE 0x000017BC -# define NV097_SET_LOGIC_OP 0x000017C0 -# define NV097_CLEAR_REPORT_VALUE 0x000017C8 -# define NV097_CLEAR_REPORT_VALUE_TYPE 0xFFFFFFFF -# define NV097_CLEAR_REPORT_VALUE_TYPE_ZPASS_PIXEL_CNT 1 -# define NV097_SET_ZPASS_PIXEL_COUNT_ENABLE 0x000017CC -# define NV097_GET_REPORT 0x000017D0 -# define NV097_GET_REPORT_OFFSET 0x00FFFFFF -# define NV097_GET_REPORT_TYPE 0xFF000000 -# define NV097_GET_REPORT_TYPE_ZPASS_PIXEL_CNT 1 -# define NV097_SET_EYE_DIRECTION 0x000017E0 -# define NV097_SET_SHADER_CLIP_PLANE_MODE 0x000017F8 -# define NV097_SET_BEGIN_END 0x000017FC -# define NV097_SET_BEGIN_END_OP_END 0x00 -# define NV097_SET_BEGIN_END_OP_POINTS 0x01 -# define NV097_SET_BEGIN_END_OP_LINES 0x02 -# define NV097_SET_BEGIN_END_OP_LINE_LOOP 0x03 -# define NV097_SET_BEGIN_END_OP_LINE_STRIP 0x04 -# define NV097_SET_BEGIN_END_OP_TRIANGLES 0x05 -# define NV097_SET_BEGIN_END_OP_TRIANGLE_STRIP 0x06 -# define NV097_SET_BEGIN_END_OP_TRIANGLE_FAN 0x07 -# define NV097_SET_BEGIN_END_OP_QUADS 0x08 -# define NV097_SET_BEGIN_END_OP_QUAD_STRIP 0x09 -# define NV097_SET_BEGIN_END_OP_POLYGON 0x0A -# define NV097_ARRAY_ELEMENT16 0x00001800 -# define NV097_ARRAY_ELEMENT32 0x00001808 -# define NV097_DRAW_ARRAYS 0x00001810 -# define NV097_DRAW_ARRAYS_COUNT 0xFF000000 -# define NV097_DRAW_ARRAYS_START_INDEX 0x00FFFFFF -# define NV097_INLINE_ARRAY 0x00001818 -# define NV097_SET_EYE_VECTOR 0x0000181C -# define NV097_SET_VERTEX_DATA2F_M 0x00001880 -# define NV097_SET_VERTEX_DATA4F_M 0x00001A00 -# define NV097_SET_VERTEX_DATA2S 0x00001900 -# define NV097_SET_VERTEX_DATA4UB 0x00001940 -# define NV097_SET_VERTEX_DATA4S_M 0x00001980 -# define NV097_SET_TEXTURE_OFFSET 0x00001B00 -# define NV097_SET_TEXTURE_FORMAT 0x00001B04 -# define NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA 0x00000003 -# define NV097_SET_TEXTURE_FORMAT_CUBEMAP_ENABLE (1 << 2) -# define NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE (1 << 3) -# define NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_TEXTURE 0 -# define NV097_SET_TEXTURE_FORMAT_BORDER_SOURCE_COLOR 1 -# define NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY 0x000000F0 -# define NV097_SET_TEXTURE_FORMAT_COLOR 0x0000FF00 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_Y8 0x00 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_AY8 0x01 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A1R5G5B5 0x02 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5 0x03 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A4R4G4B4 0x04 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R5G6B5 0x05 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8R8G8B8 0x06 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8 0x07 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8 0x0B -# define NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT1_A1R5G5B5 0x0C -# define NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT23_A8R8G8B8 0x0E -# define NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT45_A8R8G8B8 0x0F -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A1R5G5B5 0x10 -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_R5G6B5 0x11 -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8R8G8B8 0x12 -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y8 0x13 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8 0x19 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8Y8 0x1A -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_AY8 0x1B -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X1R5G5B5 0x1C -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A4R4G4B4 0x1D -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8 0x1E -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8 0x1F -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8Y8 0x20 -# define NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8 0x24 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R6G5B5 0x27 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_G8B8 0x28 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R8B8 0x29 -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED 0x2E -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FIXED 0x30 -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y16 0x35 -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8B8G8R8 0x3A -# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R8G8B8A8 0x3C -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_A8B8G8R8 0x3F -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_B8G8R8A8 0x40 -# define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_R8G8B8A8 0x41 -# define NV097_SET_TEXTURE_FORMAT_MIPMAP_LEVELS 0x000F0000 -# define NV097_SET_TEXTURE_FORMAT_BASE_SIZE_U 0x00F00000 -# define NV097_SET_TEXTURE_FORMAT_BASE_SIZE_V 0x0F000000 -# define NV097_SET_TEXTURE_FORMAT_BASE_SIZE_P 0xF0000000 -# define NV097_SET_TEXTURE_ADDRESS 0x00001B08 -# define NV097_SET_TEXTURE_CONTROL0 0x00001B0C -# define NV097_SET_TEXTURE_CONTROL0_ENABLE (1 << 30) -# define NV097_SET_TEXTURE_CONTROL0_MIN_LOD_CLAMP 0x3FFC0000 -# define NV097_SET_TEXTURE_CONTROL0_MAX_LOD_CLAMP 0x0003FFC0 -# define NV097_SET_TEXTURE_CONTROL1 0x00001B10 -# define NV097_SET_TEXTURE_CONTROL1_IMAGE_PITCH 0xFFFF0000 -# define NV097_SET_TEXTURE_FILTER 0x00001B14 -# define NV097_SET_TEXTURE_FILTER_MIPMAP_LOD_BIAS 0x00001FFF -# define NV097_SET_TEXTURE_FILTER_MIN 0x00FF0000 -# define NV097_SET_TEXTURE_FILTER_MAG 0x0F000000 -# define NV097_SET_TEXTURE_FILTER_ASIGNED (1 << 28) -# define NV097_SET_TEXTURE_FILTER_RSIGNED (1 << 29) -# define NV097_SET_TEXTURE_FILTER_GSIGNED (1 << 30) -# define NV097_SET_TEXTURE_FILTER_BSIGNED (1 << 31) -# define NV097_SET_TEXTURE_IMAGE_RECT 0x00001B1C -# define NV097_SET_TEXTURE_IMAGE_RECT_WIDTH 0xFFFF0000 -# define NV097_SET_TEXTURE_IMAGE_RECT_HEIGHT 0x0000FFFF -# define NV097_SET_TEXTURE_PALETTE 0x00001B20 -# define NV097_SET_TEXTURE_PALETTE_CONTEXT_DMA (1 << 0) -# define NV097_SET_TEXTURE_PALETTE_LENGTH 0x0000000C -# define NV097_SET_TEXTURE_PALETTE_LENGTH_256 0 -# define NV097_SET_TEXTURE_PALETTE_LENGTH_128 1 -# define NV097_SET_TEXTURE_PALETTE_LENGTH_64 2 -# define NV097_SET_TEXTURE_PALETTE_LENGTH_32 3 -# define NV097_SET_TEXTURE_PALETTE_OFFSET 0xFFFFFFC0 -# define NV097_SET_TEXTURE_BORDER_COLOR 0x00001B24 -# define NV097_SET_TEXTURE_SET_BUMP_ENV_MAT 0x00001B28 -# define NV097_SET_TEXTURE_SET_BUMP_ENV_SCALE 0x00001B38 -# define NV097_SET_TEXTURE_SET_BUMP_ENV_OFFSET 0x00001B3C -# define NV097_SET_SEMAPHORE_OFFSET 0x00001D6C -# define NV097_BACK_END_WRITE_SEMAPHORE_RELEASE 0x00001D70 -# define NV097_SET_ZSTENCIL_CLEAR_VALUE 0x00001D8C -# define NV097_SET_COLOR_CLEAR_VALUE 0x00001D90 -# define NV097_CLEAR_SURFACE 0x00001D94 -# define NV097_CLEAR_SURFACE_Z (1 << 0) -# define NV097_CLEAR_SURFACE_STENCIL (1 << 1) -# define NV097_CLEAR_SURFACE_COLOR 0x000000F0 -# define NV097_CLEAR_SURFACE_R (1 << 4) -# define NV097_CLEAR_SURFACE_G (1 << 5) -# define NV097_CLEAR_SURFACE_B (1 << 6) -# define NV097_CLEAR_SURFACE_A (1 << 7) -# define NV097_SET_CLEAR_RECT_HORIZONTAL 0x00001D98 -# define NV097_SET_CLEAR_RECT_VERTICAL 0x00001D9C -# define NV097_SET_SPECULAR_FOG_FACTOR 0x00001E20 -# define NV097_SET_COMBINER_COLOR_OCW 0x00001E40 -# define NV097_SET_COMBINER_CONTROL 0x00001E60 -# define NV097_SET_SHADOW_ZSLOPE_THRESHOLD 0x00001E68 -# define NV097_SET_SHADER_STAGE_PROGRAM 0x00001E70 -# define NV097_SET_SHADER_OTHER_STAGE_INPUT 0x00001E78 -# define NV097_SET_TRANSFORM_EXECUTION_MODE 0x00001E94 -# define NV097_SET_TRANSFORM_EXECUTION_MODE_MODE 0x00000003 -# define NV097_SET_TRANSFORM_EXECUTION_MODE_RANGE_MODE 0xFFFFFFFC -# define NV097_SET_TRANSFORM_PROGRAM_CXT_WRITE_EN 0x00001E98 -# define NV097_SET_TRANSFORM_PROGRAM_LOAD 0x00001E9C -# define NV097_SET_TRANSFORM_PROGRAM_START 0x00001EA0 -# define NV097_SET_TRANSFORM_CONSTANT_LOAD 0x00001EA4 - -/* vertex processing (cheops) context layout */ -#define NV_IGRAPH_XF_XFCTX_CMAT0 0x00 -#define NV_IGRAPH_XF_XFCTX_PMAT0 0x04 -#define NV_IGRAPH_XF_XFCTX_MMAT0 0x08 -#define NV_IGRAPH_XF_XFCTX_IMMAT0 0x0c -#define NV_IGRAPH_XF_XFCTX_MMAT1 0x10 -#define NV_IGRAPH_XF_XFCTX_IMMAT1 0x14 -#define NV_IGRAPH_XF_XFCTX_MMAT2 0x18 -#define NV_IGRAPH_XF_XFCTX_IMMAT2 0x1c -#define NV_IGRAPH_XF_XFCTX_MMAT3 0x20 -#define NV_IGRAPH_XF_XFCTX_IMMAT3 0x24 -#define NV_IGRAPH_XF_XFCTX_LIT0 0x28 -#define NV_IGRAPH_XF_XFCTX_LIT1 0x29 -#define NV_IGRAPH_XF_XFCTX_LIT2 0x2a -#define NV_IGRAPH_XF_XFCTX_LIT3 0x2b -#define NV_IGRAPH_XF_XFCTX_LIT4 0x2c -#define NV_IGRAPH_XF_XFCTX_LIT5 0x2d -#define NV_IGRAPH_XF_XFCTX_LIT6 0x2e -#define NV_IGRAPH_XF_XFCTX_LIT7 0x2f -#define NV_IGRAPH_XF_XFCTX_SPOT0 0x30 -#define NV_IGRAPH_XF_XFCTX_SPOT1 0x31 -#define NV_IGRAPH_XF_XFCTX_SPOT2 0x32 -#define NV_IGRAPH_XF_XFCTX_SPOT3 0x33 -#define NV_IGRAPH_XF_XFCTX_SPOT4 0x34 -#define NV_IGRAPH_XF_XFCTX_SPOT5 0x35 -#define NV_IGRAPH_XF_XFCTX_SPOT6 0x36 -#define NV_IGRAPH_XF_XFCTX_SPOT7 0x37 -#define NV_IGRAPH_XF_XFCTX_EYEP 0x38 -#define NV_IGRAPH_XF_XFCTX_FOG 0x39 -#define NV_IGRAPH_XF_XFCTX_VPSCL 0x3a -#define NV_IGRAPH_XF_XFCTX_VPOFF 0x3b -#define NV_IGRAPH_XF_XFCTX_CONS0 0x3c -#define NV_IGRAPH_XF_XFCTX_CONS1 0x3d -#define NV_IGRAPH_XF_XFCTX_CONS2 0x3e -#define NV_IGRAPH_XF_XFCTX_CONS3 0x3f -#define NV_IGRAPH_XF_XFCTX_TG0MAT 0x40 -#define NV_IGRAPH_XF_XFCTX_T0MAT 0x44 -#define NV_IGRAPH_XF_XFCTX_TG1MAT 0x48 -#define NV_IGRAPH_XF_XFCTX_T1MAT 0x4c -#define NV_IGRAPH_XF_XFCTX_TG2MAT 0x50 -#define NV_IGRAPH_XF_XFCTX_T2MAT 0x54 -#define NV_IGRAPH_XF_XFCTX_TG3MAT 0x58 -#define NV_IGRAPH_XF_XFCTX_T3MAT 0x5c -#define NV_IGRAPH_XF_XFCTX_PRSPACE 0x60 - -/* lighting (zoser) context layout */ -#define NV_IGRAPH_XF_LTCTXA_L0_K 0x00 -#define NV_IGRAPH_XF_LTCTXA_L0_SPT 0x01 -#define NV_IGRAPH_XF_LTCTXA_L1_K 0x02 -#define NV_IGRAPH_XF_LTCTXA_L1_SPT 0x03 -#define NV_IGRAPH_XF_LTCTXA_L2_K 0x04 -#define NV_IGRAPH_XF_LTCTXA_L2_SPT 0x05 -#define NV_IGRAPH_XF_LTCTXA_L3_K 0x06 -#define NV_IGRAPH_XF_LTCTXA_L3_SPT 0x07 -#define NV_IGRAPH_XF_LTCTXA_L4_K 0x08 -#define NV_IGRAPH_XF_LTCTXA_L4_SPT 0x09 -#define NV_IGRAPH_XF_LTCTXA_L5_K 0x0a -#define NV_IGRAPH_XF_LTCTXA_L5_SPT 0x0b -#define NV_IGRAPH_XF_LTCTXA_L6_K 0x0c -#define NV_IGRAPH_XF_LTCTXA_L6_SPT 0x0d -#define NV_IGRAPH_XF_LTCTXA_L7_K 0x0e -#define NV_IGRAPH_XF_LTCTXA_L7_SPT 0x0f -#define NV_IGRAPH_XF_LTCTXA_EYED 0x10 -#define NV_IGRAPH_XF_LTCTXA_FR_AMB 0x11 -#define NV_IGRAPH_XF_LTCTXA_BR_AMB 0x12 -#define NV_IGRAPH_XF_LTCTXA_CM_COL 0x13 -#define NV_IGRAPH_XF_LTCTXA_BCM_COL 0x14 -#define NV_IGRAPH_XF_LTCTXA_FOG_K 0x15 -#define NV_IGRAPH_XF_LTCTXA_ZERO 0x16 -#define NV_IGRAPH_XF_LTCTXA_PT0 0x17 -#define NV_IGRAPH_XF_LTCTXA_FOGLIN 0x18 - -#define NV_IGRAPH_XF_LTCTXB_L0_AMB 0x00 -#define NV_IGRAPH_XF_LTCTXB_L0_DIF 0x01 -#define NV_IGRAPH_XF_LTCTXB_L0_SPC 0x02 -#define NV_IGRAPH_XF_LTCTXB_L0_BAMB 0x03 -#define NV_IGRAPH_XF_LTCTXB_L0_BDIF 0x04 -#define NV_IGRAPH_XF_LTCTXB_L0_BSPC 0x05 -#define NV_IGRAPH_XF_LTCTXB_L1_AMB 0x06 -#define NV_IGRAPH_XF_LTCTXB_L1_DIF 0x07 -#define NV_IGRAPH_XF_LTCTXB_L1_SPC 0x08 -#define NV_IGRAPH_XF_LTCTXB_L1_BAMB 0x09 -#define NV_IGRAPH_XF_LTCTXB_L1_BDIF 0x0a -#define NV_IGRAPH_XF_LTCTXB_L1_BSPC 0x0b -#define NV_IGRAPH_XF_LTCTXB_L2_AMB 0x0c -#define NV_IGRAPH_XF_LTCTXB_L2_DIF 0x0d -#define NV_IGRAPH_XF_LTCTXB_L2_SPC 0x0e -#define NV_IGRAPH_XF_LTCTXB_L2_BAMB 0x0f -#define NV_IGRAPH_XF_LTCTXB_L2_BDIF 0x10 -#define NV_IGRAPH_XF_LTCTXB_L2_BSPC 0x11 -#define NV_IGRAPH_XF_LTCTXB_L3_AMB 0x12 -#define NV_IGRAPH_XF_LTCTXB_L3_DIF 0x13 -#define NV_IGRAPH_XF_LTCTXB_L3_SPC 0x14 -#define NV_IGRAPH_XF_LTCTXB_L3_BAMB 0x15 -#define NV_IGRAPH_XF_LTCTXB_L3_BDIF 0x16 -#define NV_IGRAPH_XF_LTCTXB_L3_BSPC 0x17 -#define NV_IGRAPH_XF_LTCTXB_L4_AMB 0x18 -#define NV_IGRAPH_XF_LTCTXB_L4_DIF 0x19 -#define NV_IGRAPH_XF_LTCTXB_L4_SPC 0x1a -#define NV_IGRAPH_XF_LTCTXB_L4_BAMB 0x1b -#define NV_IGRAPH_XF_LTCTXB_L4_BDIF 0x1c -#define NV_IGRAPH_XF_LTCTXB_L4_BSPC 0x1d -#define NV_IGRAPH_XF_LTCTXB_L5_AMB 0x1e -#define NV_IGRAPH_XF_LTCTXB_L5_DIF 0x1f -#define NV_IGRAPH_XF_LTCTXB_L5_SPC 0x20 -#define NV_IGRAPH_XF_LTCTXB_L5_BAMB 0x21 -#define NV_IGRAPH_XF_LTCTXB_L5_BDIF 0x22 -#define NV_IGRAPH_XF_LTCTXB_L5_BSPC 0x23 -#define NV_IGRAPH_XF_LTCTXB_L6_AMB 0x24 -#define NV_IGRAPH_XF_LTCTXB_L6_DIF 0x25 -#define NV_IGRAPH_XF_LTCTXB_L6_SPC 0x26 -#define NV_IGRAPH_XF_LTCTXB_L6_BAMB 0x27 -#define NV_IGRAPH_XF_LTCTXB_L6_BDIF 0x28 -#define NV_IGRAPH_XF_LTCTXB_L6_BSPC 0x29 -#define NV_IGRAPH_XF_LTCTXB_L7_AMB 0x2a -#define NV_IGRAPH_XF_LTCTXB_L7_DIF 0x2b -#define NV_IGRAPH_XF_LTCTXB_L7_SPC 0x2c -#define NV_IGRAPH_XF_LTCTXB_L7_BAMB 0x2d -#define NV_IGRAPH_XF_LTCTXB_L7_BDIF 0x2e -#define NV_IGRAPH_XF_LTCTXB_L7_BSPC 0x2f -#define NV_IGRAPH_XF_LTCTXB_PT1 0x30 -#define NV_IGRAPH_XF_LTCTXB_ONE 0x31 -#define NV_IGRAPH_XF_LTCTXB_VPOFFSET 0x32 - -#define NV_IGRAPH_XF_LTC1_ZERO1 0x00 -#define NV_IGRAPH_XF_LTC1_l0 0x01 -#define NV_IGRAPH_XF_LTC1_Bl0 0x02 -#define NV_IGRAPH_XF_LTC1_PP 0x03 -#define NV_IGRAPH_XF_LTC1_r0 0x04 -#define NV_IGRAPH_XF_LTC1_r1 0x05 -#define NV_IGRAPH_XF_LTC1_r2 0x06 -#define NV_IGRAPH_XF_LTC1_r3 0x07 -#define NV_IGRAPH_XF_LTC1_r4 0x08 -#define NV_IGRAPH_XF_LTC1_r5 0x09 -#define NV_IGRAPH_XF_LTC1_r6 0x0a -#define NV_IGRAPH_XF_LTC1_r7 0x0b -#define NV_IGRAPH_XF_LTC1_L0 0x0c -#define NV_IGRAPH_XF_LTC1_L1 0x0d -#define NV_IGRAPH_XF_LTC1_L2 0x0e -#define NV_IGRAPH_XF_LTC1_L3 0x0f -#define NV_IGRAPH_XF_LTC1_L4 0x10 -#define NV_IGRAPH_XF_LTC1_L5 0x11 -#define NV_IGRAPH_XF_LTC1_L6 0x12 -#define NV_IGRAPH_XF_LTC1_L7 0x13 - - -#define NV2A_VERTEX_ATTR_POSITION 0 -#define NV2A_VERTEX_ATTR_WEIGHT 1 -#define NV2A_VERTEX_ATTR_NORMAL 2 -#define NV2A_VERTEX_ATTR_DIFFUSE 3 -#define NV2A_VERTEX_ATTR_SPECULAR 4 -#define NV2A_VERTEX_ATTR_FOG 5 -#define NV2A_VERTEX_ATTR_POINT_SIZE 6 -#define NV2A_VERTEX_ATTR_BACK_DIFFUSE 7 -#define NV2A_VERTEX_ATTR_BACK_SPECULAR 8 -#define NV2A_VERTEX_ATTR_TEXTURE0 9 -#define NV2A_VERTEX_ATTR_TEXTURE1 10 -#define NV2A_VERTEX_ATTR_TEXTURE2 11 -#define NV2A_VERTEX_ATTR_TEXTURE3 12 -#define NV2A_VERTEX_ATTR_RESERVED1 13 -#define NV2A_VERTEX_ATTR_RESERVED2 14 -#define NV2A_VERTEX_ATTR_RESERVED3 15 - -#define NV2A_CRYSTAL_FREQ 13500000 -#define NV2A_NUM_CHANNELS 32 -#define NV2A_NUM_SUBCHANNELS 8 -#define NV2A_CACHE1_SIZE 128 - -#define NV2A_MAX_BATCH_LENGTH 0x1FFFF -#define NV2A_VERTEXSHADER_ATTRIBUTES 16 -#define NV2A_MAX_TEXTURES 4 - -#define NV2A_MAX_TRANSFORM_PROGRAM_LENGTH 136 -#define NV2A_VERTEXSHADER_CONSTANTS 192 -#define NV2A_MAX_LIGHTS 8 - -#define NV2A_LTCTXA_COUNT 26 -#define NV2A_LTCTXB_COUNT 52 -#define NV2A_LTC1_COUNT 20 diff --git a/modules/core/include/strikebox/hw/nv2a/vga.h b/modules/core/include/strikebox/hw/nv2a/vga.h deleted file mode 100644 index 1198572..0000000 --- a/modules/core/include/strikebox/hw/nv2a/vga.h +++ /dev/null @@ -1,156 +0,0 @@ -#pragma once - -/* - * linux/include/video/vga.h -- standard VGA chipset interaction - * - * Copyright 1999 Jeff Garzik - * - * Copyright history from vga16fb.c: - * Copyright 1999 Ben Pfaff and Petr Vandrovec - * Based on VGA info at http://www.osdever.net/FreeVGA/home.htm - * Based on VESA framebuffer (c) 1998 Gerd Knorr - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of this - * archive for more details. - * - */ - -/* Some of the code below is taken from SVGAlib. The original, - unmodified copyright notice for that code is below. */ -/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */ -/* */ -/* This library is free software; you can redistribute it and/or */ -/* modify it without any restrictions. This library is distributed */ -/* in the hope that it will be useful, but without any warranty. */ - -/* Multi-chipset support Copyright 1993 Harm Hanemaayer */ -/* partially copyrighted (C) 1993 by Hartmut Schirmer */ - -/* VGA data register ports */ -#define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */ -#define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono emulation */ -#define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */ -#define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */ -#define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */ -#define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */ -#define VGA_MIS_R 0x3CC /* Misc Output Read Register */ -#define VGA_MIS_W 0x3C2 /* Misc Output Write Register */ -#define VGA_FTC_R 0x3CA /* Feature Control Read Register */ -#define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */ -#define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */ -#define VGA_PEL_D 0x3C9 /* PEL Data Register */ -#define VGA_PEL_MSK 0x3C6 /* PEL mask register */ - -/* EGA-specific registers */ -#define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */ -#define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */ - -/* VGA index register ports */ -#define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */ -#define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */ -#define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */ -#define VGA_GFX_I 0x3CE /* Graphics Controller Index */ -#define VGA_SEQ_I 0x3C4 /* Sequencer Index */ -#define VGA_PEL_IW 0x3C8 /* PEL Write Index */ -#define VGA_PEL_IR 0x3C7 /* PEL Read Index */ - -/* standard VGA indexes max counts */ -#define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */ -#define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */ -#define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */ -#define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */ -#define VGA_MIS_C 0x01 /* Number of Misc Output Register */ - -/* VGA misc register bit masks */ -#define VGA_MIS_COLOR 0x01 -#define VGA_MIS_ENB_MEM_ACCESS 0x02 -#define VGA_MIS_DCLK_28322_720 0x04 -#define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08) -#define VGA_MIS_SEL_HIGH_PAGE 0x20 - -/* VGA CRT controller register indices */ -#define VGA_CRTC_H_TOTAL 0 -#define VGA_CRTC_H_DISP 1 -#define VGA_CRTC_H_BLANK_START 2 -#define VGA_CRTC_H_BLANK_END 3 -#define VGA_CRTC_H_SYNC_START 4 -#define VGA_CRTC_H_SYNC_END 5 -#define VGA_CRTC_V_TOTAL 6 -#define VGA_CRTC_OVERFLOW 7 -#define VGA_CRTC_PRESET_ROW 8 -#define VGA_CRTC_MAX_SCAN 9 -#define VGA_CRTC_CURSOR_START 0x0A -#define VGA_CRTC_CURSOR_END 0x0B -#define VGA_CRTC_START_HI 0x0C -#define VGA_CRTC_START_LO 0x0D -#define VGA_CRTC_CURSOR_HI 0x0E -#define VGA_CRTC_CURSOR_LO 0x0F -#define VGA_CRTC_V_SYNC_START 0x10 -#define VGA_CRTC_V_SYNC_END 0x11 -#define VGA_CRTC_V_DISP_END 0x12 -#define VGA_CRTC_OFFSET 0x13 -#define VGA_CRTC_UNDERLINE 0x14 -#define VGA_CRTC_V_BLANK_START 0x15 -#define VGA_CRTC_V_BLANK_END 0x16 -#define VGA_CRTC_MODE 0x17 -#define VGA_CRTC_LINE_COMPARE 0x18 -#define VGA_CRTC_REGS VGA_CRT_C - -/* VGA CRT controller bit masks */ -#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */ -#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80 - -/* VGA attribute controller register indices */ -#define VGA_ATC_PALETTE0 0x00 -#define VGA_ATC_PALETTE1 0x01 -#define VGA_ATC_PALETTE2 0x02 -#define VGA_ATC_PALETTE3 0x03 -#define VGA_ATC_PALETTE4 0x04 -#define VGA_ATC_PALETTE5 0x05 -#define VGA_ATC_PALETTE6 0x06 -#define VGA_ATC_PALETTE7 0x07 -#define VGA_ATC_PALETTE8 0x08 -#define VGA_ATC_PALETTE9 0x09 -#define VGA_ATC_PALETTEA 0x0A -#define VGA_ATC_PALETTEB 0x0B -#define VGA_ATC_PALETTEC 0x0C -#define VGA_ATC_PALETTED 0x0D -#define VGA_ATC_PALETTEE 0x0E -#define VGA_ATC_PALETTEF 0x0F -#define VGA_ATC_MODE 0x10 -#define VGA_ATC_OVERSCAN 0x11 -#define VGA_ATC_PLANE_ENABLE 0x12 -#define VGA_ATC_PEL 0x13 -#define VGA_ATC_COLOR_PAGE 0x14 - -#define VGA_AR_ENABLE_DISPLAY 0x20 - -/* VGA sequencer register indices */ -#define VGA_SEQ_RESET 0x00 -#define VGA_SEQ_CLOCK_MODE 0x01 -#define VGA_SEQ_PLANE_WRITE 0x02 -#define VGA_SEQ_CHARACTER_MAP 0x03 -#define VGA_SEQ_MEMORY_MODE 0x04 - -/* VGA sequencer register bit masks */ -#define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots wide are generated */ -#define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */ -#define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */ -#define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to 256K */ -#define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a sequential addressing mode */ -#define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */ - -/* VGA graphics controller register indices */ -#define VGA_GFX_SR_VALUE 0x00 -#define VGA_GFX_SR_ENABLE 0x01 -#define VGA_GFX_COMPARE_VALUE 0x02 -#define VGA_GFX_DATA_ROTATE 0x03 -#define VGA_GFX_PLANE_READ 0x04 -#define VGA_GFX_MODE 0x05 -#define VGA_GFX_MISC 0x06 -#define VGA_GFX_COMPARE_MASK 0x07 -#define VGA_GFX_BIT_MASK 0x08 - -/* VGA graphics controller bit masks */ -#define VGA_GR06_GRAPHICS_MODE 0x01 diff --git a/modules/core/include/strikebox/hw/ohci/ohci.h b/modules/core/include/strikebox/hw/ohci/ohci.h deleted file mode 100644 index 8ed7761..0000000 --- a/modules/core/include/strikebox/hw/ohci/ohci.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->USBController->OHCI.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#pragma once - -#include "virt86/virt86.hpp" - -#include "../pci/usb_pci.h" -#include "strikebox/cxbxtimer.h" - -namespace strikebox { - -// Abbreviations used: -// OHCI: Open Host Controller Interface; the standard used on the Xbox to comunicate with the usb devices -// HC: Host Controller; the hardware which interfaces with the usb device and the usb driver -// HCD: Host Controller Driver; software which talks to the HC, it's linked in the xbe -// SOF: start of frame; the beginning of a USB-defined frame -// EOF: end of frame; the end of a USB-defined frame -// ED: endpoint descriptor; a memory structure used by the HC to communicate with an endpoint -// TD: transfer descriptor; a memory structure used by the HC to transfer a block of data to/from a device endpoint -// HCCA: Host Controller Communications Area; shared memory between the HC and HCD - - -/* endpoint descriptor */ -struct OHCI_ED { - uint32_t Flags; - uint32_t TailP; - uint32_t HeadP; - uint32_t NextED; -}; - -/* general transfer descriptor */ -struct OHCI_TD { - uint32_t Flags; - uint32_t CurrentBufferPointer; - uint32_t NextTD; - uint32_t BufferEnd; -}; - -/* Isochronous transfer descriptor */ -struct OHCI_ISO_TD { - uint32_t Flags; - uint32_t BufferPage0; - uint32_t NextTD; - uint32_t BufferEnd; - uint16_t Offset[8]; -}; - -/* enum indicating the current HC state */ -typedef enum _OHCI_State { - Reset = 0x00, - Resume = 0x40, - Operational = 0x80, - Suspend = 0xC0, -} -OHCI_State; - -/* Host Controller Communications Area */ -struct OHCI_HCCA { - uint32_t HccaInterrruptTable[32]; - uint16_t HccaFrameNumber, HccaPad1; - uint32_t HccaDoneHead; -}; - -/* Small struct used to hold the HcRhPortStatus register and the usb port status */ -struct OHCIPort { - USBPort UsbPort; - uint32_t HcRhPortStatus; -}; - -/* All these registers are well documented in the OHCI standard */ -struct OHCI_Registers { - // Control and Status partition - uint32_t HcRevision; - uint32_t HcControl; - uint32_t HcCommandStatus; - uint32_t HcInterruptStatus; - // HcInterruptEnable/Disable are the same so we can merge them together - uint32_t HcInterrupt; - - // Memory Pointer partition - uint32_t HcHCCA; - uint32_t HcPeriodCurrentED; - uint32_t HcControlHeadED; - uint32_t HcControlCurrentED; - uint32_t HcBulkHeadED; - uint32_t HcBulkCurrentED; - uint32_t HcDoneHead; - - // Frame Counter partition - uint32_t HcFmInterval; - uint32_t HcFmRemaining; - uint32_t HcFmNumber; - uint32_t HcPeriodicStart; - uint32_t HcLSThreshold; - - // Root Hub partition - uint32_t HcRhDescriptorA; - uint32_t HcRhDescriptorB; - uint32_t HcRhStatus; - OHCIPort RhPort[4]; // 4 ports per HC -}; - - -/* OHCI class representing the state of the HC */ -class OHCI { -public: - // Indicates that the timer thread is accessing the OHCI object. Necessary because the input thread from the - // InputDeviceManager will access us when it needs to create or destroy a device - std::atomic_bool m_bFrameTime; - - // constructor - OHCI(virt86::VirtualProcessor& vp, int Irqn, USBPCIDevice* UsbObj); - // destructor - ~OHCI() {} - // read a register - uint32_t OHCI_ReadRegister(uint32_t Addr); - // write a register - void OHCI_WriteRegister(uint32_t Addr, uint32_t Value); - -private: - virt86::VirtualProcessor& m_vp; - // pointer to g_USB0 or g_USB1 - USBPCIDevice* m_UsbDevice = nullptr; - // all the registers available in the OHCI standard - OHCI_Registers m_Registers; - // end-of-frame timer - TimerObject* m_pEOFtimer = nullptr; - // time at which a SOF was sent - uint64_t m_SOFtime; - // the duration of a usb frame - uint64_t m_UsbFrameTime; - // ticks per usb tick - uint64_t m_TicksPerUsbTick; - // pending usb packet to process - USBPacket m_UsbPacket = {}; - // temporary buffer that holds the user data to transfer in a packet - uint8_t m_UsbBuffer[8192] = {}; - // the value of HcControl in the previous frame - uint32_t m_OldHcControl; - // irq number - int m_IrqNum; - // Done Queue Interrupt Counter - int m_DoneCount; - // the address of the pending TD - uint32_t m_AsyncTD = 0; - // indicates if there is a pending asynchronous packet to process - bool m_AsyncComplete = 0; - - // EOF callback wrapper - static void OHCI_FrameBoundaryWrapper(void* pVoid); - // EOF callback function - void OHCI_FrameBoundaryWorker(); - // inform the HCD that we got a problem here... - void OHCI_FatalError(); - // initialize packet struct - void OHCI_PacketInit(USBPacket* packet); - // change usb state mode - void OHCI_ChangeState(uint32_t Value); - // switch the HC to the reset state - void OHCI_StateReset(); - // start sending SOF tokens across the usb bus - void OHCI_BusStart(); - // stop sending SOF tokens across the usb bus - void OHCI_BusStop(); - // generate a SOF event, and start a timer for EOF - void OHCI_SOF(bool bCreate); - // change interrupt status - void OHCI_UpdateInterrupt(); - // fire an interrupt - void OHCI_SetInterrupt(uint32_t Value); - // calculate frame time remaining - uint32_t OHCI_GetFrameRemaining(); - // halt the endpoints of the device - void OHCI_StopEndpoints(); - // set root hub status - void OHCI_SetHubStatus(uint32_t Value); - // update power related bits in HcRhPortStatus - void OHCI_PortPower(int i, int p); - // set root hub port status - void OHCI_PortSetStatus(int PortNum, uint32_t Value); - // set a flag in a port status register but only set it if the port is connected, - // if not set ConnectStatusChange flag; if flag is enabled return 1 - int OHCI_PortSetIfConnected(int i, uint32_t Value); - // read the HCCA structure in memory - bool OHCI_ReadHCCA(uint32_t Paddr, OHCI_HCCA* Hcca); - // write the HCCA structure in memory - bool OHCI_WriteHCCA(uint32_t Paddr, OHCI_HCCA* Hcca); - // read an ED in memory - bool OHCI_ReadED(uint32_t Paddr, OHCI_ED* Ed); - // write an ED in memory - bool OHCI_WriteED(uint32_t Paddr, OHCI_ED* Ed); - // read an TD in memory - bool OHCI_ReadTD(uint32_t Paddr, OHCI_TD* Td); - // write a TD in memory - bool OHCI_WriteTD(uint32_t Paddr, OHCI_TD* Td); - // read an iso TD in memory - bool OHCI_ReadIsoTD(uint32_t Paddr, OHCI_ISO_TD* td); - // write an iso TD in memory - bool OHCI_WriteIsoTD(uint32_t Paddr, OHCI_ISO_TD* td); - // read/write the user buffer pointed to by a TD from/to main memory - bool OHCI_CopyTD(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite); - // read/write the user buffer pointed to by a ISO TD from/to main memory - bool OHCI_CopyIsoTD(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffer, int Length, bool bIsWrite); - // find a TD buffer in memory and copy it - bool OHCI_FindAndCopyTD(uint32_t Paddr, uint8_t* Buffer, int Length, bool bIsWrite); - // process an ED list. Returns nonzero if active TD was found - int OHCI_ServiceEDlist(uint32_t Head, int Completion); - // process a TD. Returns nonzero to terminate processing of this endpoint - int OHCI_ServiceTD(OHCI_ED* Ed); - // process an isochronous TD - int OHCI_ServiceIsoTD(OHCI_ED* ed, int completion); - // find the usb device with the supplied address - XboxDeviceState* OHCI_FindDevice(uint8_t Addr); - // cancel a packet when a device is removed - void OHCI_AsyncCancelDevice(XboxDeviceState* dev); - // Process Control and Bulk lists - void OHCI_ProcessLists(int completion); - // see USBPortOps struct for info - void OHCI_Attach(USBPort* Port); - void OHCI_Detach(USBPort* Port); - void OHCI_ChildDetach(XboxDeviceState* child); - void OHCI_Wakeup(USBPort* port1); - void OHCI_AsyncCompletePacket(USBPort* port, USBPacket* packet); -}; - -} diff --git a/modules/core/include/strikebox/hw/ohci/ohci_common.h b/modules/core/include/strikebox/hw/ohci/ohci_common.h deleted file mode 100644 index bd27a10..0000000 --- a/modules/core/include/strikebox/hw/ohci/ohci_common.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->usb->UsbCommon.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#pragma once - -#include "strikebox/queue.h" -#include "strikebox/iovec.h" - -namespace strikebox { - -#define USB_MAX_ENDPOINTS 15 -#define USB_MAX_INTERFACES 16 - -#define USB_STATE_NOTATTACHED 0 -#define USB_STATE_ATTACHED 1 -#define USB_STATE_DEFAULT 2 - -#define USB_CLASS_HUB 9 - -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 -#define USB_ENDPOINT_XFER_INVALID 255 - -#define USB_INTERFACE_INVALID 255 - -#define USB_DIR_OUT 0 -#define USB_DIR_IN 0x80 - -#define USB_TOKEN_SETUP 0x2D -#define USB_TOKEN_IN 0x69 // device -> host -#define USB_TOKEN_OUT 0xE1 // host -> device - -#define USB_SPEED_LOW 0 -#define USB_SPEED_FULL 1 - -#define USB_DEVICE_SELF_POWERED 0 -#define USB_DEVICE_REMOTE_WAKEUP 1 - -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) - -#define USB_RECIP_MASK 0x1F -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 - -#define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) -#define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) -#define VendorDeviceRequest ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) -#define VendorDeviceOutRequest ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8) - -#define InterfaceRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -#define InterfaceOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -#define ClassInterfaceRequest \ - ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) -#define ClassInterfaceOutRequest \ - ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) -#define VendorInterfaceRequest \ - ((USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8) -#define VendorInterfaceOutRequest \ - ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE)<<8) - -#define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) -#define EndpointOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) - -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -#define USB_DT_DEVICE 0x01 -#define USB_DT_CONFIG 0x02 -#define USB_DT_STRING 0x03 -#define USB_DT_INTERFACE 0x04 -#define USB_DT_ENDPOINT 0x05 - -#define USB_RET_SUCCESS (0) -#define USB_RET_NODEV (-1) -#define USB_RET_NAK (-2) -#define USB_RET_STALL (-3) -#define USB_RET_BABBLE (-4) -#define USB_RET_IOERROR (-5) -#define USB_RET_ASYNC (-6) -#define USB_RET_ADD_TO_QUEUE (-7) -#define USB_RET_REMOVE_FROM_QUEUE (-8) - -typedef enum _USB_SPEED { - USB_SPEED_MASK_LOW = 1 << 0, - USB_SPEED_MASK_FULL = 1 << 1, -} -USB_SPEED; - -typedef enum USBPacketState { - USB_PACKET_UNDEFINED = 0, - USB_PACKET_SETUP, - USB_PACKET_QUEUED, - USB_PACKET_ASYNC, - USB_PACKET_COMPLETE, - USB_PACKET_CANCELED, -} -USBPacketState; - -/* same as Linux kernel root hubs */ -typedef enum { - STR_MANUFACTURER = 1, - STR_PRODUCT, - STR_SERIALNUMBER, -} STRING_DESC_INDEX; - -// Forward declarations -struct USBPacket; -struct USBPort; -struct USBDeviceClass; -struct XboxDeviceState; -struct USBPortOps; - -/* String descriptor */ -struct USBDescString { - uint8_t index; // index of this string descriptor - std::string str; // the string of this string descriptor - QLIST_ENTRY(USBDescString) next; -}; - -// Device-specific class descriptors, if any. No idea if some Xbox devices use this but, if not, this can be removed -struct USBDescOther { - uint8_t length; - const uint8_t *data; -}; - -/* Endpoint descriptor */ -struct USBDescEndpoint { - uint8_t bEndpointAddress; // the address of the endpoint on the USB device described by this descriptor - uint8_t bmAttributes; // this field describes the endpoint's attributes when it is configured using the bConfigurationValue - uint16_t wMaxPacketSize; // maximum packet size this endpoint is capable of sending or receiving when this configuration is selected - uint8_t bInterval; // interval for polling endpoint for data transfers, expressed in milliseconds. - uint8_t bRefresh; // for audio devices only: the rate at which synchronization feedback is provided - uint8_t bSynchAddress; // for audio devices only: the address of the synchronization endpoint - - uint8_t is_audio; // has bRefresh + bSynchAddress - uint8_t* extra; // class-specific descriptors (if any) associated with this endpoint - - // Dropped from XQEMU the parameters bMaxBurst, bmAttributes_super and wBytesPerInterval because those are only defined for - // superspeed (usb 3.0) devices in the superspeed endpoint companion -}; - -/* Interface descriptor */ -struct USBDescIface { - uint8_t bInterfaceNumber; // number of interface - uint8_t bAlternateSetting; // value used to select the alternate setting for the interface identified by bInterfaceNumber - uint8_t bNumEndpoints; // number of endpoints used by this interface (excluding endpoint zero) - uint8_t bInterfaceClass; // class code (assigned by the USB) - uint8_t bInterfaceSubClass; // subclass code (assigned by the USB) - uint8_t bInterfaceProtocol; // protocol code (assigned by the USB) - uint8_t iInterface; // index of string descriptor describing this interface - - uint8_t ndesc; // number of device-specific class descriptors (if any) - USBDescOther* descs; // pointer to the extra class descriptors - const USBDescEndpoint* eps; // endpoints supported by this interface -}; - -/* - * ergo720: I removed the Interface Association Descriptor (IAD) since, at the time of this writing (2018), the xboxdevwiki documents that all - * known xid devices don't use them and also, according to the corresponding standard, IAD applies to usb revision 2.0 while the xbox uses - * usb revision 1.1 so it shouldn't support them either. If this turns out to be incorrect, then IAD support will have to be added - */ - -/* Configuration descriptor */ -struct USBDescConfig { - uint8_t bNumInterfaces; // number of interfaces supported by this configuration - uint8_t bConfigurationValue; // value to use as an argument to the SetConfiguration() request to select this configuration - uint8_t iConfiguration; // index of string descriptor describing this configuration - uint8_t bmAttributes; // configuration characteristics - uint8_t bMaxPower; // maximum power consumption of the USB device in this configuration expressed in 2mA units - - /* "normal" interfaces */ - uint8_t nif; // number of interfaces (again) - const USBDescIface* ifs; // interfaces supported by this configuration -}; - -/* Device descriptor part 1 */ -struct USBDescDevice { - uint16_t bcdUSB; // USB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H) - uint8_t bDeviceClass; // class code (assigned by the USB) - uint8_t bDeviceSubClass; // subclass code (assigned by the USB) - uint8_t bDeviceProtocol; // protocol code (assigned by the USB) - uint8_t bMaxPacketSize0; // maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid) - uint8_t bNumConfigurations; // number of possible configurations - const USBDescConfig* confs; // configurations supported by this device -}; - -/* Device descriptor part 2 */ -struct USBDescID { - uint16_t idVendor; // vendor ID (assigned by the USB) - uint16_t idProduct; // product ID (assigned by the manufacturer) - uint16_t bcdDevice; // device release number in binary-coded decimal - uint8_t iManufacturer; // index of string descriptor describing manufacturer - uint8_t iProduct; // index of string descriptor describing product - uint8_t iSerialNumber; // index of string descriptor describing the device's serial number -}; - -/* Global USB Descriptor struct */ -struct USBDesc { - USBDescID id; // id-specific info of the device descriptor - const USBDescDevice* full; // remaining fields of the device descriptor - const char* const* str; -}; - -#pragma pack(1) - -// Binary representation of the descriptors -// Dropped from XQEMU usb 2.0 and 3.0 only descriptors -struct USBDescriptor { - uint8_t bLength; - uint8_t bDescriptorType; - union { - struct { - uint8_t bcdUSB_lo; - uint8_t bcdUSB_hi; - uint8_t bDeviceClass; - uint8_t bDeviceSubClass; - uint8_t bDeviceProtocol; - uint8_t bMaxPacketSize0; - uint8_t idVendor_lo; - uint8_t idVendor_hi; - uint8_t idProduct_lo; - uint8_t idProduct_hi; - uint8_t bcdDevice_lo; - uint8_t bcdDevice_hi; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; - } device; // device descriptor - struct { - uint8_t wTotalLength_lo; - uint8_t wTotalLength_hi; - uint8_t bNumInterfaces; - uint8_t bConfigurationValue; - uint8_t iConfiguration; - uint8_t bmAttributes; - uint8_t bMaxPower; - } config; // configuration descriptor - struct { - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bNumEndpoints; - uint8_t bInterfaceClass; - uint8_t bInterfaceSubClass; - uint8_t bInterfaceProtocol; - uint8_t iInterface; - } iface; // interface descriptor - struct { - uint8_t bEndpointAddress; - uint8_t bmAttributes; - uint8_t wMaxPacketSize_lo; - uint8_t wMaxPacketSize_hi; - uint8_t bInterval; - uint8_t bRefresh; // only audio ep - uint8_t bSynchAddress; // only audio ep - } endpoint; // endpoint descriptor - } u; -}; - -#pragma pack() - -/* USB endpoint */ -struct USBEndpoint { - uint8_t Num; // endpoint number - uint8_t pid; - uint8_t Type; // the type of this endpoint - uint8_t IfNum; // interface number this endpoint belongs to - int MaxPacketSize; // maximum packet size supported by this endpoint - bool Pipeline; - bool Halted; // indicates that the endpoint is halted - XboxDeviceState* Dev; // device this endpoint belongs to - QTAILQ_HEAD(, USBPacket) Queue; // queue of packets to this endpoint -}; - -/* Struct describing the status of a usb port */ -struct USBPort { - XboxDeviceState* Dev = nullptr; // usb device(if present) - USBPortOps* Operations; // functions to call when a port event happens - int SpeedMask; // usb speeds supported - std::string Path; // the number of the port + 1, used to create a serial number for this device - int PortIndex; // internal port index -}; - -/* Struct which stores general functions/variables regarding the peripheral */ -struct USBDeviceClass { - std::function init; - - // Walk (enabled) downstream ports, check for a matching device. - // Only hubs implement this. - std::function find_device; - - // Called when a packet is canceled. - std::function cancel_packet; - - // Called when device is destroyed. - std::function handle_destroy; - - // Attach the device - std::function handle_attach; - - // Reset the device - std::function handle_reset; - - // Process control request. - // Called from handle_packet(). - // Status gets stored in p->status, and if p->status == USB_RET_SUCCESS - // then the number of bytes transferred is stored in p->actual_length - std::function handle_control; - - // Process data transfers (both BULK and ISOC). - // Called from handle_packet(). - // Status gets stored in p->status, and if p->status == USB_RET_SUCCESS - // then the number of bytes transferred is stored in p->actual_length - std::function handle_data; - - std::function set_interface; - - // Called when the hcd is done queuing packets for an endpoint, only - // necessary for devices which can return USB_RET_ADD_TO_QUEUE. - std::function flush_ep_queue; - - // Called by the hcd to let the device know the queue for an endpoint - // has been unlinked / stopped. Optional may be NULL. - std::function ep_stopped; - - const char* product_desc; // friendly name of the device - const USBDesc* usb_desc; // device descriptor -}; - -/* definition of an Xbox usb device */ -struct XboxDeviceState { - USBPort* Port; // usb port struct of this device - int PortPath; // port index to which this device is attached to - uint32_t flags; - USBDeviceClass* klass; // usb class struct of this device - - int Speed; // actual speed of the connected device - int SpeedMask; // supported speeds, not in info because it may be variable (hostdevs) - uint8_t Addr; // device function address - std::string ProductDesc; // the friendly name of this device - int Attached; // device is attached - - int32_t State; // current state of device - uint8_t SetupBuffer[8]; // setup packet buffer - 8 bytes (control transfers only) - uint8_t DataBuffer[4096]; // buffer where to write the data requested during usb requests - int32_t RemoteWakeup; // wakeup flag - int32_t SetupState; // result of a control transfer processing operation - uint32_t SetupLength; // this field specifies the length of the data transferred during the second phase of the control transfer - uint32_t SetupIndex; // index of the parameter in a setup token? - - USBEndpoint EP_ctl; // endpoints for SETUP tokens - USBEndpoint EP_in[USB_MAX_ENDPOINTS]; // endpoints for OUT tokens - USBEndpoint EP_out[USB_MAX_ENDPOINTS]; // endpoints for IN tokens - - QLIST_HEAD(, USBDescString) Strings; // strings of the string descriptors - const USBDesc* UsbDesc; // Overrides class usb_desc if not nullptr - const USBDescDevice* Device; // device descriptor part 1 - - int Configuration; // number of the selected configuration descriptor - int NumInterfaces; // number of available interface descriptors - int AltSetting[USB_MAX_INTERFACES]; // alternate setting numbers for the current interface - const USBDescConfig* Config; // configuration descriptor in use - const USBDescIface* Ifaces[USB_MAX_INTERFACES]; // interface in use -}; - -/* Structure used to hold information about an active USB packet */ -struct USBPacket { - int Pid; // Packet ID (used to identify the type of packet that is being sent) - uint32_t Id; // Paddr of the TD for this packet - USBEndpoint* Endpoint; // endpoint this packet is transferred to - unsigned int Stream; - IOVector IoVec; // used to perform vectored I/O - uint64_t Parameter; // this seems to be used only in xhci and it's 0 otherwise. If so, this can be removed - bool ShortNotOK; // the bufferRounding mode of the TD for this packet - bool IntReq; // whether or not to generate an interrupt for this packet (DelayInterrupt of the TD is zero) - int Status; // USB_RET_* status code - unsigned int ActualLength; // number of bytes actually written to DataBuffer - // Internal use by the USB layer - USBPacketState State; - QTAILQ_ENTRY(USBPacket) Queue; -}; - -struct USBPortOps { - std::function attach; - std::function detach; - /* - * This gets called when a device downstream from the device attached to - * the port (attached through a hub) gets detached. - */ - std::function child_detach; - std::function wakeup; - /* - * Note that port->dev will be different then the device from which - * the packet originated when a hub is involved. - */ - std::function complete; -}; - -} diff --git a/modules/core/include/strikebox/hw/ohci/ohci_hub.h b/modules/core/include/strikebox/hw/ohci/ohci_hub.h deleted file mode 100644 index a876e20..0000000 --- a/modules/core/include/strikebox/hw/ohci/ohci_hub.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->usb->Hub.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#pragma once - -#include "../pci/usb_pci.h" - -namespace strikebox { - -#define NUM_PORTS 8 - -#define PORT_STAT_CONNECTION 0x0001 -#define PORT_STAT_ENABLE 0x0002 -#define PORT_STAT_SUSPEND 0x0004 -#define PORT_STAT_OVERCURRENT 0x0008 -#define PORT_STAT_RESET 0x0010 -#define PORT_STAT_POWER 0x0100 -#define PORT_STAT_LOW_SPEED 0x0200 - -#define PORT_STAT_C_CONNECTION 0x0001 -#define PORT_STAT_C_ENABLE 0x0002 -#define PORT_STAT_C_SUSPEND 0x0004 -#define PORT_STAT_C_OVERCURRENT 0x0008 -#define PORT_STAT_C_RESET 0x0010 - -#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) -#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) -#define GetHubDescriptor (0xA000 | USB_REQ_GET_DESCRIPTOR) -#define GetHubStatus (0xA000 | USB_REQ_GET_STATUS) -#define GetPortStatus (0xA300 | USB_REQ_GET_STATUS) -#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) -#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) - -#define PORT_CONNECTION 0 -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVERCURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#define PORT_LOWSPEED 9 -#define PORT_C_CONNECTION 16 -#define PORT_C_ENABLE 17 -#define PORT_C_SUSPEND 18 -#define PORT_C_OVERCURRENT 19 -#define PORT_C_RESET 20 - -struct USBHubPort { - USBPort port; // downstream port status - uint16_t wPortStatus; // Port Status Field, in accordance with the standard - uint16_t wPortChange; // Port Change Field, in accordance with the standard -}; - -struct USBHubState { - XboxDeviceState dev; // hub device status - USBEndpoint* intr; // interrupt endpoint of the hub - USBHubPort ports[NUM_PORTS]; // downstream ports of the hub -}; - -/* Class which implements a usb hub */ -class Hub { -public: - // usb device this hub is attached to - USBPCIDevice* m_UsbDev = nullptr; - - // initialize this hub - int Init(int port); - // start hub destruction - void HubDestroy(); - - -private: - // hub state - USBHubState* m_HubState = nullptr; - // hub class functions - USBDeviceClass* m_pPeripheralFuncStruct = nullptr; - - // initialize various member variables/functions - XboxDeviceState* ClassInitFn(); - // see USBDeviceClass for comments about these functions - int UsbHub_Initfn(XboxDeviceState* dev); - XboxDeviceState* UsbHub_FindDevice(XboxDeviceState* dev, uint8_t addr); - void UsbHub_HandleReset(); - void UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p, - int request, int value, int index, int length, uint8_t* data); - void UsbHub_HandleData(XboxDeviceState* dev, USBPacket* p); - void UsbHub_HandleDestroy(); - // see USBPortOps struct for info - void UsbHub_Attach(USBPort* port1); - void UsbHub_Detach(USBPort* port1); - void UsbHub_ChildDetach(XboxDeviceState* child); - void UsbHub_Wakeup(USBPort* port1); - void UsbHub_Complete(USBPort* port, USBPacket* packet); - // reserve a usb port for this hub - int UsbHubClaimPort(XboxDeviceState* dev, int port); - // free the usb port used by this hub - void UsbHubReleasePort(XboxDeviceState* dev); - // retieve the name of the feature of the usb request - std::string GetFeatureName(int feature); - // destroy hub resources - void HubCleanUp(); -}; - -extern Hub* g_HubObjArray[4]; - -} diff --git a/modules/core/include/strikebox/hw/pci/nv2a.h b/modules/core/include/strikebox/hw/pci/nv2a.h index 67c56de..0c3dbb3 100644 --- a/modules/core/include/strikebox/hw/pci/nv2a.h +++ b/modules/core/include/strikebox/hw/pci/nv2a.h @@ -1,11 +1,6 @@ #pragma once -#include - -#include "../defs.h" #include "pci.h" -#include "../nv2a/defs.h" -#include "../nv2a/vga.h" #include "../basic/irq.h" namespace strikebox { @@ -13,133 +8,21 @@ namespace strikebox { class NV2ADevice : public PCIDevice { public: NV2ADevice(uint8_t *pSystemRAM, uint32_t systemRAMSize, IRQHandler& irqHandler); - virtual ~NV2ADevice(); // PCI Device functions void Init(); void Reset(); - + void PCIIORead(int barIndex, uint32_t port, uint32_t *value, uint8_t size) override; void PCIIOWrite(int barIndex, uint32_t port, uint32_t value, uint8_t size) override; void PCIMMIORead(int barIndex, uint32_t addr, uint32_t *value, uint8_t size) override; void PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint8_t size) override; private: - const NV2ABlockInfo* FindBlock(uint32_t addr); - - static void PMCRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PMCWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PBUSRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PBUSWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PFIFORead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PFIFOWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PRMARead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PRMAWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PVIDEORead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PVIDEOWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PTIMERRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PTIMERWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PCOUNTERRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PCOUNTERWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PVPERead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PVPEWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PTVRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PTVWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PRMFBRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PRMFBWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PRMVIORead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PRMVIOWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PFBRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PFBWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PSTRAPSRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PSTRAPSWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PGRAPHRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PGRAPHWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PCRTCRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PCRTCWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PRMCIORead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PRMCIOWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PRAMDACRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PRAMDACWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PRMDIORead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PRMDIOWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void PRAMINRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void PRAMINWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - static void USERRead(NV2ADevice* pNV2A, uint32_t addr, uint32_t *value, uint8_t size); - static void USERWrite(NV2ADevice* pNV2A, uint32_t addr, uint32_t value, uint8_t size); - - uint32_t ramht_hash(uint32_t handle); - RAMHTEntry ramht_lookup(uint32_t handle); - - uint32_t ptimer_get_clock(); - - void pgraph_set_context_user(uint32_t value); - void pgraph_context_switch(unsigned int channel_id); - void pgraph_wait_fifo_access(); - void pgraph_method_log(unsigned int subchannel, unsigned int graphics_class, unsigned int method, uint32_t parameter); - void pgraph_method(unsigned int subchannel, unsigned int method, uint32_t parameter); - bool pgraph_color_write_enabled(); - bool pgraph_zeta_write_enabled(); - - unsigned int kelvin_map_stencil_op(uint32_t parameter); - unsigned int kelvin_map_polygon_mode(uint32_t parameter); - unsigned int kelvin_map_texgen(uint32_t parameter, unsigned int channel); - - void load_graphics_object(uint32_t instance_address, GraphicsObject *obj); - GraphicsObject* lookup_graphics_object(uint32_t instance_address); - - DMAObject nv_dma_load(uint32_t dma_obj_address); - void *nv_dma_map(uint32_t dma_obj_address, uint32_t *len); - - void pfifo_run_pusher(); - - static void PFIFO_Puller_Thread(NV2ADevice* pNV2a); - static void VBlankThread(NV2ADevice* pNV2A); - - void UpdateIRQ(); - uint8_t *m_pSystemRAM; uint32_t m_systemRAMSize; IRQHandler& m_irqHandler; - - uint8_t* m_pRAMIN = nullptr; - uint8_t* m_VRAM = nullptr; - NV2APRAMDAC m_PRAMDAC; - NV2APTIMER m_PTIMER; - NV2APVIDEO m_PVIDEO; - NV2APMC m_PMC; - NV2APCRTC m_PCRTC; - NV2APFIFO m_PFIFO; - NV2APFB m_PFB; - NV2APGRAPH m_PGRAPH; - NV2APRMCIO m_PRMCIO; - NV2AUSER m_User; - - VGACommonState m_VGAState; - - bool m_running; - std::vector m_MemoryRegions; - std::thread m_VblankThread; }; } diff --git a/modules/core/include/strikebox/hw/pci/nvapu.h b/modules/core/include/strikebox/hw/pci/nvapu.h index 55ab5a0..f5fa26e 100644 --- a/modules/core/include/strikebox/hw/pci/nvapu.h +++ b/modules/core/include/strikebox/hw/pci/nvapu.h @@ -1,85 +1,25 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's APU emulator. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * src->devices->APUDevice.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 Luke Usher -// * -// * All rights reserved -// * -// ****************************************************************** - #pragma once -#include - -#include "../defs.h" #include "pci.h" namespace strikebox { -#define APU_VP_BASE 0x20000 -#define APU_VP_SIZE 0x10000 - -#define APU_GP_BASE 0x30000 -#define APU_GP_SIZE 0x10000 - -#define APU_EP_BASE 0x50000 -#define APU_EP_SIZE 0x10000 +#define NVNET_ADDR 0xFEF00000 +#define NVNET_SIZE 0x00000400 class NVAPUDevice : public PCIDevice { public: - // constructor NVAPUDevice(); virtual ~NVAPUDevice(); // PCI Device functions void Init(); void Reset(); - + void PCIIORead(int barIndex, uint32_t port, uint32_t *value, uint8_t size) override; void PCIIOWrite(int barIndex, uint32_t port, uint32_t value, uint8_t size) override; void PCIMMIORead(int barIndex, uint32_t addr, uint32_t *value, uint8_t size) override; void PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint8_t size) override; - -private: - void GPRead(uint32_t address, uint32_t *value, uint8_t size); - void GPWrite(uint32_t address, uint32_t value, uint8_t size); - - void EPRead(uint32_t address, uint32_t *value, uint8_t size); - void EPWrite(uint32_t address, uint32_t value, uint8_t size); - - void VPRead(uint32_t address, uint32_t *value, uint8_t size); - void VPWrite(uint32_t address, uint32_t value, uint8_t size); }; } diff --git a/modules/core/include/strikebox/hw/pci/usb_pci.h b/modules/core/include/strikebox/hw/pci/usb_pci.h index 6c82278..ef02f47 100644 --- a/modules/core/include/strikebox/hw/pci/usb_pci.h +++ b/modules/core/include/strikebox/hw/pci/usb_pci.h @@ -1,209 +1,21 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->USBController->USBDevice.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - #pragma once -#include - -#include "virt86/virt86.hpp" - -#include "../defs.h" #include "pci.h" -#include "../ohci/ohci_common.h" namespace strikebox { -typedef enum USBDeviceFlags { - USB_DEV_FLAG_FULL_PATH, - USB_DEV_FLAG_IS_HOST, - USB_DEV_FLAG_MSOS_DESC_ENABLE, - USB_DEV_FLAG_MSOS_DESC_IN_USE, -} -USBDeviceFlags; -// Forward declare OHCI class for m_HostController pointer -class OHCI; - -/* Helper class which provides various functionality to both OHCI and usb device classes */ class USBPCIDevice : public PCIDevice { public: - // constructor USBPCIDevice(uint8_t irqn, virt86::VirtualProcessor& vp); virtual ~USBPCIDevice(); // PCI Device functions void Init(); void Reset(); - + void PCIMMIORead(int barIndex, uint32_t addr, uint32_t *value, uint8_t size) override; void PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint8_t size) override; - - - - // USBDevice-specific functions/variables - // pointer to the host controller this device refers to - OHCI* m_HostController; - // PCI path of this usb device - const char* m_PciPath; - // free usb ports on this device (hubs included) - std::vector m_FreePorts; - - // register a port with the HC - void USB_RegisterPort(USBPort* Port, int Index, int SpeedMask, USBPortOps* Ops); - // free a port with the HC - void USB_UnregisterPort(USBPort* Port); - // reset a usb port - void USB_PortReset(USBPort* Port); - // update device status during an attach - void USB_DeviceAttach(XboxDeviceState* dev); - // update device status during an detach - void USB_DeviceDetach(XboxDeviceState* dev); - // update port status when a device is attached - void USB_Attach(USBPort* Port); - // update port status when a device is detached - void USB_Detach(USBPort* Port); - // update port status when a device is detached - void USB_Wakeup(USBEndpoint* ep); - // reset a device - void USB_DeviceReset(XboxDeviceState* Dev); - // find the device connected to the supplied port and address - XboxDeviceState* USB_FindDevice(USBPort* Port, uint8_t Addr); - // find the requested endpoint in the supplied device - USBEndpoint* USB_GetEP(XboxDeviceState* Dev, int Pid, int Ep); - // setup a packet for transfer - void USB_PacketSetup(USBPacket* p, int Pid, USBEndpoint* Ep, unsigned int Stream, uint64_t Id, bool ShortNotOK, bool IntReq); - // check if the state of the packet is queued or async - bool USB_IsPacketInflight(USBPacket* p); - // append the user buffer to the packet - void USB_PacketAddBuffer(USBPacket* p, void* ptr, size_t len); - // transfer and process the packet - void USB_HandlePacket(XboxDeviceState* dev, USBPacket* p); - // check if the packet has the expected state and assert if not - void USB_PacketCheckState(USBPacket* p, USBPacketState expected); - // process the packet - void USB_ProcessOne(USBPacket* p); - // xhci only? - void USB_DoParameter(XboxDeviceState* s, USBPacket* p); - // process a setup token - void USB_DoTokenSetup(XboxDeviceState* s, USBPacket* p); - // process an input token - void DoTokenIn(XboxDeviceState* s, USBPacket* p); - // process an output token - void DoTokenOut(XboxDeviceState* s, USBPacket* p); - // copy the packet data to the buffer pointed to by ptr - void USB_PacketCopy(USBPacket* p, void* ptr, size_t bytes); - // Cancel an active packet. The packed must have been deferred by - // returning USB_RET_ASYNC from handle_packet, and not yet completed - void USB_CancelPacket(USBPacket* p); - // queue a packet to an endpoint - void USB_QueueOne(USBPacket* p); - // call usb class init function - int USB_DeviceInit(XboxDeviceState* dev); - // call usb class find_device function - XboxDeviceState* USB_DeviceFindDevice(XboxDeviceState* Dev, uint8_t Addr); - // call usb class cancel_packet function - void USB_DeviceCancelPacket(XboxDeviceState* dev, USBPacket* p); - // call usb class handle_destroy function - void USB_DeviceHandleDestroy(XboxDeviceState* dev); - // call usb class handle_attach function - void USB_DeviceHandleAttach(XboxDeviceState* dev); - // call usb class handle_reset function - void USB_DeviceHandleReset(XboxDeviceState* dev); - // call usb class handle_control function - void USB_DeviceHandleControl(XboxDeviceState* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data); - // call usb class handle_data function - void USB_DeviceHandleData(XboxDeviceState* dev, USBPacket* p); - // call usb class set_interface function - void USB_DeviceSetInterface(XboxDeviceState* dev, int iface, int alt_old, int alt_new); - // call usb class flush_ep_queue function - void USB_DeviceFlushEPqueue(XboxDeviceState* dev, USBEndpoint* ep); - // call usb class ep_stopped function - void USB_DeviceEPstopped(XboxDeviceState* Dev, USBEndpoint* Ep); - // set the type of the endpoint - void USB_EPsetType(XboxDeviceState* dev, int pid, int ep, uint8_t type); - // set the interface number of the endpoint - void USB_EPsetIfnum(XboxDeviceState* dev, int pid, int ep, uint8_t ifnum); - // set the maximum packet size parameter of the endpoint - void USB_EPsetMaxPacketSize(XboxDeviceState* dev, int pid, int ep, uint16_t raw); - // assign port numbers (also for hubs) - void USB_PortLocation(USBPort* downstream, USBPort* upstream, int portnr); - // initialize the endpoints of this peripheral - void USB_EpInit(XboxDeviceState* dev); - // reset all endpoints of this peripheral - void USB_EpReset(XboxDeviceState* dev); - // create a serial number for the device - void USB_CreateSerial(XboxDeviceState* dev, std::string&& str); - // start descriptors initialization - void USBDesc_Init(XboxDeviceState* dev); - // get device descriptor - const USBDesc* USBDesc_GetUsbDeviceDesc(XboxDeviceState* dev); - // set the descriptors to use for this device - void USBDesc_SetDefaults(XboxDeviceState* dev); - // set the configuration to use - int USBDesc_SetConfig(XboxDeviceState* dev, int value); - // set the interface to use - int USBDesc_SetInterface(XboxDeviceState* dev, int index, int value); - // find the interface to use - const USBDescIface* USBDesc_FindInterface(XboxDeviceState* dev, int nif, int alt); - // setup endpoints and their descriptors - void USBDesc_EpInit(XboxDeviceState* dev); - // handle standard control request - int USBDesc_HandleControl(XboxDeviceState *dev, USBPacket *p, int request, int value, int index, int length, uint8_t *data); - // handle standard GetDescriptor() request - int USBDesc_HandleStandardGetDescriptor(XboxDeviceState* dev, USBPacket* p, int value, uint8_t* dest, size_t len); - // return the binary rapresentation of a device descriptor - int USB_ReadDeviceDesc(const USBDescID* id, const USBDescDevice* dev, uint8_t* dest, size_t len); - // return the binary rapresentation of configuration descriptors - int USB_ReadConfigurationDesc(const USBDescConfig* conf, int flags, uint8_t* dest, size_t len); - // return the binary rapresentation of interface descriptors - int USB_ReadInterfaceDesc(const USBDescIface* iface, int flags, uint8_t* dest, size_t len); - // return the binary rapresentation of class-specific descriptors - size_t USB_ReadOtherDesc(const USBDescOther* desc, uint8_t* dest, size_t len); - // return the binary rapresentation of endpoint descriptors - int USB_ReadEndpointDesc(const USBDescEndpoint* ep, int flags, uint8_t* dest, size_t len); - // return the binary rapresentation of string descriptors - int USB_ReadStringDesc(XboxDeviceState* dev, int index, uint8_t* dest, size_t len); - // set a string in the string descriptor with the supplied index - void USBDesc_SetString(XboxDeviceState* dev, int index, std::string&& str); - // get a string in the string descriptor with the supplied index - const char* USBDesc_GetString(XboxDeviceState* dev, int index); private: uint8_t m_irqn; virt86::VirtualProcessor& m_vp; diff --git a/modules/core/include/strikebox/hw/xid/xid_gamepad.h b/modules/core/include/strikebox/hw/xid/xid_gamepad.h deleted file mode 100644 index e25c453..0000000 --- a/modules/core/include/strikebox/hw/xid/xid_gamepad.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->usb->XidGamepad.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#include "../ohci/ohci_hub.h" - -#pragma once - -namespace strikebox { - -struct USBXIDState; // forward declare - -/* Class which implements an xbox gamepad */ -class XidGamepad { -public: - // initialize this peripheral - int Init(int port); - // destroy gamepad resources - void XidCleanUp(); - - -private: - // usb device this gamepad is attached to through the hub - USBPCIDevice* m_UsbDev = nullptr; - // gamepad state - USBXIDState* m_XidState = nullptr; - // gamepad class functions - USBDeviceClass* m_pPeripheralFuncStruct = nullptr; - // xbox port this gamepad is attached to - int m_Port = 0; - - // initialize various member variables/functions - XboxDeviceState* ClassInitFn(); - // reserve a usb port for this gamepad - int UsbXidClaimPort(XboxDeviceState* dev, int port); - // free the usb port used by this gamepad - void UsbXidReleasePort(XboxDeviceState* dev); - // see USBDeviceClass for comments about these functions - int UsbXid_Initfn(XboxDeviceState* dev); - void UsbXid_HandleDestroy(); - void UsbXid_Attach(XboxDeviceState* dev); - void UsbXid_HandleReset(); - void UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p, - int request, int value, int index, int length, uint8_t* data); - void UsbXid_HandleData(XboxDeviceState* dev, USBPacket* p); - // this should update the vibration strength of the real controller this gamepad represents. - // It doesn't do anything at the moment - void UpdateForceFeedback(); -}; - -extern XidGamepad* g_XidControllerObjArray[4]; - -} diff --git a/modules/core/include/strikebox/iovec.h b/modules/core/include/strikebox/iovec.h deleted file mode 100644 index 36a97ac..0000000 --- a/modules/core/include/strikebox/iovec.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->Cxbx.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2002-2003 Aaron Robinson -// * -// * All rights reserved -// * -// ****************************************************************** -#pragma once - -#include -#include - -namespace strikebox { - -/* This is a linux struct for vectored I/O. See readv() and writev() */ -struct IoVec { - void* Iov_Base; // Starting address - size_t Iov_Len; // Number of bytes to transfer -}; - -struct IOVector { - IoVec* IoVecStruct; - int IoVecNumber; // number of I/O buffers supplied - int AllocNumber; // number of IoVec structs currently allocated - size_t Size; // total size of all I/O buffers supplied -}; - -void IoVecReset(IOVector* qiov); -void IoVecAdd(IOVector* qiov, void* base, size_t len); -size_t IoVecTobuffer(const IoVec* iov, const unsigned int iov_cnt, size_t offset, void *buf, size_t bytes); -size_t IoVecFromBuffer(const IoVec* iov, unsigned int iov_cnt, size_t offset, void* buf, size_t bytes); - -#define GET_WORD_LOW(value) (uint8_t)((value) & 0xFF) -#define GET_WORD_HIGH(value) (uint8_t)(((value) >> 8) & 0xFF) - -} diff --git a/modules/core/include/strikebox/queue.h b/modules/core/include/strikebox/queue.h deleted file mode 100644 index 434db3b..0000000 --- a/modules/core/include/strikebox/queue.h +++ /dev/null @@ -1,414 +0,0 @@ -/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */ - -/* - * QEMU version: Copy from netbsd, removed debug code, removed some of - * the implementations. Left in singly-linked lists, lists, simple - * queues, and tail queues. - */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef QEMU_SYS_QUEUE_H_ -#define QEMU_SYS_QUEUE_H_ - -/* - * This file defines four types of data structures: singly-linked lists, - * lists, simple queues, and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The - * elements are singly linked for minimum space and pointer manipulation - * overhead at the expense of O(n) removal for arbitrary elements. New - * elements can be added to the list after an existing element or at the - * head of the list. Elements being removed from the head of the list - * should use the explicit macro for this purpose for optimum - * efficiency. A singly-linked list may only be traversed in the forward - * direction. Singly-linked lists are ideal for applications with large - * datasets and few or no removals or for implementing a LIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A simple queue is headed by a pair of pointers, one the head of the - * list and the other to the tail of the list. The elements are singly - * linked to save space, so elements can only be removed from the - * head of the list. New elements can be added to the list after - * an existing element, at the head of the list, or at the end of the - * list. A simple queue may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -// #include "qemu/atomic.h" /* for smp_wmb() */ - -/* - * List definitions. - */ -#define QLIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define QLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define QLIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ -#define QLIST_INIT(head) do { \ - (head)->lh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (/*CONSTCOND*/0) - -#define QLIST_INSERT_HEAD_RCU(head, elm, field) do { \ - (elm)->field.le_prev = &(head)->lh_first; \ - (elm)->field.le_next = (head)->lh_first; \ - smp_wmb(); /* fill elm before linking it */ \ - if ((head)->lh_first != NULL) { \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next; \ - } \ - (head)->lh_first = (elm); \ - smp_wmb(); \ -} while (/* CONSTCOND*/0) - -#define QLIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ -} while (/*CONSTCOND*/0) - -#define QLIST_FOREACH(var, head, field) \ - for ((var) = ((head)->lh_first); \ - (var); \ - (var) = ((var)->field.le_next)) - -#define QLIST_FOREACH_SAFE(var, head, field, next_var) \ - for ((var) = ((head)->lh_first); \ - (var) && ((next_var) = ((var)->field.le_next), 1); \ - (var) = (next_var)) - -/* - * List access methods. - */ -#define QLIST_EMPTY(head) ((head)->lh_first == NULL) -#define QLIST_FIRST(head) ((head)->lh_first) -#define QLIST_NEXT(elm, field) ((elm)->field.le_next) - - -/* - * Singly-linked List definitions. - */ -#define QSLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define QSLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define QSLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define QSLIST_INIT(head) do { \ - (head)->slh_first = NULL; \ -} while (/*CONSTCOND*/0) - -#define QSLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.sle_next = (head)->slh_first; \ - (head)->slh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_REMOVE_HEAD(head, field) do { \ - (head)->slh_first = (head)->slh_first->field.sle_next; \ -} while (/*CONSTCOND*/0) - -#define QSLIST_REMOVE_AFTER(slistelm, field) do { \ - (slistelm)->field.sle_next = \ - QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \ -} while (/*CONSTCOND*/0) - -#define QSLIST_FOREACH(var, head, field) \ - for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) - -#define QSLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = QSLIST_FIRST((head)); \ - (var) && ((tvar) = QSLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -/* - * Singly-linked List access methods. - */ -#define QSLIST_EMPTY(head) ((head)->slh_first == NULL) -#define QSLIST_FIRST(head) ((head)->slh_first) -#define QSLIST_NEXT(elm, field) ((elm)->field.sle_next) - - -/* - * Simple queue definitions. - */ -#define QSIMPLEQ_HEAD(name, type) \ -struct name { \ - struct type *sqh_first; /* first element */ \ - struct type **sqh_last; /* addr of last next element */ \ -} - -#define QSIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - -#define QSIMPLEQ_ENTRY(type) \ -struct { \ - struct type *sqe_next; /* next element */ \ -} - -/* - * Simple queue functions. - */ -#define QSIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (head)->sqh_first = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.sqe_next = NULL; \ - *(head)->sqh_last = (elm); \ - (head)->sqh_last = &(elm)->field.sqe_next; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_REMOVE_HEAD(head, field) do { \ - if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL)\ - (head)->sqh_last = &(head)->sqh_first; \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_REMOVE(head, elm, type, field) do { \ - if ((head)->sqh_first == (elm)) { \ - QSIMPLEQ_REMOVE_HEAD((head), field); \ - } else { \ - struct type *curelm = (head)->sqh_first; \ - while (curelm->field.sqe_next != (elm)) \ - curelm = curelm->field.sqe_next; \ - if ((curelm->field.sqe_next = \ - curelm->field.sqe_next->field.sqe_next) == NULL) \ - (head)->sqh_last = &(curelm)->field.sqe_next; \ - } \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_FOREACH(var, head, field) \ - for ((var) = ((head)->sqh_first); \ - (var); \ - (var) = ((var)->field.sqe_next)) - -#define QSIMPLEQ_FOREACH_SAFE(var, head, field, next) \ - for ((var) = ((head)->sqh_first); \ - (var) && ((next = ((var)->field.sqe_next)), 1); \ - (var) = (next)) - -#define QSIMPLEQ_CONCAT(head1, head2) do { \ - if (!QSIMPLEQ_EMPTY((head2))) { \ - *(head1)->sqh_last = (head2)->sqh_first; \ - (head1)->sqh_last = (head2)->sqh_last; \ - QSIMPLEQ_INIT((head2)); \ - } \ -} while (/*CONSTCOND*/0) - -#define QSIMPLEQ_LAST(head, type, field) \ - (QSIMPLEQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *)(void *) \ - ((char *)((head)->sqh_last) - offsetof(struct type, field)))) - -/* - * Simple queue access methods. - */ -#define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) -#define QSIMPLEQ_FIRST(head) ((head)->sqh_first) -#define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) - - -/* - * Tail queue definitions. - */ -#define Q_TAILQ_HEAD(name, type, qual) \ -struct name { \ - qual type *tqh_first; /* first element */ \ - qual type *qual *tqh_last; /* addr of last next element */ \ -} -#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type,) - -#define QTAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define Q_TAILQ_ENTRY(type, qual) \ -struct { \ - qual type *tqe_next; /* next element */ \ - qual type *qual *tqe_prev; /* address of previous next element */\ -} -#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type,) - -/* - * Tail queue functions. - */ -#define QTAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -} while (/*CONSTCOND*/0) - -#define QTAILQ_FOREACH(var, head, field) \ - for ((var) = ((head)->tqh_first); \ - (var); \ - (var) = ((var)->field.tqe_next)) - -#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \ - for ((var) = ((head)->tqh_first); \ - (var) && ((next_var) = ((var)->field.tqe_next), 1); \ - (var) = (next_var)) - -#define QTAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ - (var); \ - (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) - -/* - * Tail queue access methods. - */ -#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL) -#define QTAILQ_FIRST(head) ((head)->tqh_first) -#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define QTAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) -#define QTAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#endif /* !QEMU_SYS_QUEUE_H_ */ diff --git a/modules/core/include/strikebox/xbox.h b/modules/core/include/strikebox/xbox.h index 75b2c8a..9ff32f2 100644 --- a/modules/core/include/strikebox/xbox.h +++ b/modules/core/include/strikebox/xbox.h @@ -12,7 +12,6 @@ #include "virt86/virt86.hpp" -#include "strikebox/gdbserver.h" #include "strikebox/log.h" #include "strikebox/mem.h" #include "strikebox/util.h" @@ -167,9 +166,6 @@ protected: uint32_t m_kExp_XboxKrnlVersion = 0x00000000; bool LocateKernelData(); - - // ----- Debugger --------------------------------------------------------- - GdbServer *m_gdb; }; } diff --git a/modules/core/src/common/strikebox/core.cpp b/modules/core/src/common/strikebox/core.cpp index 925bea9..2358367 100644 --- a/modules/core/src/common/strikebox/core.cpp +++ b/modules/core/src/common/strikebox/core.cpp @@ -4,9 +4,9 @@ namespace strikebox { -#define VXN_VERSION_MAJOR 0 -#define VXN_VERSION_MINOR 0 -#define VXN_VERSION_PATCH 1 +#define SBX_VERSION_MAJOR 0 +#define SBX_VERSION_MINOR 0 +#define SBX_VERSION_PATCH 1 #define STRFY(x) #x // TODO: add other things: @@ -18,8 +18,8 @@ namespace strikebox { #define MAKE_VERSION_ID(major, minor, patch) ((((uint64_t)major) << 48ull) | (((uint64_t)minor) << 32ull) | ((uint64_t)patch)) static const StrikeBoxInfo g_StrikeBoxInfo = { - MAKE_VERSION_STRING(VXN_VERSION_MAJOR, VXN_VERSION_MINOR, VXN_VERSION_PATCH), - MAKE_VERSION_ID(VXN_VERSION_MAJOR, VXN_VERSION_MINOR, VXN_VERSION_PATCH) + MAKE_VERSION_STRING(SBX_VERSION_MAJOR, SBX_VERSION_MINOR, SBX_VERSION_PATCH), + MAKE_VERSION_ID(SBX_VERSION_MAJOR, SBX_VERSION_MINOR, SBX_VERSION_PATCH) }; const struct StrikeBoxInfo * GetStrikeBoxInfo() { diff --git a/modules/core/src/common/strikebox/cxbxtimer.cpp b/modules/core/src/common/strikebox/cxbxtimer.cpp deleted file mode 100644 index 4511b4d..0000000 --- a/modules/core/src/common/strikebox/cxbxtimer.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->CxbxKrnl->Timer.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#include -#include -#include -#include "strikebox/cxbxtimer.h" - -namespace strikebox { - -#define CLOCK_REALTIME 0 -#define CLOCK_VIRTUALTIME 1 -#define SCALE_S 1000000000ULL -#define SCALE_MS 1000000ULL -#define SCALE_US 1000ULL -#define SCALE_NS 1ULL - - -// Vector storing all the timers created -static std::vector TimerList; - - -// Returns the current time of the timer -uint64_t GetTime_NS(TimerObject* Timer) { - using namespace std::chrono; - uint64_t Ret = high_resolution_clock::now().time_since_epoch().count(); - return Timer->Type == CLOCK_REALTIME ? Ret : Ret / Timer->SlowdownFactor; -} - -// Calculates the next expire time of the timer -static inline uint64_t GetNextExpireTime(TimerObject* Timer) { - return GetTime_NS(Timer) + Timer->ExpireTime_MS.load(); -} - -// Deallocates the memory of the timer -void Timer_Destroy(TimerObject* Timer) { - unsigned int index; - for (unsigned int i = 0; i < TimerList.size(); i++) { - if (Timer == TimerList[i]) { - index = i; - } - } - - delete Timer; - TimerList.erase(TimerList.begin() + index); -} - -// Thread that runs the timer -void ClockThread(TimerObject* Timer) { - uint64_t NewExpireTime = GetNextExpireTime(Timer); - - while (true) { - if (GetTime_NS(Timer) > NewExpireTime) { - if (Timer->Exit.load()) { - Timer_Destroy(Timer); - return; - } - Timer->Callback(Timer->Opaque); - if (Timer->Exit.load()) { - Timer_Destroy(Timer); - return; - } - NewExpireTime = GetNextExpireTime(Timer); - } - } -} - -// Changes the expire time of a timer -void Timer_ChangeExpireTime(TimerObject* Timer, uint64_t Expire_ms) { - Timer->ExpireTime_MS.store(Expire_ms); -} - -// Destroys the timer -void Timer_Exit(TimerObject* Timer) { - Timer->Exit.store(true); -} - -// Allocates the memory for the timer object -TimerObject* Timer_Create(pTimerCB Callback, void* Arg, unsigned int Factor) { - TimerObject* pTimer = new TimerObject; - pTimer->Type = Factor <= 1 ? CLOCK_REALTIME : CLOCK_VIRTUALTIME; - pTimer->Callback = Callback; - pTimer->ExpireTime_MS.store(0); - pTimer->Exit.store(false); - pTimer->Opaque = Arg; - pTimer->SlowdownFactor = Factor < 1 ? 1 : Factor; - TimerList.emplace_back(pTimer); - - return pTimer; -} - -// Starts the timer -// Expire_MS must be expressed in NS -void Timer_Start(TimerObject* Timer, uint64_t Expire_MS) { - Timer->ExpireTime_MS.store(Expire_MS); - std::thread(ClockThread, Timer).detach(); -} - -// Retrives the frequency of the high resolution clock of the host -void Timer_Init() { -} - -} diff --git a/modules/core/src/common/strikebox/gdbserver.cpp b/modules/core/src/common/strikebox/gdbserver.cpp deleted file mode 100644 index e9fd4c7..0000000 --- a/modules/core/src/common/strikebox/gdbserver.cpp +++ /dev/null @@ -1,1235 +0,0 @@ -/* - * Copyright (C) 2017 Matt Borgerson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "strikebox/gdbserver.h" - -namespace strikebox { - -using namespace virt86; - -#ifdef _WIN32 - int inet_aton(const char *cp, struct in_addr *inp) { return InetPton(AF_INET, cp, inp); } - int close(SOCKET socket) { return closesocket(socket); } - -# define printNetErrorMessage do { \ - int errCode = WSAGetLastError(); \ - LPSTR errString = NULL; \ - int size = FormatMessage( \ - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, \ - 0, \ - errCode, \ - 0, \ - (LPSTR)&errString, \ - 0, \ - 0); \ - fprintf(stderr, "Error: %s\n", errString); \ - LocalFree(errString); \ - } while (0); - -# define initNetwork do { \ - WSADATA wsaData; \ - int err = WSAStartup(MAKEWORD(2, 2), &wsaData); \ - if (err != 0) { \ - printNetErrorMessage; \ - return 1; \ - } \ - } while (0); - -# define shutdownNetwork do { \ - int err = WSACleanup(); \ - if (err != 0) { \ - printNetErrorMessage; \ - } \ - } while (0); - -#else -# define printNetErrorMessage fprintf(stderr, "Error: %s\n", strerror(errno)) -# define initNetwork -# define shutdownNetwork -#endif - -#define DEBUG 0 - -#if DEBUG -#define DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) -#else -#define DEBUG_PRINT(...) -#endif -#define ASSERT assert - -/*! - * Constructor - */ -GdbServer::GdbServer(VirtualProcessor& vp, const char *bind_host, int bind_port) -: m_vp(vp), m_bind_host(bind_host), m_bind_port(bind_port) -{ -} - -/*! - * Destructor - */ -GdbServer::~GdbServer() -{ -} - -/*! - * Initialize - */ -int GdbServer::Initialize() -{ - int status; - int val; - - initNetwork; - - /* Fill local address struct */ - m_bind_addr.sin_family = AF_INET; - m_bind_addr.sin_port = htons(m_bind_port); - if (!inet_aton(m_bind_host, &(m_bind_addr.sin_addr))) { - fprintf(stderr, "Error: Invalid bind host address format\n"); - return 1; - } - - /* Create the socket */ - m_sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (m_sockfd < 0) { - printNetErrorMessage; - return 1; - } - - /* Allow re-using a local address */ - val = 1; - status = setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - if (status) { - printNetErrorMessage; - close(m_sockfd); - return 1; - } - - /* No delays */ - val = 1; - status = setsockopt(m_sockfd, IPPROTO_TCP, TCP_NODELAY, (const char *)&val, sizeof(val)); - if (status) { - printNetErrorMessage; - close(m_sockfd); - return 1; - } - - /* Bind the socket to an address/port */ - status = bind(m_sockfd, (struct sockaddr *)&m_bind_addr, sizeof(m_bind_addr)); - if (status) { - printNetErrorMessage; - close(m_sockfd); - return 1; - } - - /* Begin waiting for connections */ - status = listen(m_sockfd, 10); - if (status) { - printNetErrorMessage; - close(m_sockfd); - return 1; - } - - return 0; -} - -/*! - * Close active connections - */ -int GdbServer::Shutdown() -{ - printf("Stopping server\n"); - if (m_peer_sockfd >= 0) { - close(m_peer_sockfd); - } - if (m_sockfd >= 0) { - close(m_sockfd); - } - shutdownNetwork; - return 0; -} - -/*! - * Start listening for connections - */ -int GdbServer::WaitForConnection() -{ - SOCKET_T status; - int val; - - /* Wait for an incoming connection */ - fprintf(stderr, "Waiting for new connection at %s:%d\n", - inet_ntoa(m_bind_addr.sin_addr), - ntohs(m_bind_addr.sin_port)); - m_peer_addr_len = sizeof(m_peer_addr); - status = accept(m_sockfd, (struct sockaddr *)&m_peer_addr, &m_peer_addr_len); - if (status < 0) { - printNetErrorMessage; - return 1; - } - - /* New connection received! */ - assert(m_peer_addr_len >= sizeof(m_peer_addr)); - assert(m_peer_addr.sin_family == AF_INET); - fprintf(stderr, "New connection from %s:%d\n", - inet_ntoa(m_peer_addr.sin_addr), - ntohs(m_peer_addr.sin_port)); - m_peer_sockfd = status; - - val = 1; - status = setsockopt(m_peer_sockfd, IPPROTO_TCP, TCP_NODELAY, (const char *)&val, sizeof(val)); - if (status) { - printNetErrorMessage; - close(m_peer_sockfd); - close(m_sockfd); - return 1; - } - - return 0; -} - -/*! - * Main handler for a client, called when connection is made - */ -int GdbServer::Debug(int signal) -{ - int result; - - if (m_peer_sockfd < 0) { - // No client! - return 1; - } - - memset(&m_dbg_state.registers, 0, sizeof(m_dbg_state.registers)); - - m_dbg_state.signum = signal; - - // Load Registers - { - Reg regs[] = { - Reg::EAX, Reg::ECX, Reg::EDX, Reg::EBX, - Reg::ESP, Reg::EBP, Reg::ESI, Reg::EDI, - Reg::EIP, Reg::EFLAGS, - Reg::CS, Reg::SS, Reg::DS, Reg::ES, Reg::FS, Reg::GS - }; - RegValue vals[ARRAY_SIZE(regs)]; - - m_vp.RegRead(regs, vals, ARRAY_SIZE(regs)); - - m_dbg_state.registers[DBG_CPU_I386_REG_EAX] = vals[0].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_ECX] = vals[1].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_EDX] = vals[2].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_EBX] = vals[3].u32; - - m_dbg_state.registers[DBG_CPU_I386_REG_ESP] = vals[4].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_EBP] = vals[5].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_ESI] = vals[6].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_EDI] = vals[7].u32; - - m_dbg_state.registers[DBG_CPU_I386_REG_PC] = vals[8].u32; - m_dbg_state.registers[DBG_CPU_I386_REG_PS] = vals[9].u32; - - m_dbg_state.registers[DBG_CPU_I386_REG_CS] = vals[10].segment.selector; - m_dbg_state.registers[DBG_CPU_I386_REG_SS] = vals[11].segment.selector; - m_dbg_state.registers[DBG_CPU_I386_REG_DS] = vals[12].segment.selector; - m_dbg_state.registers[DBG_CPU_I386_REG_ES] = vals[13].segment.selector; - m_dbg_state.registers[DBG_CPU_I386_REG_FS] = vals[14].segment.selector; - m_dbg_state.registers[DBG_CPU_I386_REG_GS] = vals[15].segment.selector; - } - - // If interrupt was caused by a soft breakpoint (int3 = CCh), EIP will point - // to the instruction *after* the int3 instruction, which is probably in - // the middle of the instruction that we are breaking on. In this case, roll - // EIP back by 1. GDB client will replace the soft breakpoint with correct - // instruction byte before continuing execution. - if (signal == 3) { - m_dbg_state.registers[DBG_CPU_I386_REG_PC] -= 1; - } - - // Begin debugging episode - result = dbg_main(); - if (result != 0) { - return result; - } - -#if 1 - { - // Restore Registers - Reg regs[] = { - Reg::EAX, Reg::ECX, Reg::EDX, Reg::EBX, - Reg::ESP, Reg::EBP, Reg::ESI, Reg::EDI, - Reg::EIP, Reg::EFLAGS - }; - RegValue vals[] = { - m_dbg_state.registers[DBG_CPU_I386_REG_EAX], - m_dbg_state.registers[DBG_CPU_I386_REG_ECX], - m_dbg_state.registers[DBG_CPU_I386_REG_EDX], - m_dbg_state.registers[DBG_CPU_I386_REG_EBX], - - m_dbg_state.registers[DBG_CPU_I386_REG_ESP], - m_dbg_state.registers[DBG_CPU_I386_REG_EBP], - m_dbg_state.registers[DBG_CPU_I386_REG_ESI], - m_dbg_state.registers[DBG_CPU_I386_REG_EDI], - - m_dbg_state.registers[DBG_CPU_I386_REG_PC], - m_dbg_state.registers[DBG_CPU_I386_REG_PS] - }; - - m_vp.RegWrite(regs, vals, ARRAY_SIZE(regs)); - } -#endif - - return 0; -} - -/*! - * Receive a byte from the client - */ -int GdbServer::dbg_sys_getc(void) -{ - char buf; - ssize_t bytes_received; - - if (m_peer_sockfd < 0) { - return EOF; - } - - bytes_received = recv(m_peer_sockfd, &buf, sizeof(buf), 0); - - if (bytes_received > 0) { - /* Success */ - return buf; - } else if (bytes_received == 0) { - /* Peer has shutdown */ - fprintf(stderr, "Client disconnected\n"); - return EOF; - } else { - /* Error! */ - fprintf(stderr, "Error receiving data from client!\n"); - return EOF; - } -} - -/*! - * Send a byte to the client - */ -int GdbServer::dbg_sys_putchar(int ch) -{ - char buf = (char)ch; - ssize_t bytes_sent; - - if (m_peer_sockfd < 0) { - return EOF; - } - - bytes_sent = send(m_peer_sockfd, &buf, sizeof(buf), 0); - - if (bytes_sent != sizeof(buf)) { - fprintf(stderr, "Error sending data to client!\n"); - return EOF; - } - - return 0; -} - -/*! - * Read a byte from system memory - */ -int GdbServer::dbg_sys_mem_readb(address addr, char *val) -{ - m_vp.LMemRead(addr, 1, val); - return 0; -} - -/*! - * Write a byte to system memory - */ -int GdbServer::dbg_sys_mem_writeb(address addr, char val) -{ - m_vp.LMemWrite(addr, 1, &val); - return 0; -} - -/*! - * Allow CPU to continue execution - */ -int GdbServer::dbg_sys_continue() -{ - m_dbg_state.registers[DBG_CPU_I386_REG_PS] &= ~(1<<8); - return 0; -} - -/*! - * Single step CPU execution - */ -int GdbServer::dbg_sys_step() -{ - m_dbg_state.registers[DBG_CPU_I386_REG_PS] |= 1<<8; - return 0; -} - -/* - * Get integer value for a string representation. - * - * If the string starts with + or -, it will be signed accordingly. - * - * If base == 0, the base will be determined: - * base 16 if the string starts with 0x or 0X, - * base 10 otherwise - * - * If endptr is specified, it will point to the last non-digit in the - * string. If there are no digits in the string, it will be set to NULL. - */ -int GdbServer::dbg_strtol(const char *str, size_t len, int base, const char **endptr) -{ - size_t pos; - int sign, tmp, value, valid; - - value = 0; - pos = 0; - sign = 1; - valid = 0; - - if (endptr) { - *endptr = NULL; - } - - if (len < 1) { - return 0; - } - - /* Detect negative numbers */ - if (str[pos] == '-') { - sign = -1; - pos += 1; - } else if (str[pos] == '+') { - sign = 1; - pos += 1; - } - - /* Detect '0x' hex prefix */ - if ((pos + 2 < len) && (str[pos] == '0') && - ((str[pos+1] == 'x') || (str[pos+1] == 'X'))) { - base = 16; - pos += 2; - } - - if (base == 0) { - base = 10; - } - - for (; (pos < len) && (str[pos] != '\x00'); pos++) { - tmp = dbg_get_val(str[pos], base); - if (tmp == EOF) { - break; - } - - value = value*base + tmp; - valid = 1; /* At least one digit is valid */ - } - - if (!valid) { - return 0; - } - - if (endptr) { - *endptr = str+pos; - } - - value *= sign; - - return value; -} - -/* - * Get the corresponding ASCII hex digit character for a value. - */ -char GdbServer::dbg_get_digit(int val) -{ - const char digits[] = "0123456789abcdef"; - - if ((val >= 0) && (val <= 0xf)) { - return digits[val]; - } else { - return EOF; - } -} - -/* - * Get the corresponding value for a ASCII digit character. - * - * Supports bases 2-16. - */ -int GdbServer::dbg_get_val(char digit, int base) -{ - int value; - - if ((digit >= '0') && (digit <= '9')) { - value = digit-'0'; - } else if ((digit >= 'a') && (digit <= 'f')) { - value = digit-'a'+0xa; - } else if ((digit >= 'A') && (digit <= 'F')) { - value = digit-'A'+0xa; - } else { - return EOF; - } - - return (value < base) ? value : EOF; -} - -/* - * Determine if this is a printable ASCII character. - */ -int GdbServer::dbg_is_printable_char(char ch) -{ - return (ch >= 0x20 && ch <= 0x7e); -} - -/*! - * Receive a packet acknowledgment - * - * Returns: - * 0 if an ACK (+) was received - * 1 if a NACK (-) was received - * EOF otherwise - */ -int GdbServer::dbg_recv_ack(void) -{ - int response; - - /* Wait for packet ack */ - switch (response = dbg_sys_getc()) { - case '+': - /* Packet acknowledged */ - return 0; - case '-': - /* Packet negative acknowledged */ - return 1; - case EOF: - /* Failed to recieve data from client */ - return EOF; - default: - /* Bad response! */ - DEBUG_PRINT("received bad packet response: 0x%2x\n", response); - return EOF; - } -} - -/*! - * Calculate 8-bit checksum of a buffer. - * - * Returns: - * 8-bit checksum. - */ -int GdbServer::dbg_checksum(const char *buf, size_t len) -{ - unsigned char csum; - - csum = 0; - - while (len--) { - csum += *buf++; - } - - return csum; -} - -/*! - * Transmits a packet of data. - * Packets are of the form: $# - * - * Returns: - * 0 if the packet was transmitted and acknowledged - * 1 if the packet was transmitted but not acknowledged - * EOF otherwise - */ -int GdbServer::dbg_send_packet(const char *pkt_data, size_t pkt_len) -{ - char buf[3]; - char csum; - - /* Send packet start */ - if (dbg_sys_putchar('$') == EOF) { - return EOF; - } - -#if DEBUG - { - size_t p; - DEBUG_PRINT("-> "); - for (p = 0; p < pkt_len; p++) { - if (dbg_is_printable_char(pkt_data[p])) { - DEBUG_PRINT("%c", pkt_data[p]); - } else { - DEBUG_PRINT("\\x%02x", pkt_data[p]&0xff); - } - } - DEBUG_PRINT("\n"); - } -#endif - - /* Send packet data */ - if (dbg_write(pkt_data, pkt_len) == EOF) { - return EOF; - } - - /* Send the checksum */ - buf[0] = '#'; - csum = dbg_checksum(pkt_data, pkt_len); - if ((dbg_enc_hex(buf+1, sizeof(buf)-1, &csum, 1) == EOF) || - (dbg_write(buf, sizeof(buf)) == EOF)) { - return EOF; - } - - return dbg_recv_ack(); -} - -/*! - * Receives a packet of data, assuming a 7-bit clean connection. - * - * Returns: - * 0 if the packet was received - * EOF otherwise - */ -int GdbServer::dbg_recv_packet(char *pkt_buf, size_t pkt_buf_len, size_t *pkt_len) -{ - int data; - char expected_csum, actual_csum; - char buf[2]; - - /* Wait for packet start */ - actual_csum = 0; - - while (1) { - data = dbg_sys_getc(); - if (data == '$') { - /* Detected start of packet. */ - break; - } else if (data == EOF) { - return EOF; - } - } - - /* Read until checksum */ - *pkt_len = 0; - while (1) { - data = dbg_sys_getc(); - - if (data == EOF) { - /* Error receiving character */ - return EOF; - } else if (data == '#') { - /* End of packet */ - break; - } else { - /* Check for space */ - if (*pkt_len >= pkt_buf_len) { - DEBUG_PRINT("packet buffer overflow\n"); - return EOF; - } - - /* Store character and update checksum */ - pkt_buf[(*pkt_len)++] = (char) data; - } - } - -#if DEBUG - { - size_t p; - DEBUG_PRINT("<- "); - for (p = 0; p < *pkt_len; p++) { - if (dbg_is_printable_char(pkt_buf[p])) { - DEBUG_PRINT("%c", pkt_buf[p]); - } else { - DEBUG_PRINT("\\x%02x", pkt_buf[p] & 0xff); - } - } - DEBUG_PRINT("\n"); - } -#endif - - /* Receive the checksum */ - if ((dbg_read(buf, sizeof(buf), 2) == EOF) || - (dbg_dec_hex(buf, 2, &expected_csum, 1) == EOF)) { - return EOF; - } - - /* Verify checksum */ - actual_csum = dbg_checksum(pkt_buf, *pkt_len); - if (actual_csum != expected_csum) { - /* Send packet nack */ - DEBUG_PRINT("received packet with bad checksum\n"); - dbg_sys_putchar('-'); - return EOF; - } - - /* Send packet ack */ - dbg_sys_putchar('+'); - return 0; -} - -/***************************************************************************** - * Data Encoding/Decoding - ****************************************************************************/ - -/*! - * Encode data to its hex-value representation in a buffer. - * - * Returns: - * 0+ number of bytes written to buf - * EOF if the buffer is too small - */ -int GdbServer::dbg_enc_hex(char *buf, size_t buf_len, const char *data, size_t data_len) -{ - size_t pos; - - if (buf_len < data_len*2) { - /* Buffer too small */ - return EOF; - } - - for (pos = 0; pos < data_len; pos++) { - *buf++ = dbg_get_digit((data[pos] >> 4) & 0xf); - *buf++ = dbg_get_digit((data[pos] ) & 0xf); - } - - return data_len*2; -} - -/*! - * Decode data from its hex-value representation to a buffer. - * - * Returns: - * 0 if successful - * EOF if the buffer is too small - */ -int GdbServer::dbg_dec_hex(const char *buf, size_t buf_len, char *data, size_t data_len) -{ - size_t pos; - int tmp; - - if (buf_len != data_len*2) { - /* Buffer too small */ - return EOF; - } - - for (pos = 0; pos < data_len; pos++) { - /* Decode high nibble */ - tmp = dbg_get_val(*buf++, 16); - if (tmp == EOF) { - /* Buffer contained junk. */ - ASSERT(0); - return EOF; - } - - data[pos] = tmp << 4; - - /* Decode low nibble */ - tmp = dbg_get_val(*buf++, 16); - if (tmp == EOF) { - /* Buffer contained junk. */ - ASSERT(0); - return EOF; - } - data[pos] |= tmp; - } - - return 0; -} - -/*! - * Encode data to its binary representation in a buffer. - * - * Returns: - * 0+ number of bytes written to buf - * EOF if the buffer is too small - */ -int GdbServer::dbg_enc_bin(char *buf, size_t buf_len, const char *data, size_t data_len) -{ - size_t buf_pos, data_pos; - - for (buf_pos = 0, data_pos = 0; data_pos < data_len; data_pos++) { - if (data[data_pos] == '$' || - data[data_pos] == '#' || - data[data_pos] == '}' || - data[data_pos] == '*') { - if (buf_pos+1 >= buf_len) { - ASSERT(0); - return EOF; - } - buf[buf_pos++] = '}'; - buf[buf_pos++] = data[data_pos] ^ 0x20; - } else { - if (buf_pos >= buf_len) { - ASSERT(0); - return EOF; - } - buf[buf_pos++] = data[data_pos]; - } - } - - return buf_pos; -} - -/*! - * Decode data from its bin-value representation to a buffer. - * - * Returns: - * 0+ if successful, number of bytes decoded - * EOF if the buffer is too small - */ -int GdbServer::dbg_dec_bin(const char *buf, size_t buf_len, char *data, size_t data_len) -{ - size_t buf_pos, data_pos; - - for (buf_pos = 0, data_pos = 0; buf_pos < buf_len; buf_pos++) { - if (data_pos >= data_len) { - /* Output buffer overflow */ - ASSERT(0); - return EOF; - } - if (buf[buf_pos] == '}') { - /* The next byte is escaped! */ - if (buf_pos+1 >= buf_len) { - /* There's an escape character, but no escaped character - * following the escape character. */ - ASSERT(0); - return EOF; - } - buf_pos += 1; - data[data_pos++] = buf[buf_pos] ^ 0x20; - } else { - data[data_pos++] = buf[buf_pos]; - } - } - - return data_pos; -} - -/*! - * Read from memory and encode into buf. - * - * Returns: - * 0+ number of bytes written to buf - * EOF if the buffer is too small - */ -int GdbServer::dbg_mem_read(char *buf, size_t buf_len, address addr, size_t len, dbg_enc_func enc) -{ - char data[64]; - size_t pos; - - if (len > sizeof(data)) { - return EOF; - } - - /* Read from system memory */ - for (pos = 0; pos < len; pos++) { - if (dbg_sys_mem_readb((address)(addr+pos), &data[pos])) { - /* Failed to read */ - return EOF; - } - } - - /* Encode data */ - return enc(buf, buf_len, data, len); -} - -/*! - * Write to memory from encoded buf. - */ -int GdbServer::dbg_mem_write(const char *buf, size_t buf_len, address addr, size_t len, dbg_dec_func dec) -{ - char data[64]; - size_t pos; - - if (len > sizeof(data)) { - return EOF; - } - - /* Decode data */ - if (dec(buf, buf_len, data, len) == EOF) { - return EOF; - } - - /* Write to system memory */ - for (pos = 0; pos < len; pos++) { - if (dbg_sys_mem_writeb((address)(addr+pos), data[pos])) { - /* Failed to write */ - return EOF; - } - } - - return 0; -} - -/*! - * Send OK packet - */ -int GdbServer::dbg_send_ok_packet(char *buf, size_t buf_len) -{ - return dbg_send_packet("OK", 2); -} - -/*! - * Send a message to the debugging console (via O XX... packet) - */ -int GdbServer::dbg_send_conmsg_packet(char *buf, size_t buf_len, const char *msg) -{ - size_t size; - int status; - - if (buf_len < 2) { - /* Buffer too small */ - return EOF; - } - - buf[0] = 'O'; - status = dbg_enc_hex(&buf[1], buf_len-1, msg, strlen(msg)); - if (status == EOF) { - return EOF; - } - size = 1 + status; - return dbg_send_packet(buf, size); -} - -/*! - * Send a signal packet (S AA). - */ -int GdbServer::dbg_send_signal_packet(char *buf, size_t buf_len, char signal) -{ - size_t size; - int status; - - if (buf_len < 4) { - /* Buffer too small */ - return EOF; - } - - buf[0] = 'S'; - status = dbg_enc_hex(&buf[1], buf_len-1, &signal, 1); - if (status == EOF) { - return EOF; - } - size = 1 + status; - return dbg_send_packet(buf, size); -} - -/*! - * Send an error packet (E AA). - */ -int GdbServer::dbg_send_error_packet(char *buf, size_t buf_len, char error) -{ - size_t size; - int status; - - if (buf_len < 4) { - /* Buffer too small */ - return EOF; - } - - buf[0] = 'E'; - status = dbg_enc_hex(&buf[1], buf_len-1, &error, 1); - if (status == EOF) { - return EOF; - } - size = 1 + status; - return dbg_send_packet(buf, size); -} - -/*! - * Write a sequence of bytes. - * - * Returns: - * 0 if successful - * EOF if failed to write all bytes - */ -int GdbServer::dbg_write(const char *buf, size_t len) -{ - while (len--) { - if (dbg_sys_putchar(*buf++) == EOF) { - return EOF; - } - } - - return 0; -} - -/*! - * Read a sequence of bytes. - * - * Returns: - * 0 if successfully read len bytes - * EOF if failed to read all bytes - */ -int GdbServer::dbg_read(char *buf, size_t buf_len, size_t len) -{ - char c; - - if (buf_len < len) { - /* Buffer too small */ - return EOF; - } - - while (len--) { - if ((c = dbg_sys_getc()) == EOF) { - return EOF; - } - *buf++ = c; - } - - return 0; -} - -/* - * Main debug loop. Handles commands. - */ -int GdbServer::dbg_main() -{ - address addr; - char pkt_buf[256]; - int status; - size_t length; - size_t pkt_len; - const char *ptr_next; - - if (dbg_send_signal_packet(pkt_buf, sizeof(pkt_buf), 0) == EOF) { - return EOF; - } - - while (1) { - /* Receive the next packet */ - status = dbg_recv_packet(pkt_buf, sizeof(pkt_buf), &pkt_len); - if (status == EOF) { - break; - } - - if (pkt_len == 0) { - /* Received empty packet.. */ - continue; - } - - ptr_next = pkt_buf; - - /* - * Handle one letter commands - */ - switch (pkt_buf[0]) { - - /* Calculate remaining space in packet from ptr_next position. */ - #define token_remaining_buf (pkt_len-(ptr_next-pkt_buf)) - - /* Expecting a seperator. If not present, go to error */ - #define token_expect_seperator(c) \ - { \ - if (!ptr_next || *ptr_next != c) { \ - goto error; \ - } else { \ - ptr_next += 1; \ - } \ - } - - /* Expecting an integer argument. If not present, go to error */ - #define token_expect_integer_arg(arg) \ - { \ - arg = dbg_strtol(ptr_next, token_remaining_buf, \ - 16, &ptr_next); \ - if (!ptr_next) { \ - goto error; \ - } \ - } - - /* - * Read Registers - * Command Format: g - */ - case 'g': - /* Encode registers */ - status = dbg_enc_hex(pkt_buf, sizeof(pkt_buf), - (char *)&(m_dbg_state.registers), - sizeof(m_dbg_state.registers)); - if (status == EOF) { - goto error; - } - pkt_len = status; - status = dbg_send_packet(pkt_buf, pkt_len); - break; - - /* - * Write Registers - * Command Format: G XX... - */ - case 'G': - status = dbg_dec_hex(pkt_buf+1, pkt_len-1, - (char *)&(m_dbg_state.registers), - sizeof(m_dbg_state.registers)); - if (status == EOF) { - goto error; - } - status = dbg_send_ok_packet(pkt_buf, sizeof(pkt_buf)); - break; - - /* - * Read a Register - * Command Format: p n - */ - case 'p': - ptr_next += 1; - token_expect_integer_arg(addr); - - if (addr >= DBG_CPU_I386_NUM_REGISTERS) { - goto error; - } - - /* Read Register */ - status = dbg_enc_hex(pkt_buf, sizeof(pkt_buf), - (char *)&(m_dbg_state.registers[addr]), - sizeof(m_dbg_state.registers[addr])); - if (status == EOF) { - goto error; - } - status = dbg_send_packet(pkt_buf, status); - break; - - /* - * Write a Register - * Command Format: P n...=r... - */ - case 'P': - ptr_next += 1; - token_expect_integer_arg(addr); - token_expect_seperator('='); - - if (addr >= DBG_CPU_I386_NUM_REGISTERS) { - goto error; - } - - status = dbg_dec_hex(ptr_next, token_remaining_buf, - (char *)&(m_dbg_state.registers[addr]), - sizeof(m_dbg_state.registers[addr])); - if (status == EOF) { - goto error; - } - status = dbg_send_ok_packet(pkt_buf, sizeof(pkt_buf)); - break; - - /* - * Read Memory - * Command Format: m addr,length - */ - case 'm': - ptr_next += 1; - token_expect_integer_arg(addr); - token_expect_seperator(','); - token_expect_integer_arg(length); - - /* Read Memory */ - status = dbg_mem_read(pkt_buf, sizeof(pkt_buf), - addr, length, dbg_enc_hex); - if (status == EOF) { - goto error; - } - status = dbg_send_packet(pkt_buf, status); - break; - - /* - * Write Memory - * Command Format: M addr,length:XX.. - */ - case 'M': - ptr_next += 1; - token_expect_integer_arg(addr); - token_expect_seperator(','); - token_expect_integer_arg(length); - token_expect_seperator(':'); - - /* Write Memory */ - status = dbg_mem_write(ptr_next, token_remaining_buf, - addr, length, dbg_dec_hex); - if (status == EOF) { - goto error; - } - status = dbg_send_ok_packet(pkt_buf, sizeof(pkt_buf)); - break; - - /* - * Write Memory (Binary) - * Command Format: X addr,length:XX.. - */ - case 'X': - ptr_next += 1; - token_expect_integer_arg(addr); - token_expect_seperator(','); - token_expect_integer_arg(length); - token_expect_seperator(':'); - - /* Write Memory */ - status = dbg_mem_write(ptr_next, token_remaining_buf, - addr, length, dbg_dec_bin); - if (status == EOF) { - goto error; - } - status = dbg_send_ok_packet(pkt_buf, sizeof(pkt_buf)); - break; - - /* - * Continue - * Command Format: c [addr] - */ - case 'c': - dbg_sys_continue(); - return 0; - - /* - * Single-step - * Command Format: s [addr] - */ - case 's': - dbg_sys_step(); - return 0; - - case '?': - status = dbg_send_signal_packet(pkt_buf, sizeof(pkt_buf), 0); - break; - - /* - * Unsupported Command - */ - default: - status = dbg_send_packet(NULL, 0); - } - - if (status == EOF) { - // Error! - return EOF; - } - - continue; - - error: - dbg_send_error_packet(pkt_buf, sizeof(pkt_buf), 0x00); - - #undef token_remaining_buf - #undef token_expect_seperator - #undef token_expect_integer_arg - } - - return 0; -} - -} diff --git a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_dummy.cpp b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_dummy.cpp index 1555470..473a5f9 100644 --- a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_dummy.cpp +++ b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_dummy.cpp @@ -21,7 +21,7 @@ namespace ata { DummyDVDDriveATADeviceDriver::DummyDVDDriveATADeviceDriver() { strcpy(m_serialNumber, "0123456789"); strcpy(m_firmwareRevision, "1.0.0"); - strcpy(m_modelNumber, "vXn DDVDD0010000"); + strcpy(m_modelNumber, "SBx DDVDD0010000"); } DummyDVDDriveATADeviceDriver::~DummyDVDDriveATADeviceDriver() { diff --git a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_image.cpp b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_image.cpp index 05c0460..35555c4 100644 --- a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_image.cpp +++ b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vdvd_image.cpp @@ -26,7 +26,7 @@ using namespace atapi; ImageDVDDriveATADeviceDriver::ImageDVDDriveATADeviceDriver() { strcpy(m_serialNumber, "9876543210"); strcpy(m_firmwareRevision, "1.0.0"); - strcpy(m_modelNumber, "vXn VDVDD0010000"); + strcpy(m_modelNumber, "SBx VDVDD0010000"); } ImageDVDDriveATADeviceDriver::~ImageDVDDriveATADeviceDriver() { diff --git a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_dummy.cpp b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_dummy.cpp index 5be2074..99ea4c6 100644 --- a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_dummy.cpp +++ b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_dummy.cpp @@ -32,7 +32,7 @@ static void padString(uint8_t *dest, const char *src, uint32_t length) { DummyHardDriveATADeviceDriver::DummyHardDriveATADeviceDriver() { strcpy(m_serialNumber, "0123456789"); strcpy(m_firmwareRevision, "1.0.0"); - strcpy(m_modelNumber, "vXn DHDD0010000"); + strcpy(m_modelNumber, "SBx DHDD0010000"); // Initialize with parameters for a 10 GiB hard drive m_numCylinders = 20480; diff --git a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_image.cpp b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_image.cpp index c01b077..719dd49 100644 --- a/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_image.cpp +++ b/modules/core/src/common/strikebox/hw/ata/drvs/drv_vhd_image.cpp @@ -33,7 +33,7 @@ ImageHardDriveATADeviceDriver::ImageHardDriveATADeviceDriver() { // TODO: fill in with appropriate data strcpy(m_serialNumber, "9876543210"); strcpy(m_firmwareRevision, "1.0.0"); - strcpy(m_modelNumber, "vXn VHDD0010000"); + strcpy(m_modelNumber, "SBx VHDD0010000"); // Initialize an empty (invalid) disk m_numCylinders = 0; diff --git a/modules/core/src/common/strikebox/hw/ohci/ohci.cpp b/modules/core/src/common/strikebox/hw/ohci/ohci.cpp deleted file mode 100644 index ab72328..0000000 --- a/modules/core/src/common/strikebox/hw/ohci/ohci.cpp +++ /dev/null @@ -1,1847 +0,0 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->USBController->OHCI.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#include "strikebox/hw/ohci/ohci.h" - -#include "strikebox/log.h" - -#include - -//#define DEBUG_PACKET -//#define DEBUG_ISOCH - -namespace strikebox { - -#define ONE_KB 1024 -#define ONE_MB (1024 * 1024) - -#define XBOX_MEMORY_SIZE (64 * ONE_MB) -#define CONTIGUOUS_MEMORY_BASE 0x80000000 - -// Compute (a*b)/c with a 96 bit intermediate result -static inline uint64_t Muldiv64(uint64_t a, uint32_t b, uint32_t c) { - union { - uint64_t ll; - struct { - uint32_t low, high; - } l; - } u, res; - uint64_t rl, rh; - - u.ll = a; - rl = (uint64_t)u.l.low * (uint64_t)b; - rh = (uint64_t)u.l.high * (uint64_t)b; - rh += (rl >> 32); - res.l.high = rh / c; - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} - - - -/* These macros are used to access the bits of the various registers */ -// HcControl -#define OHCI_CTL_CBSR ((1<<0)|(1<<1)) // ControlBulkServiceRatio -#define OHCI_CTL_PLE (1<<2) // PeriodicListEnable -#define OHCI_CTL_IE (1<<3) // IsochronousEnable -#define OHCI_CTL_CLE (1<<4) // ControlListEnable -#define OHCI_CTL_BLE (1<<5) // BulkListEnable -#define OHCI_CTL_HCFS ((1<<6)|(1<<7)) // HostControllerFunctionalState -#define OHCI_CTL_IR (1<<8) // InterruptRouting -#define OHCI_CTL_RWC (1<<9) // RemoteWakeupConnected -#define OHCI_CTL_RWE (1<<10) // RemoteWakeupEnable -// HcCommandStatus -#define OHCI_STATUS_HCR (1<<0) // HostControllerReset -#define OHCI_STATUS_CLF (1<<1) // ControlListFilled -#define OHCI_STATUS_BLF (1<<2) // BulkListFilled -#define OHCI_STATUS_OCR (1<<3) // OwnershipChangeRequest -#define OHCI_STATUS_SOC ((1<<6)|(1<<7)) // SchedulingOverrunCount -// HcInterruptStatus -#define OHCI_INTR_SO (1<<0) // SchedulingOverrun -#define OHCI_INTR_WD (1<<1) // WritebackDoneHead -#define OHCI_INTR_SF (1<<2) // StartofFrame -#define OHCI_INTR_RD (1<<3) // ResumeDetected -#define OHCI_INTR_UE (1<<4) // UnrecoverableError -#define OHCI_INTR_FNO (1<<5) // FrameNumberOverflow -#define OHCI_INTR_RHSC (1<<6) // RootHubStatusChange -#define OHCI_INTR_OC (1<<30) // OwnershipChange -// HcInterruptEnable, HcInterruptDisable -#define OHCI_INTR_MIE (1<<31) // MasterInterruptEnable -// HcHCCA -#define OHCI_HCCA_MASK 0xFFFFFF00 // HCCA mask -// HcFmInterval -#define OHCI_FMI_FI 0x00003FFF // FrameInterval -#define OHCI_FMI_FIT 0x80000000 // FrameIntervalToggle -// HcFmRemaining -#define OHCI_FMR_FR 0x00003FFF // FrameRemaining -#define OHCI_FMR_FRT 0x80000000 // FrameRemainingToggle -// LSThreshold -#define OHCI_LS_THRESH 0x628 // LSThreshold -// HcRhDescriptorA -#define OHCI_RHA_RW_MASK 0x00000000 // Mask of supported features -#define OHCI_RHA_PSM (1<<8) // PowerSwitchingMode -#define OHCI_RHA_NPS (1<<9) // NoPowerSwitching -#define OHCI_RHA_DT (1<<10) // DeviceType -#define OHCI_RHA_OCPM (1<<11) // OverCurrentProtectionMode -#define OHCI_RHA_NOCP (1<<12) // NoOverCurrentProtection -// HcRhStatus -#define OHCI_RHS_LPS (1<<0) // LocalPowerStatus -#define OHCI_RHS_OCI (1<<1) // OverCurrentIndicator -#define OHCI_RHS_DRWE (1<<15) // DeviceRemoteWakeupEnable -#define OHCI_RHS_LPSC (1<<16) // LocalPowerStatusChange -#define OHCI_RHS_OCIC (1<<17) // OverCurrentIndicatorChange -#define OHCI_RHS_CRWE (1<<31) // ClearRemoteWakeupEnable -// HcRhPortStatus -#define OHCI_PORT_CCS (1<<0) // CurrentConnectStatus -#define OHCI_PORT_PES (1<<1) // PortEnableStatus -#define OHCI_PORT_PSS (1<<2) // PortSuspendStatus -#define OHCI_PORT_POCI (1<<3) // PortOverCurrentIndicator -#define OHCI_PORT_PRS (1<<4) // PortResetStatus -#define OHCI_PORT_PPS (1<<8) // PortPowerStatus -#define OHCI_PORT_LSDA (1<<9) // LowSpeedDeviceAttached -#define OHCI_PORT_CSC (1<<16) // ConnectStatusChange -#define OHCI_PORT_PESC (1<<17) // PortEnableStatusChange -#define OHCI_PORT_PSSC (1<<18) // PortSuspendStatusChange -#define OHCI_PORT_OCIC (1<<19) // PortOverCurrentIndicatorChange -#define OHCI_PORT_PRSC (1<<20) // PortResetStatusChange -#define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \ - |OHCI_PORT_OCIC|OHCI_PORT_PRSC) - -/* Bitfields for the first word of an ED */ -#define OHCI_ED_FA_SHIFT 0 -#define OHCI_ED_FA_MASK (0x7F<> OHCI_##field##_SHIFT) - -#define OHCI_SET_BM(val, field, newval) do { \ - val &= ~OHCI_##field##_MASK; \ - val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \ - } while(0) - -/* Indicates the direction of data flow as specified by the TD */ -#define OHCI_TD_DIR_SETUP 0x0 // to endpoint -#define OHCI_TD_DIR_OUT 0x1 // to endpoint -#define OHCI_TD_DIR_IN 0x2 // from endpoint -#define OHCI_TD_DIR_RESERVED 0x3 - -#define OHCI_CC_NOERROR 0x0 -#define OHCI_CC_CRC 0x1 -#define OHCI_CC_BITSTUFFING 0x2 -#define OHCI_CC_DATATOGGLEMISMATCH 0x3 -#define OHCI_CC_STALL 0x4 -#define OHCI_CC_DEVICENOTRESPONDING 0x5 -#define OHCI_CC_PIDCHECKFAILURE 0x6 -#define OHCI_CC_UNDEXPETEDPID 0x7 -#define OHCI_CC_DATAOVERRUN 0x8 -#define OHCI_CC_DATAUNDERRUN 0x9 -#define OHCI_CC_BUFFEROVERRUN 0xC -#define OHCI_CC_BUFFERUNDERRUN 0xD - -#define USB_HZ 12000000 - -#define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b))) - -#define OHCI_PAGE_MASK 0xFFFFF000 -#define OHCI_OFFSET_MASK 0xFFF - -OHCI::OHCI(virt86::VirtualProcessor& vp, int Irq, USBPCIDevice* UsbObj) - : m_vp(vp) -{ - int offset = 0; - USBPortOps* ops; - - m_IrqNum = Irq; - m_UsbDevice = UsbObj; - m_bFrameTime = false; - ops = new USBPortOps(); - { - using namespace std::placeholders; - - ops->attach = std::bind(&OHCI::OHCI_Attach, this, _1); - ops->detach = std::bind(&OHCI::OHCI_Detach, this, _1); - ops->child_detach = std::bind(&OHCI::OHCI_ChildDetach, this, _1); - ops->wakeup = std::bind(&OHCI::OHCI_Wakeup, this, _1); - ops->complete = std::bind(&OHCI::OHCI_AsyncCompletePacket, this, _1, _2); - } - - if (m_IrqNum == 9) { - offset = 4; - } - - for (int i = 0; i < 4; i++) { - m_UsbDevice->USB_RegisterPort(&m_Registers.RhPort[i].UsbPort, i + offset, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL, ops); - } - OHCI_PacketInit(&m_UsbPacket); - - m_UsbFrameTime = 1000000ULL; // 1 ms expressed in ns - m_TicksPerUsbTick = 1000000000ULL / USB_HZ; // 83 - - // Do a hardware reset - OHCI_StateReset(); -} - -void OHCI::OHCI_FrameBoundaryWrapper(void* pVoid) -{ - static_cast(pVoid)->OHCI_FrameBoundaryWorker(); -} - -void OHCI::OHCI_FrameBoundaryWorker() -{ - OHCI_HCCA hcca; - - while (m_bFrameTime) {} - m_bFrameTime = true; - - if (OHCI_ReadHCCA(m_Registers.HcHCCA, &hcca)) { - log_warning("OHCI: HCCA read error at physical address 0x%X\n", m_Registers.HcHCCA); - OHCI_FatalError(); - m_bFrameTime = false; - return; - } - - // Process all the lists at the end of the frame - if (m_Registers.HcControl & OHCI_CTL_PLE) { - // From the standard: "The head pointer used for a particular frame is determined by using the last 5 bits of the - // Frame Counter as an offset into the interrupt array within the HCCA." - int n = m_Registers.HcFmNumber & 0x1F; - OHCI_ServiceEDlist(hcca.HccaInterrruptTable[n], 0); // dropped little -> big endian conversion from XQEMU - } - - // Cancel all pending packets if either of the lists has been disabled - if (m_OldHcControl & (~m_Registers.HcControl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { - if (m_AsyncTD) { - m_UsbDevice->USB_CancelPacket(&m_UsbPacket); - m_AsyncTD = 0; - } - OHCI_StopEndpoints(); - } - m_OldHcControl = m_Registers.HcControl; - OHCI_ProcessLists(0); - - // Stop if UnrecoverableError happened or OHCI_SOF will crash - if (m_Registers.HcInterruptStatus & OHCI_INTR_UE) { - m_bFrameTime = false; - return; - } - - // From the standard: "This bit is loaded from the FrameIntervalToggle field of - // HcFmInterval whenever FrameRemaining reaches 0." - m_Registers.HcFmRemaining = (m_Registers.HcFmInterval & OHCI_FMI_FIT) == 0 ? - m_Registers.HcFmRemaining & ~OHCI_FMR_FRT : m_Registers.HcFmRemaining | OHCI_FMR_FRT; - - // Increment frame number - m_Registers.HcFmNumber = (m_Registers.HcFmNumber + 1) & 0xFFFF; // prevent overflow - hcca.HccaFrameNumber = m_Registers.HcFmNumber; // dropped big -> little endian conversion from XQEMU - - if (m_DoneCount == 0 && !(m_Registers.HcInterruptStatus & OHCI_INTR_WD)) { - if (!m_Registers.HcDoneHead) { - // From the standard: "This is set to zero whenever HC writes the content of this - // register to HCCA. It also sets the WritebackDoneHead of HcInterruptStatus." - log_fatal("OHCI: HcDoneHead is zero but WritebackDoneHead interrupt is not set!\n"); - } - - if (m_Registers.HcInterrupt & m_Registers.HcInterruptStatus) { - // From the standard: "The least significant bit of this entry is set to 1 to indicate whether an - // unmasked HcInterruptStatus was set when HccaDoneHead was written." It's tecnically incorrect to - // do this to HcDoneHead instead of HccaDoneHead however it doesn't matter since HcDoneHead is - // zeroed below - m_Registers.HcDoneHead |= 1; - } - - hcca.HccaDoneHead = m_Registers.HcDoneHead; // dropped big -> little endian conversion from XQEMU - m_Registers.HcDoneHead = 0; - m_DoneCount = 7; - OHCI_SetInterrupt(OHCI_INTR_WD); - } - - if (m_DoneCount != 7 && m_DoneCount != 0) { - // decrease Done Queue counter - m_DoneCount--; - } - - // Do SOF stuff here - OHCI_SOF(false); - - // Writeback HCCA - if (OHCI_WriteHCCA(m_Registers.HcHCCA, &hcca)) { - log_warning("OHCI: HCCA write error at physical address 0x%X\n", m_Registers.HcHCCA); - OHCI_FatalError(); - } - m_bFrameTime = false; -} - -void OHCI::OHCI_FatalError() -{ - // According to the standard, an OHCI will stop operating, and set itself into error state - // (which can be queried by MMIO). Instead of calling directly CxbxKrnlCleanup, we let the - // HCD know the problem so that it can try to solve it - - OHCI_SetInterrupt(OHCI_INTR_UE); - OHCI_BusStop(); - log_debug("OHCI: an unrecoverable error occoured!\n"); -} - -bool OHCI::OHCI_ReadHCCA(uint32_t Paddr, OHCI_HCCA* Hcca) -{ - // ergo720: there could be a peculiar problem if the shared memory between HCD and HC is allocated by the - // VMManager with VirtualAlloc: the physical allocation would not reside in memory.bin and if we tried to - // access the physical address of it, we would access an empty page. In practice, I disassembled various - // xbe's of my games and discovered that this shared memory is allocated with MmAllocateContiguousMemory - // which means we can access it from the contiguous region just fine (lucky) - // ... provided that XDK revisions didn't alter this - - // NOTE: this shared memory contains the HCCA + EDs and TDs - - if (Paddr != 0) { - memcpy(Hcca, reinterpret_cast(Paddr + CONTIGUOUS_MEMORY_BASE), sizeof(OHCI_HCCA)); - return false; - } - - return true; // error -} - -bool OHCI::OHCI_WriteHCCA(uint32_t Paddr, OHCI_HCCA* Hcca) -{ - if (Paddr != 0) { - // We need to calculate the offset of the HccaFrameNumber member to avoid overwriting HccaInterrruptTable - size_t OffsetOfFrameNumber = offsetof(OHCI_HCCA, HccaFrameNumber); - - memcpy(reinterpret_cast(Paddr + OffsetOfFrameNumber + CONTIGUOUS_MEMORY_BASE), - reinterpret_cast(Hcca) + OffsetOfFrameNumber, 8); - return false; - } - - return true; // error -} - -bool OHCI::OHCI_ReadED(uint32_t Paddr, OHCI_ED* Ed) -{ - if (Paddr != 0) { - m_vp.LMemRead(Paddr, sizeof(*Ed), Ed); - return false; - } - return true; // error -} - -bool OHCI::OHCI_WriteED(uint32_t Paddr, OHCI_ED* Ed) -{ - if (Paddr != 0) { - // According to the standard, only the HeadP field is writable by the HC, so we'll write just that - size_t OffsetOfHeadP = offsetof(OHCI_ED, HeadP); - m_vp.LMemWrite(Paddr, 4, Ed + OffsetOfHeadP); - return false; - } - return true; // error -} - -bool OHCI::OHCI_ReadTD(uint32_t Paddr, OHCI_TD* Td) -{ - if (Paddr != 0) { - m_vp.LMemRead(Paddr, sizeof(*Td), Td); - return false; - } - return true; // error -} - -bool OHCI::OHCI_WriteTD(uint32_t Paddr, OHCI_TD* Td) -{ - if (Paddr != 0) { - m_vp.LMemWrite(Paddr, sizeof(*Td), Td); - return false; - } - return true; // error -} - -bool OHCI::OHCI_ReadIsoTD(uint32_t Paddr, OHCI_ISO_TD* td) { - if (Paddr != 0) { - m_vp.LMemRead(Paddr, sizeof(*td), td); - return false; - } - return true; // error -} - -bool OHCI::OHCI_WriteIsoTD(uint32_t Paddr, OHCI_ISO_TD* td) { - if (Paddr != 0) { - m_vp.LMemWrite(Paddr, sizeof(*td), td); - return false; - } - return true; // error -} - -bool OHCI::OHCI_CopyTD(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite) -{ - uint32_t ptr, n; - - // Figure out if we are crossing a 4K page boundary - ptr = Td->CurrentBufferPointer; - n = 0x1000 - (ptr & 0xFFF); - if (n > (unsigned int)Length) { - n = (unsigned int)Length; - } - - if (OHCI_FindAndCopyTD(ptr, Buffer, n, bIsWrite)) { - return true; // error - } - if (n == (unsigned int)Length) { - return false; // no bytes left to copy - } - - // From the standard: "If during the data transfer the buffer address contained in the HC's working copy of - // CurrentBufferPointer crosses a 4K boundary, the upper 20 bits of BufferEnd are copied to the - // working value of CurrentBufferPointer causing the next buffer address to be the 0th byte in the - // same 4K page that contains the last byte of the buffer." - ptr = Td->BufferEnd & ~0xFFFu; - Buffer += n; - if (OHCI_FindAndCopyTD(ptr, Buffer, Length - n, bIsWrite)) { - return true; // error - } - return false; -} - -bool OHCI::OHCI_CopyIsoTD(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffer, int Length, bool bIsWrite) { - uint32_t ptr, n; - - ptr = start_addr; - n = 0x1000 - (ptr & 0xFFF); - if (n > (unsigned int)Length) { - n = Length; - } - - if (OHCI_FindAndCopyTD(ptr, Buffer, n, bIsWrite)) { - return true; // error - } - if (n == (unsigned int)Length) { - return false; // no bytes left to copy - } - ptr = end_addr & ~0xfffu; - Buffer += n; - if (OHCI_FindAndCopyTD(ptr, Buffer, Length - n, bIsWrite)) { - return true; // error - } - return false; -} - -bool OHCI::OHCI_FindAndCopyTD(uint32_t Paddr, uint8_t* Buffer, int Length, bool bIsWrite) -{ - // ergo720: the buffer pointed to by Paddr can be anywhere in memory (it depends on how the xbe has - // allocated it) so, sadly, we cannot make any assumptions here regarding its location like we did - // in OHCI_ReadHCCA and the problem with VirtualAlloc can arise this time. Because of the hack in - // TranslateVAddrToPAddr, VirtualAlloc allocations are identity mapped and addresses below 0x4000000 - // (Xbox) or 0x8000000 (Chihiro, Devkit) cannot be used by the VMManager for anything but to allocate - // xbe sections. This means that if Paddr is higher than the maximum possible physical address, then - // we know it's an identity mapped address, otherwise it's a contiguous address - - int offset = 0; - - if (Paddr == 0) { - return true; // error - } - - //if (g_bIsRetail) { - if (Paddr < XBOX_MEMORY_SIZE) { - offset = CONTIGUOUS_MEMORY_BASE; - } - /*} - else { - if (Paddr < CHIHIRO_MEMORY_SIZE) { - offset = CONTIGUOUS_MEMORY_BASE; - } - }*/ - - if (bIsWrite) { - memcpy(reinterpret_cast(Paddr + offset), Buffer, Length); - } - else { - memcpy(Buffer, reinterpret_cast(Paddr + offset), Length); - } - - return false; -} - -int OHCI::OHCI_ServiceEDlist(uint32_t Head, int Completion) -{ - OHCI_ED ed; - uint32_t next_ed; - uint32_t current; - int active; - - active = 0; - - if (Head == 0) { - // no ED here, nothing to do - return 0; - } - - for (current = Head; current; current = next_ed) { - if (OHCI_ReadED(current, &ed)) { - log_warning("OHCI: ED read error at physical address 0x%X\n", current); - OHCI_FatalError(); - return 0; - } - - // From the standard "An Endpoint Descriptor (ED) is a 16-byte, memory resident structure that must be aligned to a - // 16-byte boundary." - next_ed = ed.NextED & OHCI_DPTR_MASK; - - if ((ed.HeadP & OHCI_ED_H) || (ed.Flags & OHCI_ED_K)) { // halted or skip - // Cancel pending packets for ED that have been paused - uint32_t addr = ed.HeadP & OHCI_DPTR_MASK; - if (m_AsyncTD && addr == m_AsyncTD) { - m_UsbDevice->USB_CancelPacket(&m_UsbPacket); - m_AsyncTD = 0; - m_UsbDevice->USB_DeviceEPstopped(m_UsbPacket.Endpoint->Dev, m_UsbPacket.Endpoint); - } - continue; - } - - while ((ed.HeadP & OHCI_DPTR_MASK) != ed.TailP) { // a TD is available to be processed -#ifdef DEBUG_PACKET - log_spew("OHCI: ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u " - "h=%u c=%u\n head=0x%.8x tailp=0x%.8x next=0x%.8x\n", current, - OHCI_BM(ed.Flags, ED_FA), OHCI_BM(ed.Flags, ED_EN), - OHCI_BM(ed.Flags, ED_D), (ed.Flags & OHCI_ED_S) != 0, - (ed.Flags & OHCI_ED_K) != 0, (ed.Flags & OHCI_ED_F) != 0, - OHCI_BM(ed.Flags, ED_MPS), (ed.HeadP & OHCI_ED_H) != 0, - (ed.HeadP & OHCI_ED_C) != 0, ed.HeadP & OHCI_DPTR_MASK, - ed.TailP & OHCI_DPTR_MASK, ed.NextED & OHCI_DPTR_MASK); -#endif - active = 1; - - if ((ed.Flags & OHCI_ED_F) == 0) { - // Handle control, interrupt or bulk endpoints - if (OHCI_ServiceTD(&ed)) { - break; - } - } - else { - // Handle isochronous endpoints - if (OHCI_ServiceIsoTD(&ed, Completion)) { - break; - } - } - } - - // Writeback ED - if (OHCI_WriteED(current, &ed)) { - OHCI_FatalError(); - return 0; - } - } - - return active; -} - -int OHCI::OHCI_ServiceTD(OHCI_ED* Ed) -{ - int direction; - size_t length = 0, packetlen = 0; -#ifdef DEBUG_PACKET - const char *str = nullptr; -#endif - int pid; - int ret; - int i; - XboxDeviceState* dev; - USBEndpoint* ep; - OHCI_TD td; - uint32_t addr; - int flag_r; - int completion; - - addr = Ed->HeadP & OHCI_DPTR_MASK; - // See if this TD has already been submitted to the device - completion = (addr == m_AsyncTD); - if (completion && !m_AsyncComplete) { -#ifdef DEBUG_PACKET - log_spew("OHCI: Skipping async TD\n"); -#endif - return 1; - } - if (OHCI_ReadTD(addr, &td)) { - log_warning("OHCI: TD read error at physical address 0x%X\n", addr); - OHCI_FatalError(); - return 0; - } - - // From the standard: "This 2-bit field indicates the direction of data flow and the PID - // to be used for the token. This field is only relevant to the HC if the D field in the ED - // was set to 00b or 11b indicating that the PID determination is deferred to the TD." - direction = OHCI_BM(Ed->Flags, ED_D); - switch (direction) { - case OHCI_TD_DIR_OUT: - case OHCI_TD_DIR_IN: - // Same value - break; - default: - direction = OHCI_BM(td.Flags, TD_DP); - } - - // Info: Each USB transaction consists of a - // 1. Token Packet, (Header defining what it expects to follow). - // 2. Optional Data Packet, (Containing the payload). - // 3. Status Packet, (Used to acknowledge transactions and to provide a means of error correction). - - // There are three types of token packets: - // In - Informs the USB device that the host wishes to read information. - // Out - Informs the USB device that the host wishes to send information. - // Setup - Used to begin control transfers. - - switch (direction) { - case OHCI_TD_DIR_IN: -#ifdef DEBUG_PACKET - str = "in"; -#endif - pid = USB_TOKEN_IN; - break; - case OHCI_TD_DIR_OUT: -#ifdef DEBUG_PACKET - str = "out"; -#endif - pid = USB_TOKEN_OUT; - break; - case OHCI_TD_DIR_SETUP: -#ifdef DEBUG_PACKET - str = "setup"; -#endif - pid = USB_TOKEN_SETUP; - break; - default: - log_warning("OHCI: bad direction\n"); - return 1; - } - - // Check if this TD has a buffer of user data to transfer - if (td.CurrentBufferPointer && td.BufferEnd) { - if ((td.CurrentBufferPointer & 0xFFFFF000) != (td.BufferEnd & 0xFFFFF000)) { - // the buffer crosses a 4K page boundary - length = (td.BufferEnd & 0xFFF) + 0x1001 - (td.CurrentBufferPointer & 0xFFF); - } - else { - // the buffer is within a single page - length = (td.BufferEnd - td.CurrentBufferPointer) + 1; - } - - packetlen = length; - if (length && direction != OHCI_TD_DIR_IN) { - // The endpoint may not allow us to transfer it all now - packetlen = (Ed->Flags & OHCI_ED_MPS_MASK) >> OHCI_ED_MPS_SHIFT; - if (packetlen > length) { - packetlen = length; - } - if (!completion) { - if (OHCI_CopyTD(&td, m_UsbBuffer, packetlen, false)) { - OHCI_FatalError(); - } - } - } - } - - flag_r = (td.Flags & OHCI_TD_R) != 0; -#ifdef DEBUG_PACKET - log_spew("OHCI: TD @ 0x%.8X %lld of %lld bytes %s r=%d cbp=0x%.8X be=0x%.8X\n", - addr, (int64_t)packetlen, (int64_t)length, str, flag_r, td.CurrentBufferPointer, td.BufferEnd); - -#if LOG_LEVEL >= LOG_LEVEL_SPEW - if (packetlen > 0 && direction != OHCI_TD_DIR_IN) { - printf(" data:"); - for (i = 0; i < packetlen; i++) { - printf(" %.2x", m_UsbBuffer[i]); - } - printf("\n"); - } -#endif - -#endif - if (completion) { - m_AsyncTD = 0; - m_AsyncComplete = 0; - } - else { - if (m_AsyncTD) { - // From XQEMU: "??? The hardware should allow one active packet per endpoint. - // We only allow one active packet per controller. This should be sufficient - // as long as devices respond in a timely manner." - log_debug("OHCI: too many pending packets\n"); - return 1; - } - dev = OHCI_FindDevice(OHCI_BM(Ed->Flags, ED_FA)); - ep = m_UsbDevice->USB_GetEP(dev, pid, OHCI_BM(Ed->Flags, ED_EN)); - m_UsbDevice->USB_PacketSetup(&m_UsbPacket, pid, ep, 0, addr, !flag_r, OHCI_BM(td.Flags, TD_DI) == 0); - m_UsbDevice->USB_PacketAddBuffer(&m_UsbPacket, m_UsbBuffer, packetlen); - m_UsbDevice->USB_HandlePacket(dev, &m_UsbPacket); -#ifdef DEBUG_PACKET - log_spew("OHCI: status=%d\n", m_UsbPacket.Status); -#endif - if (m_UsbPacket.Status == USB_RET_ASYNC) { - m_UsbDevice->USB_DeviceFlushEPqueue(dev, ep); - m_AsyncTD = addr; - return 1; - } - } - if (m_UsbPacket.Status == USB_RET_SUCCESS) { - ret = m_UsbPacket.ActualLength; - } - else { - ret = m_UsbPacket.Status; - } - - if (ret >= 0) { - if (direction == OHCI_TD_DIR_IN) { - if (OHCI_CopyTD(&td, m_UsbBuffer, ret, true)) { - OHCI_FatalError(); - } -#ifdef DEBUG_PACKET -#if LOG_LEVEL >= LOG_LEVEL_SPEW - printf(" data:"); - for (i = 0; i < ret; i++) - printf(" %.2x", m_UsbBuffer[i]); - printf("\n"); -#endif -#endif - } - else { - ret = packetlen; - } - } - - if (ret >= 0) { - if ((td.CurrentBufferPointer & 0xFFF) + ret > 0xFFF) { - td.CurrentBufferPointer = (td.BufferEnd & ~0xFFF) + ((td.CurrentBufferPointer + ret) & 0xFFF); - } - else { - td.CurrentBufferPointer += ret; - } - } - - // Writeback - if ((unsigned int)ret == packetlen || (direction == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { - // Transmission succeeded - if ((unsigned int)ret == length) { - td.CurrentBufferPointer = 0; - } - td.Flags |= OHCI_TD_T1; - td.Flags ^= OHCI_TD_T0; - OHCI_SET_BM(td.Flags, TD_CC, OHCI_CC_NOERROR); - OHCI_SET_BM(td.Flags, TD_EC, 0); - - if ((direction != OHCI_TD_DIR_IN) && ((unsigned int)ret != length)) { - // Partial packet transfer: TD not ready to retire yet - goto exit_no_retire; - } - - // Setting ED_C is part of the TD retirement process - Ed->HeadP &= ~OHCI_ED_C; - if (td.Flags & OHCI_TD_T0) - Ed->HeadP |= OHCI_ED_C; - } - else { - if (ret >= 0) { - log_debug("OHCI: Underrun\n"); - OHCI_SET_BM(td.Flags, TD_CC, OHCI_CC_DATAUNDERRUN); - } - else { - switch (ret) { - case USB_RET_IOERROR: - case USB_RET_NODEV: - log_debug("OHCI: Received DEV ERROR\n"); - OHCI_SET_BM(td.Flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); - break; - case USB_RET_NAK: - log_debug("OHCI: Received NAK\n"); - return 1; - case USB_RET_STALL: - log_debug("OHCI: Received STALL\n"); - OHCI_SET_BM(td.Flags, TD_CC, OHCI_CC_STALL); - break; - case USB_RET_BABBLE: - log_debug("OHCI: Received BABBLE\n"); - OHCI_SET_BM(td.Flags, TD_CC, OHCI_CC_DATAOVERRUN); - break; - default: - log_debug("OHCI: Bad device response %d\n", ret); - OHCI_SET_BM(td.Flags, TD_CC, OHCI_CC_UNDEXPETEDPID); - OHCI_SET_BM(td.Flags, TD_EC, 3); - } - } - Ed->HeadP |= OHCI_ED_H; - } - - // Retire this TD - Ed->HeadP &= ~OHCI_DPTR_MASK; - Ed->HeadP |= td.NextTD & OHCI_DPTR_MASK; - td.NextTD = m_Registers.HcDoneHead; - m_Registers.HcDoneHead = addr; - i = OHCI_BM(td.Flags, TD_DI); - if (i < m_DoneCount) { - m_DoneCount = i; - } - if (OHCI_BM(td.Flags, TD_CC) != OHCI_CC_NOERROR) { - m_DoneCount = 0; - } - -exit_no_retire: - if (OHCI_WriteTD(addr, &td)) { - OHCI_FatalError(); - return 1; - } - return OHCI_BM(td.Flags, TD_CC) != OHCI_CC_NOERROR; -} - -XboxDeviceState* OHCI::OHCI_FindDevice(uint8_t Addr) -{ - XboxDeviceState* dev; - int i; - - for (i = 0; i < 4; i++) { - if ((m_Registers.RhPort[i].HcRhPortStatus & OHCI_PORT_PES) == 0) { - continue; // port is disabled - } - dev = m_UsbDevice->USB_FindDevice(&m_Registers.RhPort[i].UsbPort, Addr); - if (dev != nullptr) { - return dev; // return found device - } - } - - return nullptr; -} - -void OHCI::OHCI_StateReset() -{ - // The usb state can be USB_Suspend if it is a software reset, and USB_Reset if it is a hardware - // reset or cold boot - - OHCI_BusStop(); - m_OldHcControl = 0; - - // Reset all registers - m_Registers.HcRevision = 0x10; - m_Registers.HcControl = 0; - m_Registers.HcCommandStatus = 0; - m_Registers.HcInterruptStatus = 0; - m_Registers.HcInterrupt = OHCI_INTR_MIE; // enable interrupts - - m_Registers.HcHCCA = 0; - m_Registers.HcPeriodCurrentED = 0; - m_Registers.HcControlHeadED = m_Registers.HcControlCurrentED = 0; - m_Registers.HcBulkHeadED = m_Registers.HcBulkCurrentED = 0; - m_Registers.HcDoneHead = 0; - - m_Registers.HcFmInterval = 0; - m_Registers.HcFmInterval |= (0x2778 << 16); // TBD according to the standard, using what XQEMU sets (FSLargestDataPacket) - m_Registers.HcFmInterval |= 0x2EDF; // bit-time of a frame. 1 frame = 1 ms (FrameInterval) - m_Registers.HcFmRemaining = 0; - m_Registers.HcFmNumber = 0; - m_Registers.HcPeriodicStart = 0; - m_Registers.HcLSThreshold = OHCI_LS_THRESH; - - m_Registers.HcRhDescriptorA = OHCI_RHA_NOCP | OHCI_RHA_NPS | 4; // The xbox lacks the hw to switch off the power on the ports and has 4 ports per HC - m_Registers.HcRhDescriptorB = 0; // The attached devices are removable and use PowerSwitchingMode to control the power on the ports - m_Registers.HcRhStatus = 0; - - m_DoneCount = 7; - - for (int i = 0; i < 4; i++) - { - OHCIPort* Port = &m_Registers.RhPort[i]; - Port->HcRhPortStatus = 0; - if (Port->UsbPort.Dev && Port->UsbPort.Dev->Attached) { - m_UsbDevice->USB_PortReset(&Port->UsbPort); - } - } - if (m_AsyncTD) { - m_UsbDevice->USB_CancelPacket(&m_UsbPacket); - m_AsyncTD = 0; - } - - OHCI_StopEndpoints(); - - log_debug("OHCI: Reset mode event.\n"); -} - -void OHCI::OHCI_BusStart() -{ - // Create the EOF timer. Let's try a factor of 50 (1 virtual ms -> 50 real ms) - m_pEOFtimer = Timer_Create(OHCI_FrameBoundaryWrapper, this, 50); - - log_debug("OHCI: Operational mode event\n"); - - // SOF event - OHCI_SOF(true); -} - -void OHCI::OHCI_BusStop() -{ - if (m_pEOFtimer) { - // Delete existing EOF timer - Timer_Exit(m_pEOFtimer); - } - m_pEOFtimer = nullptr; -} - -void OHCI::OHCI_SOF(bool bCreate) -{ - // set current SOF time - m_SOFtime = GetTime_NS(m_pEOFtimer); - - // make timer expire at SOF + 1 virtual ms from now - if (bCreate) { - Timer_Start(m_pEOFtimer, m_UsbFrameTime); - } - - OHCI_SetInterrupt(OHCI_INTR_SF); -} - -void OHCI::OHCI_ChangeState(uint32_t Value) -{ - uint32_t OldState = m_Registers.HcControl & OHCI_CTL_HCFS; - m_Registers.HcControl = Value; - uint32_t NewState = m_Registers.HcControl & OHCI_CTL_HCFS; - - // no state change - if (OldState == NewState) { - return; - } - - switch (NewState) - { - case Operational: - OHCI_BusStart(); - break; - - case Suspend: - OHCI_BusStop(); - log_debug("OHCI: Suspend mode event\n"); - break; - - case Resume: - log_debug("OHCI: Resume mode event\n"); - break; - - case Reset: - OHCI_StateReset(); - break; - - default: - log_warning("OHCI: Unknown USB mode!\n"); - } -} - -void OHCI::OHCI_PacketInit(USBPacket* packet) -{ - IOVector* vec = &packet->IoVec; - vec->IoVecStruct = new IoVec; - vec->IoVecNumber = 0; - vec->AllocNumber = 1; - vec->Size = 0; -} - -uint32_t OHCI::OHCI_ReadRegister(uint32_t Addr) -{ - uint32_t ret = 0xFFFFFFFF; - - if (Addr & 3) { - // The standard allows only aligned reads to the registers - log_debug("OHCI: Unaligned read. Ignoring.\n"); - return ret; - } - else { - switch (Addr >> 2) // read the register - { - case 0: // HcRevision - ret = m_Registers.HcRevision; - break; - - case 1: // HcControl - ret = m_Registers.HcControl; - break; - - case 2: // HcCommandStatus - ret = m_Registers.HcCommandStatus; - break; - - case 3: // HcInterruptStatus - ret = m_Registers.HcInterruptStatus; - break; - - case 4: // HcInterruptEnable - case 5: // HcInterruptDisable - ret = m_Registers.HcInterrupt; - break; - - case 6: // HcHCCA - ret = m_Registers.HcHCCA; - break; - - case 7: // HcPeriodCurrentED - ret = m_Registers.HcPeriodCurrentED; - break; - - case 8: // HcControlHeadED - ret = m_Registers.HcControlHeadED; - break; - - case 9: // HcControlCurrentED - ret = m_Registers.HcControlCurrentED; - break; - - case 10: // HcBulkHeadED - ret = m_Registers.HcBulkHeadED; - break; - - case 11: // HcBulkCurrentED - ret = m_Registers.HcBulkCurrentED; - break; - - case 12: // HcDoneHead - ret = m_Registers.HcDoneHead; - break; - - case 13: // HcFmInterval - ret = m_Registers.HcFmInterval; - break; - - case 14: // HcFmRemaining - ret = OHCI_GetFrameRemaining(); - break; - - case 15: // HcFmNumber - ret = m_Registers.HcFmNumber; - break; - - case 16: // HcPeriodicStart - ret = m_Registers.HcPeriodicStart; - break; - - case 17: // HcLSThreshold - ret = m_Registers.HcLSThreshold; - break; - - case 18: // HcRhDescriptorA - ret = m_Registers.HcRhDescriptorA; - break; - - case 19: // HcRhDescriptorB - ret = m_Registers.HcRhDescriptorB; - break; - - case 20: // HcRhStatus - ret = m_Registers.HcRhStatus; - break; - - // Always report that the port power is on since the Xbox cannot switch off the electrical current to it - case 21: // RhPort 0 - ret = m_Registers.RhPort[0].HcRhPortStatus | OHCI_PORT_PPS; - break; - - case 22: // RhPort 1 - ret = m_Registers.RhPort[1].HcRhPortStatus | OHCI_PORT_PPS; - break; - - case 23: // RhPort 2 - ret = m_Registers.RhPort[2].HcRhPortStatus | OHCI_PORT_PPS; - break; - - case 24: // RhPort 3 - ret = m_Registers.RhPort[3].HcRhPortStatus | OHCI_PORT_PPS; - break; - - default: - log_warning("OHCI: Read register operation with bad offset %u. Ignoring.\n", Addr >> 2); - } - return ret; - } -} - -void OHCI::OHCI_WriteRegister(uint32_t Addr, uint32_t Value) -{ - if (Addr & 3) { - // The standard allows only aligned writes to the registers - log_debug("OHCI: Unaligned write. Ignoring.\n"); - return; - } - else { - switch (Addr >> 2) - { - case 0: // HcRevision - // This register is read-only - break; - - case 1: // HcControl - OHCI_ChangeState(Value); - break; - - case 2: // HcCommandStatus - { - // SOC is read-only - Value &= ~OHCI_STATUS_SOC; - - // From the standard: "The Host Controller must ensure that bits written as 1 become set - // in the register while bits written as 0 remain unchanged in the register." - m_Registers.HcCommandStatus |= Value; - - if (m_Registers.HcCommandStatus & OHCI_STATUS_HCR) { - // Do a hardware reset - OHCI_StateReset(); - } - } - break; - - case 3: // HcInterruptStatus - m_Registers.HcInterruptStatus &= ~Value; - OHCI_UpdateInterrupt(); - break; - - case 4: // HcInterruptEnable - m_Registers.HcInterrupt |= Value; - OHCI_UpdateInterrupt(); - break; - - case 5: // HcInterruptDisable - m_Registers.HcInterrupt &= ~Value; - OHCI_UpdateInterrupt(); - break; - - case 6: // HcHCCA - // The standard says the minimum alignment is 256 bytes and so bits 0 through 7 are always zero - m_Registers.HcHCCA = Value & OHCI_HCCA_MASK; - break; - - case 7: // HcPeriodCurrentED - // This register is read-only - break; - - case 8: // HcControlHeadED - m_Registers.HcControlHeadED = Value & OHCI_DPTR_MASK; - break; - - case 9: // HcControlCurrentED - m_Registers.HcControlCurrentED = Value & OHCI_DPTR_MASK; - break; - - case 10: // HcBulkHeadED - m_Registers.HcBulkHeadED = Value & OHCI_DPTR_MASK; - break; - - case 11: // HcBulkCurrentED - m_Registers.HcBulkCurrentED = Value & OHCI_DPTR_MASK; - break; - - case 12: // HcDoneHead - // This register is read-only - break; - - case 13: // HcFmInterval - { - if ((Value & OHCI_FMI_FIT) != (m_Registers.HcFmInterval & OHCI_FMI_FIT)) { - log_debug("OHCI: Changing frame interval duration. New value is %u\n", Value & OHCI_FMI_FI); - } - m_Registers.HcFmInterval = Value & ~0xC000; - } - break; - - case 14: // HcFmRemaining - // This register is read-only - break; - - case 15: // HcFmNumber - // This register is read-only - break; - - case 16: // HcPeriodicStart - m_Registers.HcPeriodicStart = Value & 0x3FFF; - break; - - case 17: // HcLSThreshold - m_Registers.HcLSThreshold = Value & 0xFFF; - break; - - case 18: // HcRhDescriptorA - m_Registers.HcRhDescriptorA &= ~OHCI_RHA_RW_MASK; - m_Registers.HcRhDescriptorA |= Value & OHCI_RHA_RW_MASK; // ?? - break; - - case 19: // HcRhDescriptorB - // Don't do anything, the attached devices are all removable and PowerSwitchingMode is always 0 - break; - - case 20: // HcRhStatus - OHCI_SetHubStatus(Value); - break; - - case 21: // RhPort 0 - OHCI_PortSetStatus(0, Value); - break; - - case 22: // RhPort 1 - OHCI_PortSetStatus(1, Value); - break; - - case 23: // RhPort 2 - OHCI_PortSetStatus(2, Value); - break; - - case 24: // RhPort 3 - OHCI_PortSetStatus(3, Value); - break; - - default: - log_warning("OHCI: Write register operation with bad offset %u. Ignoring.\n", Addr >> 2); - } - } -} - -void OHCI::OHCI_UpdateInterrupt() -{ - // TODO: interrupts - if ((m_Registers.HcInterrupt & OHCI_INTR_MIE) && (m_Registers.HcInterruptStatus & m_Registers.HcInterrupt)) { - //HalSystemInterrupts[m_IrqNum].Assert(false); - //HalSystemInterrupts[m_IrqNum].Assert(true); - } -} - -void OHCI::OHCI_SetInterrupt(uint32_t Value) -{ - m_Registers.HcInterruptStatus |= Value; - OHCI_UpdateInterrupt(); -} - -uint32_t OHCI::OHCI_GetFrameRemaining() -{ - uint16_t frame; - uint64_t ticks; - - if ((m_Registers.HcControl & OHCI_CTL_HCFS) != Operational) { - return m_Registers.HcFmRemaining & OHCI_FMR_FRT; - } - - // Being in USB operational state guarantees that m_pEOFtimer and m_SOFtime were set already - ticks = GetTime_NS(m_pEOFtimer) - m_SOFtime; - - // Avoid Muldiv64 if possible - if (ticks >= m_UsbFrameTime) { - return m_Registers.HcFmRemaining & OHCI_FMR_FRT; - } - - ticks = Muldiv64(1, ticks, m_TicksPerUsbTick); - frame = static_cast((m_Registers.HcFmInterval & OHCI_FMI_FI) - ticks); - - return (m_Registers.HcFmRemaining & OHCI_FMR_FRT) | frame; -} - -void OHCI::OHCI_StopEndpoints() -{ - XboxDeviceState* dev; - int i, j; - - for (i = 0; i < 4; i++) { - dev = m_Registers.RhPort[i].UsbPort.Dev; - if (dev && dev->Attached) { - m_UsbDevice->USB_DeviceEPstopped(dev, &dev->EP_ctl); - for (j = 0; j < USB_MAX_ENDPOINTS; j++) { - m_UsbDevice->USB_DeviceEPstopped(dev, &dev->EP_in[j]); - m_UsbDevice->USB_DeviceEPstopped(dev, &dev->EP_out[j]); - } - } - } -} - -void OHCI::OHCI_SetHubStatus(uint32_t Value) -{ - uint32_t old_state; - - old_state = m_Registers.HcRhStatus; - - // write 1 to clear OCIC - if (Value & OHCI_RHS_OCIC) { - m_Registers.HcRhStatus &= ~OHCI_RHS_OCIC; - } - - if (Value & OHCI_RHS_LPS) { - int i; - - for (i = 0; i < 4; i++) { - OHCI_PortPower(i, 0); - } - log_debug("OHCI: powered down all ports\n"); - } - - if (Value & OHCI_RHS_LPSC) { - int i; - - for (i = 0; i < 4; i++) { - OHCI_PortPower(i, 1); - } - log_debug("OHCI: powered up all ports\n"); - } - - if (Value & OHCI_RHS_DRWE) { - m_Registers.HcRhStatus |= OHCI_RHS_DRWE; - } - - if (Value & OHCI_RHS_CRWE) { - m_Registers.HcRhStatus &= ~OHCI_RHS_DRWE; - } - - if (old_state != m_Registers.HcRhStatus) { - OHCI_SetInterrupt(OHCI_INTR_RHSC); - } -} - -void OHCI::OHCI_PortPower(int i, int p) -{ - if (p) { - m_Registers.RhPort[i].HcRhPortStatus |= OHCI_PORT_PPS; - } - else { - m_Registers.RhPort[i].HcRhPortStatus &= ~(OHCI_PORT_PPS | - OHCI_PORT_CCS | - OHCI_PORT_PSS | - OHCI_PORT_PRS); - } -} - -void OHCI::OHCI_PortSetStatus(int PortNum, uint32_t Value) -{ - uint32_t old_state; - OHCIPort* port; - - port = &m_Registers.RhPort[PortNum]; - old_state = port->HcRhPortStatus; - - // Write to clear CSC, PESC, PSSC, OCIC, PRSC - if (Value & OHCI_PORT_WTC) { - port->HcRhPortStatus &= ~(Value & OHCI_PORT_WTC); - } - - if (Value & OHCI_PORT_CCS) { - port->HcRhPortStatus &= ~OHCI_PORT_PES; - } - - OHCI_PortSetIfConnected(PortNum, Value & OHCI_PORT_PES); - - if (OHCI_PortSetIfConnected(PortNum, Value & OHCI_PORT_PSS)) { - log_debug("OHCI: port %d: SUSPEND\n", PortNum); - } - - if (OHCI_PortSetIfConnected(PortNum, Value & OHCI_PORT_PRS)) { - log_debug("OHCI: port %d: RESET\n", PortNum); - m_UsbDevice->USB_DeviceReset(port->UsbPort.Dev); - port->HcRhPortStatus &= ~OHCI_PORT_PRS; - // ??? Should this also set OHCI_PORT_PESC - port->HcRhPortStatus |= OHCI_PORT_PES | OHCI_PORT_PRSC; - } - - // Invert order here to ensure in ambiguous case, device is powered up... - if (Value & OHCI_PORT_LSDA) { - OHCI_PortPower(PortNum, 0); - } - - if (Value & OHCI_PORT_PPS) { - OHCI_PortPower(PortNum, 1); - } - - if (old_state != port->HcRhPortStatus) { - OHCI_SetInterrupt(OHCI_INTR_RHSC); - } -} - -int OHCI::OHCI_PortSetIfConnected(int i, uint32_t Value) -{ - int ret = 1; - - // writing a 0 has no effect - if (Value == 0) { - return 0; - } - - // If CurrentConnectStatus is cleared we set ConnectStatusChange - if (!(m_Registers.RhPort[i].HcRhPortStatus & OHCI_PORT_CCS)) { - m_Registers.RhPort[i].HcRhPortStatus |= OHCI_PORT_CSC; - if (m_Registers.HcRhStatus & OHCI_RHS_DRWE) { - // from XQEMU: TODO: CSC is a wakeup event - } - return 0; - } - - if (m_Registers.RhPort[i].HcRhPortStatus & Value) { - ret = 0; - } - - // set the bit - m_Registers.RhPort[i].HcRhPortStatus |= Value; - - return ret; -} - -void OHCI::OHCI_Detach(USBPort* Port) -{ - OHCIPort* port = &m_Registers.RhPort[Port->PortIndex]; - uint32_t old_state = port->HcRhPortStatus; - - OHCI_AsyncCancelDevice(Port->Dev); - - // set connect status - if (port->HcRhPortStatus & OHCI_PORT_CCS) { - port->HcRhPortStatus &= ~OHCI_PORT_CCS; - port->HcRhPortStatus |= OHCI_PORT_CSC; - } - - // disable port - if (port->HcRhPortStatus & OHCI_PORT_PES) { - port->HcRhPortStatus &= ~OHCI_PORT_PES; - port->HcRhPortStatus |= OHCI_PORT_PESC; - } - - log_debug("OHCI: Detached port %d\n", Port->PortIndex); - - if (old_state != port->HcRhPortStatus) { - OHCI_SetInterrupt(OHCI_INTR_RHSC); - } -} - -void OHCI::OHCI_Attach(USBPort* Port) -{ - OHCIPort* port = &m_Registers.RhPort[Port->PortIndex]; - uint32_t old_state = port->HcRhPortStatus; - - // set connect status - port->HcRhPortStatus |= OHCI_PORT_CCS | OHCI_PORT_CSC; - - // update speed - if (port->UsbPort.Dev->Speed == USB_SPEED_LOW) { - port->HcRhPortStatus |= OHCI_PORT_LSDA; - } - else { - port->HcRhPortStatus &= ~OHCI_PORT_LSDA; - } - - // notify of remote-wakeup - if ((m_Registers.HcControl & OHCI_CTL_HCFS) == Suspend) { - OHCI_SetInterrupt(OHCI_INTR_RD); - } - - log_debug("OHCI: Attached port %d", Port->PortIndex); - - if (old_state != port->HcRhPortStatus) { - OHCI_SetInterrupt(OHCI_INTR_RHSC); - } -} - -void OHCI::OHCI_ChildDetach(XboxDeviceState* child) { - OHCI_AsyncCancelDevice(child); -} - -void OHCI::OHCI_Wakeup(USBPort* port1) { - OHCIPort* port = &m_Registers.RhPort[port1->PortIndex]; - uint32_t intr = 0; - if (port->HcRhPortStatus & OHCI_PORT_PSS) { - log_debug("OHCI: port %d: wakeup", port1->PortIndex); - port->HcRhPortStatus |= OHCI_PORT_PSSC; - port->HcRhPortStatus &= ~OHCI_PORT_PSS; - intr = OHCI_INTR_RHSC; - } - // Note that the controller can be suspended even if this port is not - if ((m_Registers.HcControl & OHCI_CTL_HCFS) == Suspend) { - log_debug("OHCI: remote-wakeup: SUSPEND->RESUME"); - // From the standard: "The only interrupts possible in the USBSUSPEND state are ResumeDetected (the - // Host Controller will have changed the HostControllerFunctionalState to the USBRESUME state) - // and OwnershipChange." - m_Registers.HcControl &= ~OHCI_CTL_HCFS; - m_Registers.HcControl |= Resume; - intr = OHCI_INTR_RD; - } - OHCI_SetInterrupt(intr); -} - -void OHCI::OHCI_AsyncCompletePacket(USBPort* port, USBPacket* packet) { -#ifdef DEBUG_PACKET - log_spew("OHCI: Async packet complete"); -#endif - m_AsyncComplete = 1; - OHCI_ProcessLists(1); -} - -void OHCI::OHCI_AsyncCancelDevice(XboxDeviceState* dev) -{ - if (m_AsyncTD && - m_UsbDevice->USB_IsPacketInflight(&m_UsbPacket) && - m_UsbPacket.Endpoint->Dev == dev) { - m_UsbDevice->USB_CancelPacket(&m_UsbPacket); - m_AsyncTD = 0; - } -} - -void OHCI::OHCI_ProcessLists(int completion) -{ - // Only process the control list if it is enabled (HcControl) and has available TD's (HcCommandStatus) - if ((m_Registers.HcControl & OHCI_CTL_CLE) && (m_Registers.HcCommandStatus & OHCI_STATUS_CLF)) { - if (m_Registers.HcControlCurrentED && m_Registers.HcControlCurrentED != m_Registers.HcControlHeadED) { - log_debug("OHCI: head 0x%X, current 0x%X\n", - m_Registers.HcControlHeadED, m_Registers.HcControlCurrentED); - } - if (!OHCI_ServiceEDlist(m_Registers.HcControlHeadED, completion)) { - m_Registers.HcControlCurrentED = 0; - m_Registers.HcCommandStatus &= ~OHCI_STATUS_CLF; - } - } - - // Only process the bulk list if it is enabled (HcControl) and has available TD's (HcCommandStatus) - if ((m_Registers.HcControl & OHCI_CTL_BLE) && (m_Registers.HcCommandStatus & OHCI_STATUS_BLF)) { - if (!OHCI_ServiceEDlist(m_Registers.HcBulkHeadED, completion)) { - m_Registers.HcBulkCurrentED = 0; - m_Registers.HcCommandStatus &= ~OHCI_STATUS_BLF; - } - } -} - - -int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion) -{ - int dir; - size_t len = 0; -#ifdef DEBUG_ISOCH - const char *str = nullptr; -#endif - int pid; - int ret; - int i; - XboxDeviceState* dev; - USBEndpoint* ep; - OHCI_ISO_TD iso_td; - uint32_t addr; - uint16_t starting_frame; - int16_t relative_frame_number; - int frame_count; - uint32_t start_offset, next_offset, end_offset = 0; - uint32_t start_addr, end_addr; - - addr = ed->HeadP & OHCI_DPTR_MASK; - - if (OHCI_ReadIsoTD(addr, &iso_td)) { - log_debug("OHCI: ISO_TD read error at physical address 0x%X\n", addr); - OHCI_FatalError(); - return 0; - } - - starting_frame = OHCI_BM(iso_td.Flags, TD_SF); - frame_count = OHCI_BM(iso_td.Flags, TD_FC); - // From the standard: "The Host Controller does an unsigned subtraction of StartingFrame from the 16 bits of - // HcFmNumber to arrive at a signed value for a relative frame number (frame R)." - relative_frame_number = USUB(m_Registers.HcFmNumber & 0xFFFF, starting_frame); - -#ifdef DEBUG_ISOCH - log_spew("OHCI: --- ISO_TD ED head 0x%.8x tailp 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "frame_number 0x%.8x starting_frame 0x%.8x\n" - "frame_count 0x%.8x relative %d\n" - "di 0x%.8x cc 0x%.8x\n", - ed->HeadP & OHCI_DPTR_MASK, ed->TailP & OHCI_DPTR_MASK, - iso_td.Flags, iso_td.BufferPage0, iso_td.NextTD, iso_td.BufferEnd, - iso_td.Offset[0], iso_td.Offset[1], iso_td.Offset[2], iso_td.Offset[3], - iso_td.Offset[4], iso_td.Offset[5], iso_td.Offset[6], iso_td.Offset[7], - m_Registers.HcFmNumber, starting_frame, - frame_count, relative_frame_number, - OHCI_BM(iso_td.Flags, TD_DI), OHCI_BM(iso_td.Flags, TD_CC)); -#endif - - if (relative_frame_number < 0) { - // From the standard: "If the relative frame number is negative, then the current frame is earlier than the 0th frame - // of the Isochronous TD and the Host Controller advances to the next ED." - log_debug("OHCI: ISO_TD R=%d < 0\n", relative_frame_number); - return 1; - } - else if (relative_frame_number > frame_count) { - // From the standard: "If the relative frame number is greater than - // FrameCount, then the Isochronous TD has expired and a error condition exists." - log_debug("OHCI: ISO_TD R=%d > FC=%d\n", relative_frame_number, frame_count); - OHCI_SET_BM(iso_td.Flags, TD_CC, OHCI_CC_DATAOVERRUN); - ed->HeadP &= ~OHCI_DPTR_MASK; - ed->HeadP |= (iso_td.NextTD & OHCI_DPTR_MASK); - iso_td.NextTD = m_Registers.HcDoneHead; - m_Registers.HcDoneHead = addr; - i = OHCI_BM(iso_td.Flags, TD_DI); - if (i < m_DoneCount) { - m_DoneCount = i; - } - if (OHCI_WriteIsoTD(addr, &iso_td)) { - OHCI_FatalError(); - return 1; - } - return 0; - } - - // From the standard: "If the relative frame number is between 0 and FrameCount, then the Host Controller issues - // a token to the endpoint and attempts a data transfer using the buffer described by the Isochronous TD." - - dir = OHCI_BM(ed->Flags, ED_D); - switch (dir) { - case OHCI_TD_DIR_IN: -#ifdef DEBUG_ISOCH - str = "in"; -#endif - pid = USB_TOKEN_IN; - break; - case OHCI_TD_DIR_OUT: -#ifdef DEBUG_ISOCH - str = "out"; -#endif - pid = USB_TOKEN_OUT; - break; - case OHCI_TD_DIR_SETUP: -#ifdef DEBUG_ISOCH - str = "setup"; -#endif - pid = USB_TOKEN_SETUP; - break; - default: - log_warning("OHCI: Bad direction %d\n", dir); - return 1; - } - - if (!iso_td.BufferPage0 || !iso_td.BufferEnd) { - log_debug("OHCI: ISO_TD bp 0x%.8X be 0x%.8X\n", iso_td.BufferPage0, iso_td.BufferEnd); - return 1; - } - - start_offset = iso_td.Offset[relative_frame_number]; - next_offset = iso_td.Offset[relative_frame_number + 1]; - - // From the standard: "If the Host Controller supports checking of the Offsets, if either Offset[R] or Offset[R+1] does - // not have a ConditionCode of NOT ACCESSED or if the Offset[R + 1] is not greater than or equal to Offset[R], then - // an Unrecoverable Error is indicated." - // ergo720: I have a doubt here: according to the standard, the error condition is set if ConditionCode (bits 12-15 of - // Offset[R(+1)] is not 111x (= NOT ACCESSED), however the check below is only triggered if the bits are all zeros - // (= NO ERROR). So, if, for example, these bits are 1100 (= BUFFER OVERRUN), the check won't be triggered when actually - // it should be - - if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xE) || - ((relative_frame_number < frame_count) && - !(OHCI_BM(next_offset, TD_PSW_CC) & 0xE))) { - log_debug("OHCI: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n", start_offset, next_offset); - return 1; - } - - if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { - log_spew("OHCI: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n", start_offset, next_offset); - return 1; - } - - // From the standard: "Bit 12 of offset R then selects the upper 20 bits of the physical address - // as either BufferPage0 when bit 12 = 0 or the upper 20 bits of BufferEnd when bit 12 = 1." - - if ((start_offset & 0x1000) == 0) { - start_addr = (iso_td.BufferPage0 & OHCI_PAGE_MASK) | - (start_offset & OHCI_OFFSET_MASK); - } - else { - start_addr = (iso_td.BufferEnd & OHCI_PAGE_MASK) | - (start_offset & OHCI_OFFSET_MASK); - } - - // From the standard: "If the data packet is not the last in an Isochronous TD (R not equal to FrameCount), - // then the ending address of the buffer is found by using Offset[R + 1] - 1. This value is then used to create a - // physical address in the same manner as the Offset[R] was used to create the starting physical address." - - if (relative_frame_number < frame_count) { - end_offset = next_offset - 1; - if ((end_offset & 0x1000) == 0) { - end_addr = (iso_td.BufferPage0 & OHCI_PAGE_MASK) | - (end_offset & OHCI_OFFSET_MASK); - } - else { - end_addr = (iso_td.BufferEnd & OHCI_PAGE_MASK) | - (end_offset & OHCI_OFFSET_MASK); - } - } - else { - // From the standard: "If, however, the data packet is the last in an Isochronous TD(R = FrameCount), - // then the value of BufferEnd is the address of the last byte in the buffer." - end_addr = iso_td.BufferEnd; - } - - if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { - len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 - - (start_addr & OHCI_OFFSET_MASK); - } - else { - len = end_addr - start_addr + 1; - } - - if (len && dir != OHCI_TD_DIR_IN) { - if (OHCI_CopyIsoTD(start_addr, end_addr, m_UsbBuffer, len, false)) { - OHCI_FatalError(); - return 1; - } - } - - if (!completion) { - bool int_req = relative_frame_number == frame_count && OHCI_BM(iso_td.Flags, TD_DI) == 0; - dev = OHCI_FindDevice(OHCI_BM(ed->Flags, ED_FA)); - ep = m_UsbDevice->USB_GetEP(dev, pid, OHCI_BM(ed->Flags, ED_EN)); - m_UsbDevice->USB_PacketSetup(&m_UsbPacket, pid, ep, 0, addr, false, int_req); - m_UsbDevice->USB_PacketAddBuffer(&m_UsbPacket, m_UsbBuffer, len); - m_UsbDevice->USB_HandlePacket(dev, &m_UsbPacket); - if (m_UsbPacket.Status == USB_RET_ASYNC) { - m_UsbDevice->USB_DeviceFlushEPqueue(dev, ep); - return 1; - } - } - if (m_UsbPacket.Status == USB_RET_SUCCESS) { - ret = m_UsbPacket.ActualLength; - } - else { - ret = m_UsbPacket.Status; - } - -#ifdef DEBUG_ISOCH - log_spew("OHCI: so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n", - start_offset, end_offset, start_addr, end_addr, str, len, ret); -#endif - - // From the standard: "After each data packet transfer, the Rth Offset is replaced with a value that indicates the status of - // the data packet transfer.The upper 4 bits of the value are the ConditionCode for the transfer and the lower 12 bits - // represent the size of the transfer.Together, these two fields constitute the Packet Status Word(PacketStatusWord)." - - // Writeback - if (dir == OHCI_TD_DIR_IN && ret >= 0 && (unsigned int)ret <= len) { - // IN transfer succeeded - if (OHCI_CopyIsoTD(start_addr, end_addr, m_UsbBuffer, ret, true)) { - OHCI_FatalError(); - return 1; - } - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_CC, OHCI_CC_NOERROR); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_SIZE, ret); - } - else if (dir == OHCI_TD_DIR_OUT && (unsigned int)ret == len) { - // OUT transfer succeeded - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_CC, OHCI_CC_NOERROR); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_SIZE, 0); - } - else { - // Handle the error condition - if (ret > static_cast(len)) { // Sequence Error - log_debug("OHCI: DataOverrun %d > %zu\n", ret, len); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_CC, OHCI_CC_DATAOVERRUN); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_SIZE, len); - } - else if (ret >= 0) { // Sequence Error - log_debug("OHCI: DataUnderrun %d\n", ret); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_CC, OHCI_CC_DATAUNDERRUN); - } - else { - switch (ret) { - case USB_RET_IOERROR: // Transmission Errors - case USB_RET_NODEV: - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_CC, OHCI_CC_DEVICENOTRESPONDING); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_SIZE, 0); - break; - case USB_RET_NAK: // NAK and STALL - case USB_RET_STALL: - log_debug("OHCI: got NAK/STALL %d\n", ret); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_CC, OHCI_CC_STALL); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_SIZE, 0); - break; - default: // Unknown Error - log_debug("OHCI: Bad device response %d\n", ret); - OHCI_SET_BM(iso_td.Offset[relative_frame_number], TD_PSW_CC, OHCI_CC_UNDEXPETEDPID); - break; - } - } - } - - if (relative_frame_number == frame_count) { - // Last data packet of ISO TD - retire the TD to the Done Queue - OHCI_SET_BM(iso_td.Flags, TD_CC, OHCI_CC_NOERROR); - ed->HeadP &= ~OHCI_DPTR_MASK; - ed->HeadP |= (iso_td.NextTD & OHCI_DPTR_MASK); - iso_td.NextTD = m_Registers.HcDoneHead; - m_Registers.HcDoneHead = addr; - i = OHCI_BM(iso_td.Flags, TD_DI); - if (i < m_DoneCount) { - m_DoneCount = i; - } - } - if (OHCI_WriteIsoTD(addr, &iso_td)) { - OHCI_FatalError(); - } - return 1; -} - -} diff --git a/modules/core/src/common/strikebox/hw/ohci/ohci_hub.cpp b/modules/core/src/common/strikebox/hw/ohci/ohci_hub.cpp deleted file mode 100644 index 49b911b..0000000 --- a/modules/core/src/common/strikebox/hw/ohci/ohci_hub.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->usb->Hub.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#include - -#include "strikebox/hw/ohci/ohci.h" -#include "strikebox/hw/ohci/ohci_hub.h" - -#include "strikebox/log.h" - -namespace strikebox { - -Hub* g_HubObjArray[4] = { nullptr }; - -static const USBDescEndpoint desc_endp_hub = { - USB_DIR_IN | 0x01, // bEndpointAddress; - USB_ENDPOINT_XFER_INT, // bmAttributes; - 1 + (NUM_PORTS + 7) / 8, // wMaxPacketSize; - 0xFF, // bInterval; - 0, // bRefresh; - 0, // bSynchAddress - 0, // is_audio - nullptr // extra -}; - -static const USBDescIface desc_iface_hub = { - 0, // bInterfaceNumber; - 0, // bAlternateSetting; - 1, // bNumEndpoints; - USB_CLASS_HUB, // bInterfaceClass; - 0, // bInterfaceSubClass - 0, // bInterfaceProtocol - 0, // iInterface - 0, // ndesc - nullptr, // descs - &desc_endp_hub -}; - -static const USBDescConfig desc_config_hub = { - 1, // bNumInterfaces - 1, // bConfigurationValue - 0, // iConfiguration - 0xE0, // bmAttributes - 0, // bMaxPower - 1, // nif - &desc_iface_hub -}; - -static const USBDescDevice desc_device_hub = { - 0x0110, // bcdUSB - USB_CLASS_HUB, // bDeviceClass - 0, // bDeviceSubClass - 0, // bDeviceProtocol - 8, // bMaxPacketSize0 - 1, // bNumConfigurations - &desc_config_hub -}; - -static const USBDesc desc_hub = { - { - 0x0409, // idVendor - 0x55AA, // idProduct - 0x0101, // bcdDevice - STR_MANUFACTURER, // iManufacturer - STR_PRODUCT, // iProduct - STR_SERIALNUMBER // iSerialNumber - }, - &desc_device_hub -}; - -// Class-specific hub descriptor. Remember to update DeviceRemovable and PortPwrCtrlMask if you change NUM_PORTS since their values depend on -// the number of downstream ports available on the hub! Also note that this descriptor cannot be put in the descs member of the interface descriptor -// because then this descriptor will be retrieved during a standard GetDescriptor request instead of the hub-specific GetHubDescriptor request -static const uint8_t HubDescriptor[] = { - 0x0A, // u8 bDescLength; 10 bytes - 0x29, // u8 bDescriptorType; Hub-descriptor - NUM_PORTS, // u8 bNbrPorts; 0x08 - 0x0a, // u16 wHubCharacteristics; (individual port over-current protection, no power switching) - 0x00, - 0x01, // u8 bPwrOn2pwrGood; 2 ms - 0x00, // u8 bHubContrCurrent; 0 mA - 0x00, // u16 DeviceRemovable; all devices are removable - 0x00, - 0xFF, // u8 PortPwrCtrlMask; all 1's for compatibility reasons -}; - -int Hub::Init(int port) { - if (port > 4 || port < 1) { - return -1; - } - - XboxDeviceState* dev = ClassInitFn(); - int rc = UsbHubClaimPort(dev, port); - if (rc != 0) { - m_UsbDev->m_HostController->m_bFrameTime = false; - return rc; - } - m_UsbDev->USB_EpInit(dev); - m_UsbDev->USB_DeviceInit(dev); - m_UsbDev->USB_DeviceAttach(dev); - - m_UsbDev->m_HostController->m_bFrameTime = false; - - return 0; -} - -XboxDeviceState* Hub::ClassInitFn() { - m_pPeripheralFuncStruct = new USBDeviceClass(); - m_HubState = new USBHubState(); - XboxDeviceState* dev = &m_HubState->dev; - - dev->ProductDesc = "Cxbx-Reloaded USB Hub"; - QLIST_INIT(&dev->Strings); - dev->klass = m_pPeripheralFuncStruct; - - { - using namespace std::placeholders; - - m_pPeripheralFuncStruct->init = std::bind(&Hub::UsbHub_Initfn, this, _1); - m_pPeripheralFuncStruct->find_device = std::bind(&Hub::UsbHub_FindDevice, this, _1, _2); - m_pPeripheralFuncStruct->handle_reset = std::bind(&Hub::UsbHub_HandleReset, this); - m_pPeripheralFuncStruct->handle_control = std::bind(&Hub::UsbHub_HandleControl, this, _1, _2, _3, _4, _5, _6, _7); - m_pPeripheralFuncStruct->handle_data = std::bind(&Hub::UsbHub_HandleData, this, _1, _2); - m_pPeripheralFuncStruct->handle_destroy = std::bind(&Hub::UsbHub_HandleDestroy, this); - m_pPeripheralFuncStruct->product_desc = dev->ProductDesc.c_str(); - m_pPeripheralFuncStruct->usb_desc = &desc_hub; - } - - return dev; -} - -int Hub::UsbHubClaimPort(XboxDeviceState* dev, int port) { - int i; - std::vector::iterator it; - - assert(dev->Port == nullptr); - - if (port > 2) { - //m_UsbDev = g_USB1; // FIXME: how to retrieve these? - } - else { - //m_UsbDev = g_USB0; // FIXME: how to retrieve these? - } - - while (m_UsbDev->m_HostController->m_bFrameTime) {} - m_UsbDev->m_HostController->m_bFrameTime = true; - - i = 0; - for (auto usb_port : m_UsbDev->m_FreePorts) { - if (usb_port->Path == std::to_string(port)) { - it = m_UsbDev->m_FreePorts.begin() + i; - break; - } - i++; - } - if (it == m_UsbDev->m_FreePorts.end()) { - log_warning("OHCI: Port requested %d not found (in use?)", port); - return -1; - } - dev->Port = *it; - (*it)->Dev = dev; - m_UsbDev->m_FreePorts.erase(it); - - return 0; -} - -void Hub::UsbHubReleasePort(XboxDeviceState* dev) { - USBPort * port = dev->Port; - - assert(port != nullptr); - - port->Dev = nullptr; - dev->Port = nullptr; -} - -int Hub::UsbHub_Initfn(XboxDeviceState* dev) { - USBHubPort* port; - USBPortOps* ops; - int i; - - m_UsbDev->USB_CreateSerial(dev, std::string("314159")); - m_UsbDev->USBDesc_SetString(dev, STR_MANUFACTURER, std::string("Cxbx-Reloaded")); - m_UsbDev->USBDesc_SetString(dev, STR_PRODUCT, std::string("Cxbx-Reloaded USB Hub")); - m_UsbDev->USBDesc_Init(dev); - m_HubState->intr = m_UsbDev->USB_GetEP(dev, USB_TOKEN_IN, 1); - - ops = new USBPortOps(); - { - using namespace std::placeholders; - - ops->attach = std::bind(&Hub::UsbHub_Attach, this, _1); - ops->detach = std::bind(&Hub::UsbHub_Detach, this, _1); - ops->child_detach = std::bind(&Hub::UsbHub_ChildDetach, this, _1); - ops->wakeup = std::bind(&Hub::UsbHub_Wakeup, this, _1); - ops->complete = std::bind(&Hub::UsbHub_Complete, this, _1, _2); - } - - for (i = 0; i < NUM_PORTS; i++) { - port = &m_HubState->ports[i]; - m_UsbDev->USB_RegisterPort(&port->port, i, USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL, ops); - m_UsbDev->USB_PortLocation(&port->port, dev->Port, i + 1); - } - UsbHub_HandleReset(); - return 0; -} - -XboxDeviceState* Hub::UsbHub_FindDevice(XboxDeviceState* dev, uint8_t addr) { - USBHubPort * port; - XboxDeviceState * downstream; - - for (int i = 0; i < NUM_PORTS; i++) { - port = &m_HubState->ports[i]; - if (!(port->wPortStatus & PORT_STAT_ENABLE)) { - continue; - } - downstream = m_UsbDev->USB_FindDevice(&port->port, addr); - if (downstream != nullptr) { - return downstream; - } - } - return nullptr; -} - -void Hub::UsbHub_HandleReset() { - USBHubPort* port; - - for (int i = 0; i < NUM_PORTS; i++) { - port = m_HubState->ports + i; - port->wPortStatus = PORT_STAT_POWER; - port->wPortChange = 0; - if (port->port.Dev && port->port.Dev->Attached) { - port->wPortStatus |= PORT_STAT_CONNECTION; - port->wPortChange |= PORT_STAT_C_CONNECTION; - if (port->port.Dev->Speed == USB_SPEED_LOW) { - port->wPortStatus |= PORT_STAT_LOW_SPEED; - } - } - } -} -void Hub::UsbHub_HandleControl(XboxDeviceState* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data) { - int ret; - ret = m_UsbDev->USBDesc_HandleControl(dev, p, request, value, index, length, data); - if (ret >= 0) { - return; - } - - switch (request) { - case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: - { - // clear ep halt and bEndpointAddress of hub is 0x81 - if (value == 0 && index != 0x81) { - goto fail; - } - break; - } - - case GetHubStatus: - { - // From the standard: "This request returns the current hub status and the states that have changed since the previous acknowledgment. - // The first word of data contains wHubStatus. The second word of data contains wHubChange" - // We always report that the local power supply is good and that currently there is no over-power condition - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - p->ActualLength = 4; - break; - } - - case GetPortStatus: - { - // From the standard: "This request returns the current port status and the current value of the port status change bits. - // The first word of data contains wPortStatus. The second word of data contains wPortChange" - unsigned int n = index - 1; - USBHubPort* port; - if (n >= NUM_PORTS) { - goto fail; - } - port = &m_HubState->ports[n]; - log_debug("OHCI Hub: %s GetPortStatus -> Address 0x%X, wIndex %d, wPortStatus %d, wPortChange %d", - __func__, m_HubState->dev.Addr, index, port->wPortStatus, port->wPortChange); - data[0] = port->wPortStatus; - data[1] = port->wPortStatus >> 8; - data[2] = port->wPortChange; - data[3] = port->wPortChange >> 8; - p->ActualLength = 4; - break; - } - - case SetHubFeature: - case ClearHubFeature: - { - if (value != 0 && value != 1) { - goto fail; - } - break; - } - - case SetPortFeature: - { - // From the standard: "This request sets a value reported in the port status. Features that can be set with this request are PORT_RESET, - // PORT_SUSPEND and PORT_POWER; others features are not required to be set by this request" - unsigned int n = index - 1; - USBHubPort* port; - XboxDeviceState* dev; - - log_debug("OHCI Hub: %s SetPortFeature -> Address 0x%X, wIndex %d, Feature %s", - __func__, m_HubState->dev.Addr, index, GetFeatureName(value)); - - if (n >= NUM_PORTS) { - goto fail; - } - port = &m_HubState->ports[n]; - dev = port->port.Dev; - switch (value) { - case PORT_SUSPEND: - { - port->wPortStatus |= PORT_STAT_SUSPEND; - break; - } - - case PORT_RESET: - { - if (dev && dev->Attached) { - m_UsbDev->USB_DeviceReset(dev); - port->wPortChange |= PORT_STAT_C_RESET; - port->wPortStatus |= PORT_STAT_ENABLE; - m_UsbDev->USB_Wakeup(m_HubState->intr); - } - break; - } - - case PORT_POWER: - break; - - default: - goto fail; - } - break; - } - - case ClearPortFeature: - { - // From the standard: "This request resets a value reported in the port status" - unsigned int n = index - 1; - USBHubPort *port; - - log_debug("OHCI Hub: %s ClearPortFeature -> Address 0x%X, wIndex %d, Feature %s", - __func__, m_HubState->dev.Addr, index, GetFeatureName(value)); - - if (n >= NUM_PORTS) { - goto fail; - } - port = &m_HubState->ports[n]; - switch (value) { - case PORT_ENABLE: - { - port->wPortStatus &= ~PORT_STAT_ENABLE; - break; - } - - case PORT_C_ENABLE: - { - port->wPortChange &= ~PORT_STAT_C_ENABLE; - break; - } - - case PORT_SUSPEND: - { - port->wPortStatus &= ~PORT_STAT_SUSPEND; - break; - } - - case PORT_C_SUSPEND: - { - port->wPortChange &= ~PORT_STAT_C_SUSPEND; - break; - } - - case PORT_C_CONNECTION: - { - port->wPortChange &= ~PORT_STAT_C_CONNECTION; - break; - } - - case PORT_C_OVERCURRENT: - { - port->wPortChange &= ~PORT_STAT_C_OVERCURRENT; - break; - } - - case PORT_C_RESET: - { - port->wPortChange &= ~PORT_STAT_C_RESET; - break; - } - - default: - goto fail; - } - break; - } - - case GetHubDescriptor: - { - memcpy(data, HubDescriptor, sizeof(HubDescriptor)); - p->ActualLength = sizeof(HubDescriptor); - break; - } - - default: - fail: - p->Status = USB_RET_STALL; - break; - } -} - -void Hub::UsbHub_HandleData(XboxDeviceState* dev, USBPacket* p) { - switch (p->Pid) { - case USB_TOKEN_IN: - { - if (p->Endpoint->Num == 1) { - USBHubPort* port; - unsigned int status; - uint8_t buf[4]; - int i, n; - status = 0; - for (i = 0; i < NUM_PORTS; i++) { - port = &m_HubState->ports[i]; - if (port->wPortChange) { - status |= (1 << (i + 1)); - } - } - if (status != 0) { - n = (NUM_PORTS + 1 + 7) / 8; - if (p->IoVec.Size == 1) { // FreeBSD workaround - n = 1; - } - else if ((unsigned int)n > p->IoVec.Size) { - p->Status = USB_RET_BABBLE; - return; - } - log_debug("OHCI Hub: %s Address 0x%X, Status %d", __func__, m_HubState->dev.Addr, status); - for (i = 0; i < n; i++) { - buf[i] = status >> (8 * i); - } - m_UsbDev->USB_PacketCopy(p, buf, n); - } - else { - p->Status = USB_RET_NAK; // usb11 11.13.1 - } - } - else { - goto fail; - } - break; - } - - case USB_TOKEN_OUT: - default: - fail: - p->Status = USB_RET_STALL; - break; - } -} - -void Hub::UsbHub_HandleDestroy() { - // Inform upstream that the hub is detached and gone - m_UsbDev->USB_DeviceDetach(&m_HubState->dev); - m_UsbDev->m_FreePorts.push_back(m_HubState->dev.Port); - - for (int i = 0; i < NUM_PORTS; i++) { - if (m_HubState->ports[i].port.Dev) { - // Also destroy attached downstream device - m_HubState->ports[i].port.Dev->klass->handle_destroy(); - } - else { - m_UsbDev->USB_UnregisterPort(&m_HubState->ports[i].port); - } - } - UsbHubReleasePort(&m_HubState->dev); - HubCleanUp(); -} - -void Hub::UsbHub_Attach(USBPort* port1) { - USBHubPort* port = &m_HubState->ports[port1->PortIndex]; - - port->wPortStatus |= PORT_STAT_CONNECTION; - port->wPortChange |= PORT_STAT_C_CONNECTION; - if (port->port.Dev->Speed == USB_SPEED_LOW) { - port->wPortStatus |= PORT_STAT_LOW_SPEED; - } - else { - port->wPortStatus &= ~PORT_STAT_LOW_SPEED; - } - m_UsbDev->USB_Wakeup(m_HubState->intr); -} - -void Hub::UsbHub_Detach(USBPort* port1) { - USBHubPort* port = &m_HubState->ports[port1->PortIndex]; - - m_UsbDev->USB_Wakeup(m_HubState->intr); - - // Let upstream know the device on this port is gone - m_HubState->dev.Port->Operations->child_detach(port1->Dev); - - port->wPortStatus &= ~PORT_STAT_CONNECTION; - port->wPortChange |= PORT_STAT_C_CONNECTION; - if (port->wPortStatus & PORT_STAT_ENABLE) { - port->wPortStatus &= ~PORT_STAT_ENABLE; - port->wPortChange |= PORT_STAT_C_ENABLE; - } - m_UsbDev->USB_Wakeup(m_HubState->intr); -} - -void Hub::UsbHub_ChildDetach(XboxDeviceState* child) { - // Pass along to upstream - m_HubState->dev.Port->Operations->child_detach(child); -} - -void Hub::UsbHub_Wakeup(USBPort* port1) { - USBHubPort* port = &m_HubState->ports[port1->PortIndex]; - - if (port->wPortStatus & PORT_STAT_SUSPEND) { - port->wPortChange |= PORT_STAT_C_SUSPEND; - m_UsbDev->USB_Wakeup(m_HubState->intr); - } -} - -void Hub::UsbHub_Complete(USBPort* port, USBPacket* packet) { - // Just pass it along to upstream - m_HubState->dev.Port->Operations->complete(m_HubState->dev.Port, packet); -} - -std::string Hub::GetFeatureName(int feature) { - std::string str; - - switch (feature) { - case PORT_CONNECTION: - { - str = "connection"; - break; - } - - case PORT_ENABLE: - { - str = "enable"; - break; - } - - case PORT_SUSPEND: - { - str = "suspend"; - break; - } - - case PORT_OVERCURRENT: - { - str = "overcurrent"; - break; - } - - case PORT_RESET: - { - str = "reset"; - break; - } - - case PORT_POWER: - { - str = "power"; - break; - } - - case PORT_LOWSPEED: - { - str = "lowspeed"; - break; - } - - case PORT_C_CONNECTION: - { - str = "change_connection"; - break; - } - - case PORT_C_ENABLE: - { - str = "change_enable"; - break; - } - - case PORT_C_SUSPEND: - { - str = "change_suspend"; - break; - } - - case PORT_C_OVERCURRENT: - { - str = "change_overcurrent"; - break; - } - - case PORT_C_RESET: - { - str = "change_reset"; - break; - } - - default: - str = "?"; - break; - } - - return str; -} - -void Hub::HubCleanUp() { - delete m_pPeripheralFuncStruct; - delete m_HubState->ports[0].port.Operations; - delete m_HubState; - m_pPeripheralFuncStruct = nullptr; - m_HubState = nullptr; -} - -void Hub::HubDestroy() { - while (m_UsbDev->m_HostController->m_bFrameTime) {} - m_UsbDev->m_HostController->m_bFrameTime = true; - m_pPeripheralFuncStruct->handle_destroy(); - m_UsbDev->m_HostController->m_bFrameTime = false; -} - -} diff --git a/modules/core/src/common/strikebox/hw/pci/nv2a.cpp b/modules/core/src/common/strikebox/hw/pci/nv2a.cpp index 67a7b54..b14f6bf 100644 --- a/modules/core/src/common/strikebox/hw/pci/nv2a.cpp +++ b/modules/core/src/common/strikebox/hw/pci/nv2a.cpp @@ -1,70 +1,13 @@ -/* - * Portions of the code are based on XQEMU's Geforce NV2A implementation. - * The original copyright header is included below. - * - * Additional work by Ivan "StrikerX3" Oliveira. - */ -/* - * QEMU Geforce NV2A implementation - * - * Copyright (c) 2012 espes - * Copyright (c) 2015 Jannik Vogel - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ #include "strikebox/hw/pci/nv2a.h" #include "strikebox/log.h" -#include "strikebox/thread.h" - -#include -#include - -#ifdef _MSC_VER -#include -static inline int ffs(int i) { - unsigned long pos; - if (_BitScanForward(&pos, i)) { - return pos + 1; - } - return 0; -} -#endif namespace strikebox { -#define GET_MASK(v, mask) (((v) & (mask)) >> (ffs(mask)-1)) - -#define SET_MASK(v, mask, val) \ - do { \ - (v) &= ~(mask); \ - (v) |= ((val) << (ffs(mask)-1)) & (mask); \ - } while (0) - -static inline uint32_t ldl_le_p(const void *p) { - return *(uint32_t*)p; -} -#define CASE_4(v, step) \ - case (v): \ - case (v)+(step): \ - case (v)+(step) * 2: \ - case (v)+(step) * 3 - NV2ADevice::NV2ADevice(uint8_t *pSystemRAM, uint32_t systemRAMSize, IRQHandler& irqHandler) - : PCIDevice(PCI_HEADER_TYPE_NORMAL, PCI_VENDOR_ID_NVIDIA, 0x02A0, 0xA1, - 0x03, 0x00, 0x00) // VGA-compatible controller + : PCIDevice(PCI_HEADER_TYPE_NORMAL, PCI_VENDOR_ID_NVIDIA, 0x02A0, 0xA1, + 0x03, 0x00, 0x00) // VGA-compatible controller , m_pSystemRAM(pSystemRAM) , m_systemRAMSize(systemRAMSize) , m_irqHandler(irqHandler) @@ -72,20 +15,14 @@ NV2ADevice::NV2ADevice(uint8_t *pSystemRAM, uint32_t systemRAMSize, IRQHandler& } NV2ADevice::~NV2ADevice() { - m_running = false; - - m_PFIFO.cache1.cache_cond.notify_all(); - - m_PFIFO.puller_thread.join(); - m_VblankThread.join(); } // PCI Device functions void NV2ADevice::Init() { - RegisterBAR(0, 0x1000000, PCI_BAR_TYPE_MEMORY); // 0xFD000000 - 0xFDFFFFFF - RegisterBAR(1, 0x8000000, PCI_BAR_TYPE_MEMORY | PCI_BAR_MEMORY_PREFETCHABLE); // 0xF0000000 - 0xF7FFFFFF - RegisterBAR(2, 0x80000, PCI_BAR_TYPE_MEMORY | PCI_BAR_MEMORY_PREFETCHABLE); // 0x0 - 0x7FFFF + RegisterBAR(0, 0x1000000, PCI_BAR_TYPE_MEMORY); // 0xFD000000 - 0xFDFFFFFF + RegisterBAR(1, 0x8000000, PCI_BAR_TYPE_MEMORY | PCI_BAR_MEMORY_PREFETCHABLE); // 0xF0000000 - 0xF7FFFFFF + RegisterBAR(2, 0x80000, PCI_BAR_TYPE_MEMORY | PCI_BAR_MEMORY_PREFETCHABLE); // 0x0 - 0x7FFFF Write8(m_configSpace, PCI_LATENCY_TIMER, 0xf8); @@ -113,2386 +50,27 @@ void NV2ADevice::Init() { Write32(m_configSpace, 0x80, 0x2b16d065); Reset(); - - m_running = true; - - m_VblankThread = std::thread(VBlankThread, this); - - m_MemoryRegions.clear(); - m_MemoryRegions.push_back({ NV_PMC_ADDR, NV_PMC_SIZE, PMCRead, PMCWrite }); - m_MemoryRegions.push_back({ NV_PBUS_ADDR, NV_PBUS_SIZE, PBUSRead, PBUSWrite }); - m_MemoryRegions.push_back({ NV_PFIFO_ADDR, NV_PFIFO_SIZE, PFIFORead, PFIFOWrite }); - m_MemoryRegions.push_back({ NV_PRMA_ADDR, NV_PRMA_SIZE, PRMARead, PRMAWrite }); - m_MemoryRegions.push_back({ NV_PVIDEO_ADDR, NV_PVIDEO_SIZE, PVIDEORead, PVIDEOWrite }); - m_MemoryRegions.push_back({ NV_PTIMER_ADDR, NV_PTIMER_SIZE, PTIMERRead, PTIMERWrite }); - m_MemoryRegions.push_back({ NV_PCOUNTER_ADDR, NV_PCOUNTER_SIZE, PCOUNTERRead, PCOUNTERWrite }); - m_MemoryRegions.push_back({ NV_PVPE_ADDR, NV_PVPE_SIZE, PVPERead, PVPEWrite }); - m_MemoryRegions.push_back({ NV_PTV_ADDR, NV_PTV_SIZE, PTVRead, PTVWrite }); - m_MemoryRegions.push_back({ NV_PRMFB_ADDR, NV_PRMFB_SIZE, PRMFBRead, PRMFBWrite }); - m_MemoryRegions.push_back({ NV_PRMVIO_ADDR, NV_PRMVIO_SIZE, PRMVIORead, PRMVIOWrite }); - m_MemoryRegions.push_back({ NV_PFB_ADDR, NV_PFB_SIZE, PFBRead, PFBWrite }); - m_MemoryRegions.push_back({ NV_PSTRAPS_ADDR, NV_PSTRAPS_SIZE, PSTRAPSRead, PSTRAPSWrite }); - m_MemoryRegions.push_back({ NV_PGRAPH_ADDR, NV_PGRAPH_SIZE, PGRAPHRead, PGRAPHWrite }); - m_MemoryRegions.push_back({ NV_PCRTC_ADDR, NV_PCRTC_SIZE, PCRTCRead, PCRTCWrite }); - m_MemoryRegions.push_back({ NV_PRMCIO_ADDR, NV_PRMCIO_SIZE, PRMCIORead, PRMCIOWrite }); - m_MemoryRegions.push_back({ NV_PRAMDAC_ADDR, NV_PRAMDAC_SIZE, PRAMDACRead, PRAMDACWrite }); - m_MemoryRegions.push_back({ NV_PRMDIO_ADDR, NV_PRMDIO_SIZE, PRMDIORead, PRMDIOWrite }); - m_MemoryRegions.push_back({ NV_PRAMIN_ADDR, NV_PRAMIN_SIZE, PRAMINRead, PRAMINWrite }); - m_MemoryRegions.push_back({ NV_USER_ADDR, NV_USER_SIZE, USERRead, USERWrite }); } void NV2ADevice::Reset() { - // RAMIN is just RAM, so we allocate it as such - if (m_pRAMIN == nullptr) { - m_pRAMIN = (uint8_t*)malloc(NV_PRAMIN_SIZE); - } - memset(m_pRAMIN, 0, NV_PRAMIN_SIZE); - - // VRAM IS System RAM, so we mark it as such - m_VRAM = m_pSystemRAM; - - m_PFIFO.puller_thread = std::thread(PFIFO_Puller_Thread, this); - - m_PCRTC.pendingInterrupts = 0; - m_PCRTC.enabledInterrupts = 0; - - m_PRAMDAC.core_clock_coeff = 0x00011c01; /* 189MHz...? */ - m_PRAMDAC.core_clock_freq = 189000000; - m_PRAMDAC.memory_clock_coeff = 0; - m_PRAMDAC.video_clock_coeff = 0x0003C20D; /* 25182Khz...? */ - - //VGACommonState m_VGAState; -} - -const NV2ABlockInfo* NV2ADevice::FindBlock(uint32_t addr) { - // TODO: use an AVL tree to speed up lookups - for (auto it = m_MemoryRegions.begin(); it != m_MemoryRegions.end(); ++it) { - if (addr >= it->offset && addr < it->offset + it->size) { - return &it[0]; - } - } - - return nullptr; } void NV2ADevice::PCIIORead(int barIndex, uint32_t port, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::IORead: Unexpected I/O read! bar = %d, port = 0x%x, size = %u\n", barIndex, port, size); + log_warning("NV2ADevice::IORead: Unexpected I/O read! bar = %d, port = 0x%x, size = %u\n", barIndex, port, size); *value = 0; } void NV2ADevice::PCIIOWrite(int barIndex, uint32_t port, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::IOWrite: Unexpected I/O write! bar = %d, port = 0x%x, size = %u, value = 0x%x\n", barIndex, port, size, value); + log_warning("NV2ADevice::IOWrite: Unexpected I/O write! bar = %d, port = 0x%x, size = %u, value = 0x%x\n", barIndex, port, size, value); } void NV2ADevice::PCIMMIORead(int barIndex, uint32_t addr, uint32_t *value, uint8_t size) { - //log_spew("NV2ADevice::MMIORead: bar = %d, addr = 0x%x, size = %u\n", barIndex, addr, size); - - if (barIndex == 1) { - switch (size) { - case 1: - *value = m_VRAM[addr]; - return; - case 2: - *value = *(uint16_t*)(&m_VRAM[addr]); - return; - case 4: - *value = *(uint32_t*)(&m_VRAM[addr]); - return; - } - - log_warning("NV2ADevice::MMIORead: Unexpected framebuffer read size! addr = 0x%x, size = %u\n", addr, size); - *value = 0; - return; - } - - auto memoryBlock = FindBlock(addr); - if (memoryBlock != nullptr) { - memoryBlock->read(this, addr - memoryBlock->offset, value, size); - return; - } - - log_warning("NV2ADevice::MMIORead: Unimplemented! bar = %d, addr = 0x%x, size = %u\n", barIndex, addr, size); - *value = 0; + log_spew("NV2ADevice::PCIMMIORead: Unimplemented read! bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); } void NV2ADevice::PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint8_t size) { - //log_spew("NV2ADevice::MMIOWrite: bar = %d, addr = 0x%x, size = %u, value = 0x%x\n", barIndex, addr, size, value); - - if (barIndex == 1) { - switch (size) { - case 1: - m_VRAM[addr] = value; - return; - case 2: - *(uint16_t*)(&m_VRAM[addr]) = value; - return; - case 4: - *(uint32_t*)(&m_VRAM[addr]) = value; - return; - } - - log_warning("NV2ADevice::MMIOWrite: Unimplemented framebuffer write! addr = 0x%x, size = %u, value = 0x%x\n", addr, size, value); - } - - // Currently we only support 32-bit accesses - auto memoryBlock = FindBlock(addr); - if (memoryBlock != nullptr) { - memoryBlock->write(this, addr - memoryBlock->offset, value, size); - return; - } - - log_warning("NV2ADevice::MMIOWrite: Unimplemented! bar = %d, addr = 0x%x, size = %u, value = 0x%x\n", barIndex, addr, size, value); -} - -// ----- NV2A I/O ------------------------------------------------------------- - -void NV2ADevice::PMCRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - switch (addr) { - case NV_PMC_BOOT_0: - // NV2ADevice, A02, Revision 0 - *value = 0x02A000A2; - return; - case NV_PMC_INTR_0: - *value = nv2a->m_PMC.pendingInterrupts; - return; - case NV_PMC_INTR_EN_0: - *value = nv2a->m_PMC.enabledInterrupts; - return; - } - - log_warning("NV2ADevice::PMCRead: Unknown NV2A PMC read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PMCWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - assert(size == 4); - - switch (addr) { - case NV_PMC_INTR_0: - // Only bit 31 is writable - nv2a->m_PMC.pendingInterrupts &= ~NV_PMC_INTR_0_SOFTWARE; - nv2a->m_PMC.pendingInterrupts |= (value & NV_PMC_INTR_0_SOFTWARE); - nv2a->UpdateIRQ(); - break; - case NV_PMC_INTR_EN_0: - nv2a->m_PMC.enabledInterrupts = value; - nv2a->UpdateIRQ(); - break; - default: - log_warning("NV2ADevice::PMCWrite: Unknown NV2A PMC write! addr = 0x%x, size = %u, value = 0x%x\n", addr, size, value); - break; - } -} - -void NV2ADevice::PBUSRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - assert(size == 4); - - switch (addr) { - case NV_PBUS_PCI_NV_0: - *value = PCI_VENDOR_ID_NVIDIA; - return; - - case NV_PBUS_PCI_NV_1: - *value = 1; // NV_PBUS_PCI_NV_1_IO_SPACE_ENABLED - return; - - case NV_PBUS_PCI_NV_2: - *value = (0x02 << 24) | 161; // PCI_CLASS_DISPLAY_3D (0x02) Rev 161 (0xA1) - return; - } - - log_warning("NV2ADevice::PBUSRead: Unknown NV2A PBUS read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; - return; -} - -void NV2ADevice::PBUSWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - switch (addr) { - case NV_PBUS_PCI_NV_1: - nv2a->Write16(nv2a->m_configSpace, PCI_COMMAND, value); - break; - default: - break; - } - - log_warning("NV2ADevice::PBUSWrite: Unknown NV2A PBUS write! addr = 0x%x, size = %u, value = 0x%x\n", addr, size, value); -} - -void NV2ADevice::PFIFORead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - // TODO: Acknowledge the size. - //assert(size == 4); - - switch (addr) { - case NV_PFIFO_RAMHT: - *value = 0x03000100; // = NV_PFIFO_RAMHT_SIZE_4K | NV_PFIFO_RAMHT_BASE_ADDRESS(NumberOfPaddingBytes >> 12) | NV_PFIFO_RAMHT_SEARCH_128 - break; - case NV_PFIFO_RAMFC: - *value = 0x00890110; // = ? | NV_PFIFO_RAMFC_SIZE_2K | ? - break; - case NV_PFIFO_INTR_0: - *value = nv2a->m_PFIFO.pending_interrupts; - break; - case NV_PFIFO_INTR_EN_0: - *value = nv2a->m_PFIFO.enabled_interrupts; - break; - case NV_PFIFO_RUNOUT_STATUS: - *value = NV_PFIFO_RUNOUT_STATUS_LOW_MARK; /* low mark empty */ - break; - case NV_PFIFO_CACHE1_PUSH0: - *value = nv2a->m_PFIFO.cache1.push_enabled; - break; - case NV_PFIFO_CACHE1_PUSH1: - SET_MASK(*value, NV_PFIFO_CACHE1_PUSH1_CHID, nv2a->m_PFIFO.cache1.channel_id); - SET_MASK(*value, NV_PFIFO_CACHE1_PUSH1_MODE, nv2a->m_PFIFO.cache1.mode); - break; - case NV_PFIFO_CACHE1_STATUS: - { - std::lock_guard lk(nv2a->m_PFIFO.cache1.mutex); - - if (nv2a->m_PFIFO.cache1.cache.empty()) { - *value |= NV_PFIFO_CACHE1_STATUS_LOW_MARK; /* low mark empty */ - } - - } break; - case NV_PFIFO_CACHE1_DMA_PUSH: - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS, - nv2a->m_PFIFO.cache1.dma_push_enabled); - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS, - nv2a->m_PFIFO.cache1.dma_push_suspended); - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_PUSH_BUFFER, 1); /* buffer emoty */ - break; - case NV_PFIFO_CACHE1_DMA_STATE: - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE, - nv2a->m_PFIFO.cache1.method_nonincreasing); - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_STATE_METHOD, - nv2a->m_PFIFO.cache1.method >> 2); - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL, - nv2a->m_PFIFO.cache1.subchannel); - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT, - nv2a->m_PFIFO.cache1.method_count); - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_STATE_ERROR, - nv2a->m_PFIFO.cache1.error); - break; - case NV_PFIFO_CACHE1_DMA_INSTANCE: - SET_MASK(*value, NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS, - nv2a->m_PFIFO.cache1.dma_instance >> 4); - break; - case NV_PFIFO_CACHE1_DMA_PUT: - *value = nv2a->m_User.channel_control[nv2a->m_PFIFO.cache1.channel_id].dma_put; - break; - case NV_PFIFO_CACHE1_DMA_GET: - *value = nv2a->m_User.channel_control[nv2a->m_PFIFO.cache1.channel_id].dma_get; - break; - case NV_PFIFO_CACHE1_DMA_SUBROUTINE: - *value = nv2a->m_PFIFO.cache1.subroutine_return - | nv2a->m_PFIFO.cache1.subroutine_active; - break; - case NV_PFIFO_CACHE1_PULL0: - { - std::lock_guard lk(nv2a->m_PFIFO.cache1.mutex); - *value = nv2a->m_PFIFO.cache1.pull_enabled; - } break; - case NV_PFIFO_CACHE1_ENGINE: - { - std::lock_guard lk(nv2a->m_PFIFO.cache1.mutex); - for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) { - *value |= nv2a->m_PFIFO.cache1.bound_engines[i] << (i * 2); - } - - } break; - case NV_PFIFO_CACHE1_DMA_DCOUNT: - *value = nv2a->m_PFIFO.cache1.dcount; - break; - case NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW: - *value = nv2a->m_PFIFO.cache1.get_jmp_shadow; - break; - case NV_PFIFO_CACHE1_DMA_RSVD_SHADOW: - *value = nv2a->m_PFIFO.cache1.rsvd_shadow; - break; - case NV_PFIFO_CACHE1_DMA_DATA_SHADOW: - *value = nv2a->m_PFIFO.cache1.data_shadow; - break; - default: - *value = nv2a->m_PFIFO.regs[addr]; - break; - } -} - -void NV2ADevice::PFIFOWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - assert(size == 4); - - switch (addr) { - case NV_PFIFO_INTR_0: - nv2a->m_PFIFO.pending_interrupts &= ~value; - nv2a->UpdateIRQ(); - break; - case NV_PFIFO_INTR_EN_0: - nv2a->m_PFIFO.enabled_interrupts = value; - nv2a->UpdateIRQ(); - break; - case NV_PFIFO_CACHE1_PUSH0: - nv2a->m_PFIFO.cache1.push_enabled = value & NV_PFIFO_CACHE1_PUSH0_ACCESS; - break; - case NV_PFIFO_CACHE1_PUSH1: - nv2a->m_PFIFO.cache1.channel_id = GET_MASK(value, NV_PFIFO_CACHE1_PUSH1_CHID); - nv2a->m_PFIFO.cache1.mode = (FifoMode)GET_MASK(value, NV_PFIFO_CACHE1_PUSH1_MODE); - assert(nv2a->m_PFIFO.cache1.channel_id < NV2A_NUM_CHANNELS); - break; - case NV_PFIFO_CACHE1_DMA_PUSH: - nv2a->m_PFIFO.cache1.dma_push_enabled = GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS); - if (nv2a->m_PFIFO.cache1.dma_push_suspended && !GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS)) { - nv2a->m_PFIFO.cache1.dma_push_suspended = false; - nv2a->pfifo_run_pusher(); - } - nv2a->m_PFIFO.cache1.dma_push_suspended = GET_MASK(value, NV_PFIFO_CACHE1_DMA_PUSH_STATUS); - break; - case NV_PFIFO_CACHE1_DMA_STATE: - nv2a->m_PFIFO.cache1.method_nonincreasing = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_TYPE); - nv2a->m_PFIFO.cache1.method = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD) << 2; - nv2a->m_PFIFO.cache1.subchannel = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_SUBCHANNEL); - nv2a->m_PFIFO.cache1.method_count = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_METHOD_COUNT); - nv2a->m_PFIFO.cache1.error = GET_MASK(value, NV_PFIFO_CACHE1_DMA_STATE_ERROR); - break; - case NV_PFIFO_CACHE1_DMA_INSTANCE: - nv2a->m_PFIFO.cache1.dma_instance = GET_MASK(value, NV_PFIFO_CACHE1_DMA_INSTANCE_ADDRESS) << 4; - break; - case NV_PFIFO_CACHE1_DMA_PUT: - nv2a->m_User.channel_control[nv2a->m_PFIFO.cache1.channel_id].dma_put = value; - break; - case NV_PFIFO_CACHE1_DMA_GET: - nv2a->m_User.channel_control[nv2a->m_PFIFO.cache1.channel_id].dma_get = value; - break; - case NV_PFIFO_CACHE1_DMA_SUBROUTINE: - nv2a->m_PFIFO.cache1.subroutine_return = (value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_RETURN_OFFSET); - nv2a->m_PFIFO.cache1.subroutine_active = (value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE); - break; - case NV_PFIFO_CACHE1_PULL0: - { - std::lock_guard lk(nv2a->m_PFIFO.cache1.mutex); - - if ((value & NV_PFIFO_CACHE1_PULL0_ACCESS) - && !nv2a->m_PFIFO.cache1.pull_enabled) { - nv2a->m_PFIFO.cache1.pull_enabled = true; - - /* the puller thread should wake up */ - nv2a->m_PFIFO.cache1.cache_cond.notify_all(); - } - else if (!(value & NV_PFIFO_CACHE1_PULL0_ACCESS) - && nv2a->m_PFIFO.cache1.pull_enabled) { - nv2a->m_PFIFO.cache1.pull_enabled = false; - } - } break; - case NV_PFIFO_CACHE1_ENGINE: - { - std::lock_guard lk(nv2a->m_PFIFO.cache1.mutex); - - for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) { - nv2a->m_PFIFO.cache1.bound_engines[i] = (FIFOEngine)((value >> (i * 2)) & 3); - } - - } break; - case NV_PFIFO_CACHE1_DMA_DCOUNT: - nv2a->m_PFIFO.cache1.dcount = (value & NV_PFIFO_CACHE1_DMA_DCOUNT_VALUE); - break; - case NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW: - nv2a->m_PFIFO.cache1.get_jmp_shadow = (value & NV_PFIFO_CACHE1_DMA_GET_JMP_SHADOW_OFFSET); - break; - case NV_PFIFO_CACHE1_DMA_RSVD_SHADOW: - nv2a->m_PFIFO.cache1.rsvd_shadow = value; - break; - case NV_PFIFO_CACHE1_DMA_DATA_SHADOW: - nv2a->m_PFIFO.cache1.data_shadow = value; - break; - default: - nv2a->m_PFIFO.regs[addr] = value; - break; - } -} - -void NV2ADevice::PRMARead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PRMARead: Unknown NV2A PRMA read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PRMAWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PRMAWrite: Unknown NV2A PRMA write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PVIDEORead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - switch (addr) { - case NV_PVIDEO_STOP: - *value = 0; - break; - - default: - *value = nv2a->m_PVIDEO.regs[addr]; - break; - } -} - -void NV2ADevice::PVIDEOWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - switch (addr) { - case NV_PVIDEO_BUFFER: - nv2a->m_PVIDEO.regs[addr] = value; - break; - - case NV_PVIDEO_STOP: - nv2a->m_PVIDEO.regs[NV_PVIDEO_BUFFER] = 0; - break; - - default: - nv2a->m_PVIDEO.regs[addr] = addr; - } -} - -static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) { - union { - uint64_t ll; - struct { - uint32_t low, high; - } l; - } u, res; - uint64_t rl, rh; - - u.ll = a; - rl = (uint64_t)u.l.low * (uint64_t)b; - rh = (uint64_t)u.l.high * (uint64_t)b; - rh += (rl >> 32); - res.l.high = rh / c; - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} - -uint32_t NV2ADevice::ptimer_get_clock() { - // Get time in nanoseconds - long int time = static_cast(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); - return muldiv64(time, m_PRAMDAC.core_clock_freq * m_PTIMER.numerator, CLOCKS_PER_SEC * m_PTIMER.denominator); -} - -void NV2ADevice::PTIMERRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - switch (addr) { - case NV_PTIMER_INTR_0: - *value = nv2a->m_PTIMER.pending_interrupts; - break; - case NV_PTIMER_INTR_EN_0: - *value = nv2a->m_PTIMER.enabled_interrupts; - break; - case NV_PTIMER_NUMERATOR: - *value = nv2a->m_PTIMER.numerator; - break; - case NV_PTIMER_DENOMINATOR: - *value = nv2a->m_PTIMER.denominator; - break; - case NV_PTIMER_TIME_0: - *value = (nv2a->ptimer_get_clock() & 0x7ffffff) << 5; - break; - case NV_PTIMER_TIME_1: - *value = (nv2a->ptimer_get_clock() >> 27) & 0x1fffffff; - break; - default: - *value = 0; - break; - } -} - -void NV2ADevice::PTIMERWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - switch (addr) { - case NV_PTIMER_INTR_0: - nv2a->m_PTIMER.pending_interrupts &= ~value; - nv2a->UpdateIRQ(); - break; - case NV_PTIMER_INTR_EN_0: - nv2a->m_PTIMER.enabled_interrupts = value; - nv2a->UpdateIRQ(); - break; - case NV_PTIMER_DENOMINATOR: - nv2a->m_PTIMER.denominator = value; - break; - case NV_PTIMER_NUMERATOR: - nv2a->m_PTIMER.numerator = value; - break; - case NV_PTIMER_ALARM_0: - nv2a->m_PTIMER.alarm_time = value; - break; - default: - break; - } -} - -void NV2ADevice::PCOUNTERRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PCOUNTERRead: Unknown NV2A PCOUNTER read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PCOUNTERWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PCOUNTERWrite: Unknown NV2A PCOUNTER write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PVPERead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PVPERead: Unknown NV2A PVPE read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PVPEWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PVPEWrite: Unknown NV2A PVPE write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PTVRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PTVRead: Unknown NV2A PTV read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PTVWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PTVWrite: Unknown NV2A PTV write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PRMFBRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PRMFBRead: Unknown NV2A PRMFB read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PRMFBWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PRMFBWrite: Unknown NV2A PRMFB write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PRMVIORead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PRMVIORead: Unknown NV2A PRMVIO read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PRMVIOWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PRMVIOWrite: Unknown NV2A PRMVIO write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PFBRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - assert(size == 4); - - switch (addr) { - case NV_PFB_CFG0: - *value = 3; // 3 memory partitions - break; - case NV_PFB_CSTATUS: - *value = nv2a->m_systemRAMSize; - break; - case NV_PFB_WBC: - *value = 0; - break; - default: - *value = nv2a->m_PFB.registers[addr]; - break; - } -} - -void NV2ADevice::PFBWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - assert(size == 4); - nv2a->m_PFB.registers[addr] = value; -} - -void NV2ADevice::PSTRAPSRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PSTRAPSRead: Unknown NV2A PSTRAPS read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PSTRAPSWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PSTRAPSWrite: Unknown NV2A PSTRAPS write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PGRAPHRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - assert(size == 4); - - std::lock_guard lk(nv2a->m_PGRAPH.mutex); - - switch (addr) { - case NV_PGRAPH_INTR: - *value = nv2a->m_PGRAPH.pending_interrupts; - break; - - case NV_PGRAPH_INTR_EN: - *value = nv2a->m_PGRAPH.enabled_interrupts; - break; - - case NV_PGRAPH_NSOURCE: - *value = nv2a->m_PGRAPH.notify_source; - break; - - case NV_PGRAPH_CTX_USER: - SET_MASK(*value, NV_PGRAPH_CTX_USER_CHANNEL_3D, nv2a->m_PGRAPH.context[nv2a->m_PGRAPH.channel_id].channel_3d); - SET_MASK(*value, NV_PGRAPH_CTX_USER_CHANNEL_3D_VALID, 1); - SET_MASK(*value, NV_PGRAPH_CTX_USER_SUBCH, nv2a->m_PGRAPH.context[nv2a->m_PGRAPH.channel_id].subchannel << 13); - SET_MASK(*value, NV_PGRAPH_CTX_USER_CHID, nv2a->m_PGRAPH.channel_id); - break; - - case NV_PGRAPH_TRAPPED_ADDR: - SET_MASK(*value, NV_PGRAPH_TRAPPED_ADDR_CHID, nv2a->m_PGRAPH.trapped_channel_id); - SET_MASK(*value, NV_PGRAPH_TRAPPED_ADDR_SUBCH, nv2a->m_PGRAPH.trapped_subchannel); - SET_MASK(*value, NV_PGRAPH_TRAPPED_ADDR_MTHD, nv2a->m_PGRAPH.trapped_method); - break; - - case NV_PGRAPH_TRAPPED_DATA_LOW: - *value = nv2a->m_PGRAPH.trapped_data[0]; - break; - - case NV_PGRAPH_FIFO: - SET_MASK(*value, NV_PGRAPH_FIFO_ACCESS, nv2a->m_PGRAPH.fifo_access); - break; - - case NV_PGRAPH_CHANNEL_CTX_TABLE: - *value = nv2a->m_PGRAPH.context_table >> 4; - break; - - case NV_PGRAPH_CHANNEL_CTX_POINTER: - *value = nv2a->m_PGRAPH.context_address >> 4; - break; - - default: - *value = nv2a->m_PGRAPH.regs[addr]; - break; - } -} - -void NV2ADevice::PGRAPHWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - std::lock_guard lk(nv2a->m_PGRAPH.mutex); - - switch (addr) { - case NV_PGRAPH_INTR: - nv2a->m_PGRAPH.pending_interrupts &= ~value; - nv2a->m_PGRAPH.interrupt_cond.notify_all(); - break; - case NV_PGRAPH_INTR_EN: - nv2a->m_PGRAPH.enabled_interrupts = value; - break; - case NV_PGRAPH_CTX_CONTROL: - nv2a->m_PGRAPH.channel_valid = (value & NV_PGRAPH_CTX_CONTROL_CHID); - break; - case NV_PGRAPH_CTX_USER: - nv2a->pgraph_set_context_user(value); - break; - case NV_PGRAPH_INCREMENT: - if (value & NV_PGRAPH_INCREMENT_READ_3D) { - SET_MASK(nv2a->m_PGRAPH.regs[NV_PGRAPH_SURFACE], - NV_PGRAPH_SURFACE_READ_3D, - (GET_MASK(nv2a->m_PGRAPH.regs[NV_PGRAPH_SURFACE], - NV_PGRAPH_SURFACE_READ_3D) + 1) - % GET_MASK(nv2a->m_PGRAPH.regs[NV_PGRAPH_SURFACE], - NV_PGRAPH_SURFACE_MODULO_3D)); - - nv2a->m_PGRAPH.flip_3d.notify_all(); - } - break; - case NV_PGRAPH_FIFO: - nv2a->m_PGRAPH.fifo_access = GET_MASK(value, NV_PGRAPH_FIFO_ACCESS); - nv2a->m_PGRAPH.fifo_access_cond.notify_all(); - break; - case NV_PGRAPH_CHANNEL_CTX_TABLE: - nv2a->m_PGRAPH.context_table = (value & NV_PGRAPH_CHANNEL_CTX_TABLE_INST) << 4; - break; - case NV_PGRAPH_CHANNEL_CTX_POINTER: - nv2a->m_PGRAPH.context_address = - (value & NV_PGRAPH_CHANNEL_CTX_POINTER_INST) << 4; - break; - case NV_PGRAPH_CHANNEL_CTX_TRIGGER: - if (value & NV_PGRAPH_CHANNEL_CTX_TRIGGER_READ_IN) { - log_debug("PGRAPH: read channel %d context from %0x08X\n", - nv2a->m_PGRAPH.channel_id, nv2a->m_PGRAPH.context_address); - - uint8_t *context_ptr = (uint8_t*)(nv2a->m_pRAMIN + nv2a->m_PGRAPH.context_address); - uint32_t context_user = ldl_le_p((uint32_t*)context_ptr); - - log_debug(" - CTX_USER = 0x%x\n", context_user); - - //pgraph_set_context_user - nv2a->m_PGRAPH.channel_id = (context_user & NV_PGRAPH_CTX_USER_CHID) >> 24; - nv2a->m_PGRAPH.context[nv2a->m_PGRAPH.channel_id].channel_3d = GET_MASK(context_user, NV_PGRAPH_CTX_USER_CHANNEL_3D); - nv2a->m_PGRAPH.context[nv2a->m_PGRAPH.channel_id].subchannel = GET_MASK(context_user, NV_PGRAPH_CTX_USER_SUBCH); - - } - if (value & NV_PGRAPH_CHANNEL_CTX_TRIGGER_WRITE_OUT) { - /* do stuff ... */ - } - - break; - default: - nv2a->m_PGRAPH.regs[addr] = value; - break; - } -} - -void NV2ADevice::PCRTCRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - switch (addr) { - case NV_PCRTC_INTR_0: - *value = nv2a->m_PCRTC.pendingInterrupts; - break; - case NV_PCRTC_INTR_EN_0: - *value = nv2a->m_PCRTC.enabledInterrupts; - break; - case NV_PCRTC_START: - *value = nv2a->m_PCRTC.start; - break; - default: - *value = 0; - break; - } -} - -void NV2ADevice::PCRTCWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - switch (addr) { - case NV_PCRTC_INTR_0: - nv2a->m_PCRTC.pendingInterrupts &= ~value; - nv2a->UpdateIRQ(); - break; - case NV_PCRTC_INTR_EN_0: - nv2a->m_PCRTC.enabledInterrupts = value; - nv2a->UpdateIRQ(); - break; - case NV_PCRTC_START: - nv2a->m_PCRTC.start = value &= 0x07FFFFFF; - break; - default: - nv2a->m_PCRTC.regs[addr] = value; - break; - } - -} - -void NV2ADevice::PRMCIORead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - switch (addr) { - case VGA_CRT_IM: - case VGA_CRT_IC: - *value = nv2a->m_PRMCIO.cr_index; - break; - - case VGA_IS1_RC: - case VGA_IS1_RM: - // Toggle the retrace bit to fool polling. QEMU does the same. - *value = nv2a->m_VGAState.st01; - nv2a->m_VGAState.st01 ^= 1 << 3; - break; - - case VGA_CRT_DM: - case VGA_CRT_DC: - *value = nv2a->m_PRMCIO.cr[nv2a->m_PRMCIO.cr_index]; - - log_debug("vga: read CR%x = 0x%02x\n", nv2a->m_PRMCIO.cr_index, *value); - break; - default: - log_warning("NV2ADevice::PRMCIORead: Unknown NV2A PRMCIO read! addr = 0x%x, size = %u\n", addr, size); - break; - } -} - -void NV2ADevice::PRMCIOWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - switch (addr) { - case VGA_CRT_IM: - case VGA_CRT_IC: - nv2a->m_PRMCIO.cr_index = value; - break; - case VGA_CRT_DM: - case VGA_CRT_DC: - log_debug("vga: write CR%x = 0x%02x\n", nv2a->m_PRMCIO.cr_index, value); - - /* handle CR0-7 protection */ - if ((nv2a->m_PRMCIO.cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) && - nv2a->m_PRMCIO.cr_index <= VGA_CRTC_OVERFLOW) { - /* can always write bit 4 of CR7 */ - if (nv2a->m_PRMCIO.cr_index == VGA_CRTC_OVERFLOW) { - nv2a->m_PRMCIO.cr[VGA_CRTC_OVERFLOW] = (nv2a->m_PRMCIO.cr[VGA_CRTC_OVERFLOW] & ~0x10) | - (value & 0x10); - log_debug("TODO: vbe_update_vgaregs\n"); - //vbe_update_vgaregs(); - } - return; - } - - nv2a->m_PRMCIO.cr[nv2a->m_PRMCIO.cr_index] = value; - log_debug("TODO: vbe_update_vgaregs\n"); - //vbe_update_vgaregs(); - - switch (nv2a->m_PRMCIO.cr_index) { - case VGA_CRTC_H_TOTAL: - case VGA_CRTC_H_SYNC_START: - case VGA_CRTC_H_SYNC_END: - case VGA_CRTC_V_TOTAL: - case VGA_CRTC_OVERFLOW: - case VGA_CRTC_V_SYNC_END: - case VGA_CRTC_MODE: - // TODO: s->update_retrace_info(s); - log_debug("TODO: update_retrace_info\n"); - break; - } - break; - default: - log_warning("NV2ADevice::PRMCIOWrite: Unknown NV2A PRMCIO write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); - break; - } -} - -void NV2ADevice::PRAMDACRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - switch (addr) { - case NV_PRAMDAC_NVPLL_COEFF: - *value = nv2a->m_PRAMDAC.core_clock_coeff; - break; - case NV_PRAMDAC_MPLL_COEFF: - *value = nv2a->m_PRAMDAC.memory_clock_coeff; - break; - case NV_PRAMDAC_VPLL_COEFF: - *value = nv2a->m_PRAMDAC.video_clock_coeff; - break; - case NV_PRAMDAC_PLL_TEST_COUNTER: - /* emulated PLLs locked instantly? */ - *value = NV_PRAMDAC_PLL_TEST_COUNTER_VPLL2_LOCK - | NV_PRAMDAC_PLL_TEST_COUNTER_NVPLL_LOCK - | NV_PRAMDAC_PLL_TEST_COUNTER_MPLL_LOCK - | NV_PRAMDAC_PLL_TEST_COUNTER_VPLL_LOCK; - break; - default: - log_warning("NV2ADevice::PRAMDACRead: Unknown NV2A PRAMDAC read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; - break; - } -} - -void NV2ADevice::PRAMDACWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - switch (addr) { - case NV_PRAMDAC_NVPLL_COEFF: - uint32_t m, n, p; - nv2a->m_PRAMDAC.core_clock_coeff = value; - - m = value & NV_PRAMDAC_NVPLL_COEFF_MDIV; - n = (value & NV_PRAMDAC_NVPLL_COEFF_NDIV) >> 8; - p = (value & NV_PRAMDAC_NVPLL_COEFF_PDIV) >> 16; - - if (m == 0) { - nv2a->m_PRAMDAC.core_clock_freq = 0; - } - else { - nv2a->m_PRAMDAC.core_clock_freq = (NV2A_CRYSTAL_FREQ * n) / (1 << p) / m; - } - - break; - case NV_PRAMDAC_MPLL_COEFF: - nv2a->m_PRAMDAC.memory_clock_coeff = value; - break; - case NV_PRAMDAC_VPLL_COEFF: - nv2a->m_PRAMDAC.video_clock_coeff = value; - break; - - default: - log_warning("NV2ADevice::PRAMDACWrite: Unknown NV2A PRAMDAC write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); - break; - } -} - -void NV2ADevice::PRMDIORead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - log_warning("NV2ADevice::PRMDIORead: Unknown NV2A PRMDIO read! addr = 0x%x, size = %u\n", addr, size); - *value = 0; -} - -void NV2ADevice::PRMDIOWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - log_warning("NV2ADevice::PRMDIOWrite: Unknown NV2A PRMDIO write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); -} - -void NV2ADevice::PRAMINRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - void* ptr = (uint8_t*)nv2a->m_pRAMIN + addr; - - switch (size) { - case 1: - *value = *((uint8_t*)ptr); - break; - case 2: - *value = *((uint16_t*)ptr); - break; - case 4: - *value = *((uint32_t*)ptr); - break; - default: - *value = 0; - break; - } -} - -void NV2ADevice::PRAMINWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - void* ptr = (uint8_t*)nv2a->m_pRAMIN + addr; - - switch (size) { - case 1: - *((uint8_t*)ptr) = value; - break; - case 2: - *((uint16_t*)ptr) = value; - break; - case 4: - *((uint32_t*)ptr) = value; - break; - } -} - -void NV2ADevice::USERRead(NV2ADevice *nv2a, uint32_t addr, uint32_t *value, uint8_t size) { - assert(size == 4); - - unsigned int channel_id = addr >> 16; - assert(channel_id < NV2A_NUM_CHANNELS); - - ChannelControl *control = &nv2a->m_User.channel_control[channel_id]; - uint32_t channel_modes = nv2a->m_PFIFO.regs[NV_PFIFO_MODE]; - - /* PIO Mode */ - if (!(channel_modes & (1 << channel_id))) { - assert(false); - } - - /* DMA Mode */ - addr &= 0xFFFF; - switch (addr) { - case NV_USER_DMA_PUT: - *value = control->dma_put; - break; - case NV_USER_DMA_GET: - *value = control->dma_get; - break; - case NV_USER_REF: - *value = control->ref; - break; - default: - log_warning("NV2ADevice::USERRead: Unknown NV2A USER read! addr = 0x%x, size = %u\n", addr, size); - break; - } -} - -void NV2ADevice::USERWrite(NV2ADevice *nv2a, uint32_t addr, uint32_t value, uint8_t size) { - assert(size == 4); - - unsigned int channel_id = addr >> 16; - assert(channel_id < NV2A_NUM_CHANNELS); - - ChannelControl *control = &nv2a->m_User.channel_control[channel_id]; - - uint32_t channel_modes = nv2a->m_PFIFO.regs[NV_PFIFO_MODE]; - - if (channel_modes & (1 << channel_id)) { - /* DMA Mode */ - switch (addr & 0xFFFF) { - case NV_USER_DMA_PUT: - control->dma_put = value; - - if (nv2a->m_PFIFO.cache1.push_enabled) { - nv2a->pfifo_run_pusher(); - } - break; - case NV_USER_DMA_GET: - control->dma_get = value; - break; - case NV_USER_REF: - control->ref = value; - break; - default: - log_warning("NV2ADevice::USERWrite: Unknown NV2A USER write! addr = 0x%x, size: %d, value: 0x%x\n", addr, size, value); - break; - } - } - else { - /* PIO Mode */ - assert(false); - } -} - -// ----- Utility functions ---------------------------------------------------- - -uint32_t NV2ADevice::ramht_hash(uint32_t handle) { - unsigned int ramht_size = 1 << (GET_MASK(m_PFIFO.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE) + 12); - - /* XXX: Think this is different to what nouveau calculates... */ - unsigned int bits = ffs(ramht_size) - 2; - - uint32_t hash = 0; - while (handle) { - hash ^= (handle & ((1 << bits) - 1)); - handle >>= bits; - } - hash ^= m_PFIFO.cache1.channel_id << (bits - 4); - - return hash; -} - -RAMHTEntry NV2ADevice::ramht_lookup(uint32_t handle) { - unsigned int ramht_size = 1 << (GET_MASK(m_PFIFO.regs[NV_PFIFO_RAMHT], NV_PFIFO_RAMHT_SIZE) + 12); - - uint32_t hash = ramht_hash(handle); - assert(hash * 8 < ramht_size); - - uint32_t ramht_address = - GET_MASK(m_PFIFO.regs[NV_PFIFO_RAMHT], - NV_PFIFO_RAMHT_BASE_ADDRESS) << 12; - - uint8_t *entry_ptr = (uint8_t*)(m_pRAMIN + ramht_address + hash * 8); - - uint32_t entry_handle = ldl_le_p((uint32_t*)entry_ptr); - uint32_t entry_context = ldl_le_p((uint32_t*)(entry_ptr + 4)); - - RAMHTEntry entry; - entry.handle = entry_handle; - entry.instance = (entry_context & NV_RAMHT_INSTANCE) << 4; - entry.engine = (FIFOEngine)((entry_context & NV_RAMHT_ENGINE) >> 16); - entry.channel_id = (entry_context & NV_RAMHT_CHID) >> 24; - entry.valid = entry_context & NV_RAMHT_STATUS; - - return entry; -} - -void NV2ADevice::pgraph_set_context_user(uint32_t value) { - m_PGRAPH.channel_id = (value & NV_PGRAPH_CTX_USER_CHID) >> 24; - m_PGRAPH.context[m_PGRAPH.channel_id].channel_3d = GET_MASK(value, NV_PGRAPH_CTX_USER_CHANNEL_3D); - m_PGRAPH.context[m_PGRAPH.channel_id].subchannel = GET_MASK(value, NV_PGRAPH_CTX_USER_SUBCH); -} - -void NV2ADevice::pgraph_context_switch(unsigned int channel_id) { - bool valid = false; - - // Scope the lock so that it gets unlocked at end of this block - { - std::lock_guard lk(m_PGRAPH.mutex); - - valid = m_PGRAPH.channel_valid && m_PGRAPH.channel_id == channel_id; - if (!valid) { - m_PGRAPH.trapped_channel_id = channel_id; - } - } - - if (!valid) { - log_debug("puller needs to switch to ch %d\n", channel_id); - - //qemu_mutex_lock_iothread(); - m_PGRAPH.pending_interrupts |= NV_PGRAPH_INTR_CONTEXT_SWITCH; - UpdateIRQ(); - - std::unique_lock lk(m_PGRAPH.mutex); - //qemu_mutex_unlock_iothread(); - - while (m_PGRAPH.pending_interrupts & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - m_PGRAPH.interrupt_cond.wait(lk); - } - } -} - -void NV2ADevice::pgraph_wait_fifo_access() { - std::unique_lock lk(m_PGRAPH.mutex); - - while (!m_PGRAPH.fifo_access) { - m_PGRAPH.fifo_access_cond.wait(lk); - } -} - -void NV2ADevice::load_graphics_object(uint32_t instance_address, GraphicsObject *obj) { - uint8_t *obj_ptr; - uint32_t switch1; - //uint32_t switch2; - //uint32_t switch3; - - assert(instance_address < NV_PRAMIN_SIZE); - obj_ptr = (uint8_t*)(m_pRAMIN + instance_address); - - switch1 = ldl_le_p((uint32_t*)obj_ptr); - //switch2 = ldl_le_p((uint32_t*)(obj_ptr + 4)); - //switch3 = ldl_le_p((uint32_t*)(obj_ptr + 8)); - - obj->graphics_class = switch1 & NV_PGRAPH_CTX_SWITCH1_GRCLASS; - - /* init graphics object */ - switch (obj->graphics_class) { - case NV_KELVIN_PRIMITIVE: - // kelvin->vertex_attributes[NV2A_VERTEX_ATTR_DIFFUSE].inline_value = 0xFFFFFFF; - break; - default: - break; - } -} - -GraphicsObject* NV2ADevice::lookup_graphics_object(uint32_t instance_address) { - int i; - for (i = 0; ivram)); - *len = dma.limit; - return (void*)(m_VRAM + dma.address); -} - -bool NV2ADevice::pgraph_color_write_enabled() { - return m_PGRAPH.regs[NV_PGRAPH_CONTROL_0] & ( - NV_PGRAPH_CONTROL_0_ALPHA_WRITE_ENABLE - | NV_PGRAPH_CONTROL_0_RED_WRITE_ENABLE - | NV_PGRAPH_CONTROL_0_GREEN_WRITE_ENABLE - | NV_PGRAPH_CONTROL_0_BLUE_WRITE_ENABLE); -} - -bool NV2ADevice::pgraph_zeta_write_enabled() { - return m_PGRAPH.regs[NV_PGRAPH_CONTROL_0] & ( - NV_PGRAPH_CONTROL_0_ZWRITEENABLE - | NV_PGRAPH_CONTROL_0_STENCIL_WRITE_ENABLE); -} - -unsigned int NV2ADevice::kelvin_map_stencil_op(uint32_t parameter) { - unsigned int op; - switch (parameter) { - case NV097_SET_STENCIL_OP_V_KEEP: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_KEEP; break; - case NV097_SET_STENCIL_OP_V_ZERO: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_ZERO; break; - case NV097_SET_STENCIL_OP_V_REPLACE: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_REPLACE; break; - case NV097_SET_STENCIL_OP_V_INCRSAT: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INCRSAT; break; - case NV097_SET_STENCIL_OP_V_DECRSAT: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_DECRSAT; break; - case NV097_SET_STENCIL_OP_V_INVERT: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INVERT; break; - case NV097_SET_STENCIL_OP_V_INCR: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INCR; break; - case NV097_SET_STENCIL_OP_V_DECR: - op = NV_PGRAPH_CONTROL_2_STENCIL_OP_V_DECR; break; - default: - assert(false); - break; - } - return op; -} - -unsigned int NV2ADevice::kelvin_map_polygon_mode(uint32_t parameter) { - unsigned int mode; - switch (parameter) { - case NV097_SET_FRONT_POLYGON_MODE_V_POINT: - mode = NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_POINT; break; - case NV097_SET_FRONT_POLYGON_MODE_V_LINE: - mode = NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_LINE; break; - case NV097_SET_FRONT_POLYGON_MODE_V_FILL: - mode = NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_FILL; break; - default: - assert(false); - break; - } - return mode; -} - -unsigned int NV2ADevice::kelvin_map_texgen(uint32_t parameter, unsigned int channel) { - assert(channel < 4); - unsigned int texgen; - switch (parameter) { - case NV097_SET_TEXGEN_S_DISABLE: - texgen = NV_PGRAPH_CSV1_A_T0_S_DISABLE; break; - case NV097_SET_TEXGEN_S_EYE_LINEAR: - texgen = NV_PGRAPH_CSV1_A_T0_S_EYE_LINEAR; break; - case NV097_SET_TEXGEN_S_OBJECT_LINEAR: - texgen = NV_PGRAPH_CSV1_A_T0_S_OBJECT_LINEAR; break; - case NV097_SET_TEXGEN_S_SPHERE_MAP: - assert(channel < 2); - texgen = NV_PGRAPH_CSV1_A_T0_S_SPHERE_MAP; break; - case NV097_SET_TEXGEN_S_REFLECTION_MAP: - assert(channel < 3); - texgen = NV_PGRAPH_CSV1_A_T0_S_REFLECTION_MAP; break; - case NV097_SET_TEXGEN_S_NORMAL_MAP: - assert(channel < 3); - texgen = NV_PGRAPH_CSV1_A_T0_S_NORMAL_MAP; break; - default: - assert(false); - break; - } - return texgen; -} - -void NV2ADevice::pgraph_method_log(unsigned int subchannel, unsigned int graphics_class, unsigned int method, uint32_t parameter) { - static unsigned int last = 0; - static unsigned int count = 0; - - if (last == 0x1800 && method != last) { - log_debug("pgraph method (%d) 0x%08X * %d", subchannel, last, count); - } - if (method != 0x1800) { - /*const char* method_name = NULL; - unsigned int nmethod = 0; - switch (graphics_class) { - case NV_KELVIN_PRIMITIVE: - nmethod = method | (0x5c << 16); - break; - case NV_CONTEXT_SURFACES_2D: - nmethod = method | (0x6d << 16); - break; - default: - break; - } - - if (nmethod != 0 && nmethod < ARRAY_SIZE(nv2a_method_names)) { - method_name = nv2a_method_names[nmethod]; - } - if (method_name) { - log_debug("pgraph method (%d): %s (0x%x)\n", - subchannel, method_name, parameter); - } - else { - */ - log_debug("pgraph method (%d): 0x%x -> 0x%04x (0x%x)\n", - subchannel, graphics_class, method, parameter); - //} - - } - if (method == last) { count++; } - else { count = 0; } - last = method; -} - -void NV2ADevice::pgraph_method(unsigned int subchannel, unsigned int method, uint32_t parameter) { - std::lock_guard lk(m_PGRAPH.mutex); - - GraphicsSubchannel *subchannel_data; - GraphicsObject *object; - - unsigned int slot; - - assert(m_PGRAPH.channel_valid); - subchannel_data = &m_PGRAPH.subchannel_data[subchannel]; - object = &subchannel_data->object; - - ContextSurfaces2DState *context_surfaces_2d = &object->data.context_surfaces_2d; - ImageBlitState *image_blit = &object->data.image_blit; - KelvinState *kelvin = &object->data.kelvin; - - pgraph_method_log(subchannel, object->graphics_class, method, parameter); - - if (method == NV_SET_OBJECT) { - subchannel_data->object_instance = parameter; - - //qemu_mutex_lock_iothread(); - load_graphics_object(parameter, object); - //qemu_mutex_unlock_iothread(); - return; - } - - switch (object->graphics_class) { - case NV_CONTEXT_SURFACES_2D: - { - switch (method) { - case NV062_SET_CONTEXT_DMA_IMAGE_SOURCE: - context_surfaces_2d->dma_image_source = parameter; - break; - case NV062_SET_CONTEXT_DMA_IMAGE_DESTIN: - context_surfaces_2d->dma_image_dest = parameter; - break; - case NV062_SET_COLOR_FORMAT: - context_surfaces_2d->color_format = parameter; - break; - case NV062_SET_PITCH: - context_surfaces_2d->source_pitch = parameter & 0xFFFF; - context_surfaces_2d->dest_pitch = parameter >> 16; - break; - case NV062_SET_OFFSET_SOURCE: - context_surfaces_2d->source_offset = parameter & 0x07FFFFFF; - break; - case NV062_SET_OFFSET_DESTIN: - context_surfaces_2d->dest_offset = parameter & 0x07FFFFFF; - break; - default: - log_warning("EmuNV2A: Unknown NV_CONTEXT_SURFACES_2D Method: 0x%08X\n", method); - } - - break; - } - - case NV_IMAGE_BLIT: - { - switch (method) { - case NV09F_SET_CONTEXT_SURFACES: - image_blit->context_surfaces = parameter; - break; - case NV09F_SET_OPERATION: - image_blit->operation = parameter; - break; - case NV09F_CONTROL_POINT_IN: - image_blit->in_x = parameter & 0xFFFF; - image_blit->in_y = parameter >> 16; - break; - case NV09F_CONTROL_POINT_OUT: - image_blit->out_x = parameter & 0xFFFF; - image_blit->out_y = parameter >> 16; - break; - case NV09F_SIZE: - image_blit->width = parameter & 0xFFFF; - image_blit->height = parameter >> 16; - - /* I guess this kicks it off? */ - if (image_blit->operation == NV09F_SET_OPERATION_SRCCOPY) { - - log_debug("NV09F_SET_OPERATION_SRCCOPY"); - - GraphicsObject *context_surfaces_obj = lookup_graphics_object(image_blit->context_surfaces); - assert(context_surfaces_obj); - assert(context_surfaces_obj->graphics_class == NV_CONTEXT_SURFACES_2D); - - ContextSurfaces2DState *context_surfaces = &context_surfaces_obj->data.context_surfaces_2d; - - unsigned int bytes_per_pixel; - switch (context_surfaces->color_format) { - case NV062_SET_COLOR_FORMAT_LE_Y8: - bytes_per_pixel = 1; - break; - case NV062_SET_COLOR_FORMAT_LE_R5G6B5: - bytes_per_pixel = 2; - break; - case NV062_SET_COLOR_FORMAT_LE_A8R8G8B8: - bytes_per_pixel = 4; - break; - default: - log_debug("Unknown blit surface format: 0x%x\n", context_surfaces->color_format); - assert(false); - break; - } - - uint32_t source_dma_len, dest_dma_len; - uint8_t *source, *dest; - - source = (uint8_t*)nv_dma_map(context_surfaces->dma_image_source, &source_dma_len); - assert(context_surfaces->source_offset < source_dma_len); - source += context_surfaces->source_offset; - - dest = (uint8_t*)nv_dma_map(context_surfaces->dma_image_dest, &dest_dma_len); - assert(context_surfaces->dest_offset < dest_dma_len); - dest += context_surfaces->dest_offset; - - log_debug(" - 0x%tx -> 0x%tx\n", source - m_VRAM, dest - m_VRAM); - - for (unsigned int y = 0; yheight; y++) { - uint8_t *source_row = source - + (image_blit->in_y + y) * context_surfaces->source_pitch - + image_blit->in_x * bytes_per_pixel; - - uint8_t *dest_row = dest - + (image_blit->out_y + y) * context_surfaces->dest_pitch - + image_blit->out_x * bytes_per_pixel; - - memmove(dest_row, source_row, - image_blit->width * bytes_per_pixel); - } - } - else { - assert(false); - } - - break; - default: - log_warning("EmuNV2A: Unknown NV_IMAGE_BLIT Method: 0x%08X\n", method); - } - break; - } - - case NV_KELVIN_PRIMITIVE: - { - switch (method) { - case NV097_SET_CONTEXT_DMA_NOTIFIES: - kelvin->dma_notifies = parameter; - break; - case NV097_SET_CONTEXT_DMA_A: - m_PGRAPH.dma_a = parameter; - break; - case NV097_SET_CONTEXT_DMA_B: - m_PGRAPH.dma_b = parameter; - break; - case NV097_SET_CONTEXT_DMA_STATE: - kelvin->dma_state = parameter; - break; - case NV097_SET_CONTEXT_DMA_COLOR: - log_debug("TODO: pgraph_update_surface\n"); - /* try to get any straggling draws in before the surface's changed :/ */ - //pgraph_update_surface(d, false, true, true); - - m_PGRAPH.dma_color = parameter; - break; - case NV097_SET_CONTEXT_DMA_ZETA: - m_PGRAPH.dma_zeta = parameter; - break; - case NV097_SET_CONTEXT_DMA_VERTEX_A: - m_PGRAPH.dma_vertex_a = parameter; - break; - case NV097_SET_CONTEXT_DMA_VERTEX_B: - m_PGRAPH.dma_vertex_b = parameter; - break; - case NV097_SET_CONTEXT_DMA_SEMAPHORE: - kelvin->dma_semaphore = parameter; - break; - case NV097_SET_CONTEXT_DMA_REPORT: - m_PGRAPH.dma_report = parameter; - break; - case NV097_SET_SURFACE_CLIP_HORIZONTAL: - log_debug("TODO: pgraph_update_surface\n"); - //pgraph_update_surface(d, false, true, true); - - m_PGRAPH.surface_shape.clip_x = - GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_X); - m_PGRAPH.surface_shape.clip_width = - GET_MASK(parameter, NV097_SET_SURFACE_CLIP_HORIZONTAL_WIDTH); - break; - case NV097_SET_SURFACE_CLIP_VERTICAL: - log_debug("TODO: pgraph_update_surface\n"); - //pgraph_update_surface(d, false, true, true); - - m_PGRAPH.surface_shape.clip_y = - GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_Y); - m_PGRAPH.surface_shape.clip_height = - GET_MASK(parameter, NV097_SET_SURFACE_CLIP_VERTICAL_HEIGHT); - break; - case NV097_SET_SURFACE_FORMAT: - log_debug("TODO: pgraph_update_surface\n"); - //pgraph_update_surface(d, false, true, true); - - m_PGRAPH.surface_shape.color_format = - GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_COLOR); - m_PGRAPH.surface_shape.zeta_format = - GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_ZETA); - m_PGRAPH.surface_type = - GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_TYPE); - m_PGRAPH.surface_shape.anti_aliasing = - GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_ANTI_ALIASING); - m_PGRAPH.surface_shape.log_width = - GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_WIDTH); - m_PGRAPH.surface_shape.log_height = - GET_MASK(parameter, NV097_SET_SURFACE_FORMAT_HEIGHT); - break; - case NV097_SET_SURFACE_PITCH: - log_debug("TODO: pgraph_update_surface\n"); - //pgraph_update_surface(d, false, true, true); - - m_PGRAPH.surface_color.pitch = - GET_MASK(parameter, NV097_SET_SURFACE_PITCH_COLOR); - m_PGRAPH.surface_zeta.pitch = - GET_MASK(parameter, NV097_SET_SURFACE_PITCH_ZETA); - break; - case NV097_SET_SURFACE_COLOR_OFFSET: - log_debug("TODO: pgraph_update_surface\n"); - //pgraph_update_surface(d, false, true, true); - - m_PGRAPH.surface_color.offset = parameter; - break; - case NV097_SET_SURFACE_ZETA_OFFSET: - log_debug("TODO: pgraph_update_surface\n"); - //pgraph_update_surface(d, false, true, true); - - m_PGRAPH.surface_zeta.offset = parameter; - break; - case NV097_SET_COMBINER_SPECULAR_FOG_CW0: - m_PGRAPH.regs[NV_PGRAPH_COMBINESPECFOG0] = parameter; - break; - case NV097_SET_COMBINER_SPECULAR_FOG_CW1: - m_PGRAPH.regs[NV_PGRAPH_COMBINESPECFOG1] = parameter; - break; - CASE_4(NV097_SET_TEXTURE_ADDRESS, 64) : - slot = (method - NV097_SET_TEXTURE_ADDRESS) / 64; - m_PGRAPH.regs[NV_PGRAPH_TEXADDRESS0 + slot * 4] = parameter; - break; - case NV097_SET_CONTROL0: - { - log_debug("TODO: pgraph_update_surface\n"); - //pgraph_update_surface(d, false, true, true); - - bool stencil_write_enable = - parameter & NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE; - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_STENCIL_WRITE_ENABLE, - stencil_write_enable); - - uint32_t z_format = GET_MASK(parameter, NV097_SET_CONTROL0_Z_FORMAT); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_Z_FORMAT, z_format); - - bool z_perspective = - parameter & NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE; - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE, - z_perspective); - break; - } - - case NV097_SET_FOG_MODE: - { - /* FIXME: There is also NV_PGRAPH_CSV0_D_FOG_MODE */ - unsigned int mode; - switch (parameter) { - case NV097_SET_FOG_MODE_V_LINEAR: - mode = NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR; break; - case NV097_SET_FOG_MODE_V_EXP: - mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP; break; - case NV097_SET_FOG_MODE_V_EXP2: - mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2; break; - case NV097_SET_FOG_MODE_V_EXP_ABS: - mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP_ABS; break; - case NV097_SET_FOG_MODE_V_EXP2_ABS: - mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2_ABS; break; - case NV097_SET_FOG_MODE_V_LINEAR_ABS: - mode = NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR_ABS; break; - default: - assert(false); - break; - } - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_FOG_MODE, - mode); - break; - } - case NV097_SET_FOG_GEN_MODE: - { - unsigned int mode; - switch (parameter) { - case NV097_SET_FOG_GEN_MODE_V_SPEC_ALPHA: - mode = NV_PGRAPH_CSV0_D_FOGGENMODE_SPEC_ALPHA; break; - case NV097_SET_FOG_GEN_MODE_V_RADIAL: - mode = NV_PGRAPH_CSV0_D_FOGGENMODE_RADIAL; break; - case NV097_SET_FOG_GEN_MODE_V_PLANAR: - mode = NV_PGRAPH_CSV0_D_FOGGENMODE_PLANAR; break; - case NV097_SET_FOG_GEN_MODE_V_ABS_PLANAR: - mode = NV_PGRAPH_CSV0_D_FOGGENMODE_ABS_PLANAR; break; - case NV097_SET_FOG_GEN_MODE_V_FOG_X: - mode = NV_PGRAPH_CSV0_D_FOGGENMODE_FOG_X; break; - default: - assert(false); - break; - } - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_FOGGENMODE, mode); - break; - } - case NV097_SET_FOG_ENABLE: - /* - FIXME: There is also: - SET_MASK(pgraph.regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_FOGENABLE, - parameter); - */ - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_FOGENABLE, - parameter); - break; - case NV097_SET_FOG_COLOR: - { - /* PGRAPH channels are ARGB, parameter channels are ABGR */ - uint8_t red = GET_MASK(parameter, NV097_SET_FOG_COLOR_RED); - uint8_t green = GET_MASK(parameter, NV097_SET_FOG_COLOR_GREEN); - uint8_t blue = GET_MASK(parameter, NV097_SET_FOG_COLOR_BLUE); - uint8_t alpha = GET_MASK(parameter, NV097_SET_FOG_COLOR_ALPHA); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_RED, red); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_GREEN, green); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_BLUE, blue); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_ALPHA, alpha); - break; - } - case NV097_SET_ALPHA_TEST_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_ALPHATESTENABLE, parameter); - break; - case NV097_SET_BLEND_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_BLEND], NV_PGRAPH_BLEND_EN, parameter); - break; - case NV097_SET_CULL_FACE_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_CULLENABLE, - parameter); - break; - case NV097_SET_DEPTH_TEST_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], NV_PGRAPH_CONTROL_0_ZENABLE, - parameter); - break; - case NV097_SET_DITHER_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_DITHERENABLE, parameter); - break; - case NV097_SET_LIGHTING_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_LIGHTING, - parameter); - break; - case NV097_SET_SKIN_MODE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_SKIN, - parameter); - break; - case NV097_SET_STENCIL_TEST_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_1], - NV_PGRAPH_CONTROL_1_STENCIL_TEST_ENABLE, parameter); - break; - case NV097_SET_POLY_OFFSET_POINT_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_POFFSETPOINTENABLE, parameter); - break; - case NV097_SET_POLY_OFFSET_LINE_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_POFFSETLINEENABLE, parameter); - break; - case NV097_SET_POLY_OFFSET_FILL_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_POFFSETFILLENABLE, parameter); - break; - case NV097_SET_ALPHA_FUNC: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_ALPHAFUNC, parameter & 0xF); - break; - case NV097_SET_ALPHA_REF: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_ALPHAREF, parameter); - break; - case NV097_SET_BLEND_FUNC_SFACTOR: - { - unsigned int factor; - switch (parameter) { - case NV097_SET_BLEND_FUNC_SFACTOR_V_ZERO: - factor = NV_PGRAPH_BLEND_SFACTOR_ZERO; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_ONE: - factor = NV_PGRAPH_BLEND_SFACTOR_ONE; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_COLOR: - factor = NV_PGRAPH_BLEND_SFACTOR_SRC_COLOR; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_SRC_COLOR: - factor = NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_SRC_COLOR; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA: - factor = NV_PGRAPH_BLEND_SFACTOR_SRC_ALPHA; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_SRC_ALPHA: - factor = NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_SRC_ALPHA; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_DST_ALPHA: - factor = NV_PGRAPH_BLEND_SFACTOR_DST_ALPHA; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_DST_ALPHA: - factor = NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_DST_ALPHA; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_DST_COLOR: - factor = NV_PGRAPH_BLEND_SFACTOR_DST_COLOR; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_DST_COLOR: - factor = NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_DST_COLOR; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_SRC_ALPHA_SATURATE: - factor = NV_PGRAPH_BLEND_SFACTOR_SRC_ALPHA_SATURATE; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_CONSTANT_COLOR: - factor = NV_PGRAPH_BLEND_SFACTOR_CONSTANT_COLOR; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_CONSTANT_COLOR: - factor = NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_CONSTANT_COLOR; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_CONSTANT_ALPHA: - factor = NV_PGRAPH_BLEND_SFACTOR_CONSTANT_ALPHA; break; - case NV097_SET_BLEND_FUNC_SFACTOR_V_ONE_MINUS_CONSTANT_ALPHA: - factor = NV_PGRAPH_BLEND_SFACTOR_ONE_MINUS_CONSTANT_ALPHA; break; - default: - log_warning("Unknown blend source factor: 0x%x\n", parameter); - assert(false); - break; - } - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_BLEND], NV_PGRAPH_BLEND_SFACTOR, factor); - - break; - } - - case NV097_SET_BLEND_FUNC_DFACTOR: - { - unsigned int factor; - switch (parameter) { - case NV097_SET_BLEND_FUNC_DFACTOR_V_ZERO: - factor = NV_PGRAPH_BLEND_DFACTOR_ZERO; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_ONE: - factor = NV_PGRAPH_BLEND_DFACTOR_ONE; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_SRC_COLOR: - factor = NV_PGRAPH_BLEND_DFACTOR_SRC_COLOR; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_COLOR: - factor = NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_SRC_COLOR; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_SRC_ALPHA: - factor = NV_PGRAPH_BLEND_DFACTOR_SRC_ALPHA; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_SRC_ALPHA: - factor = NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_SRC_ALPHA; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_DST_ALPHA: - factor = NV_PGRAPH_BLEND_DFACTOR_DST_ALPHA; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_DST_ALPHA: - factor = NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_DST_ALPHA; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_DST_COLOR: - factor = NV_PGRAPH_BLEND_DFACTOR_DST_COLOR; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_DST_COLOR: - factor = NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_DST_COLOR; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_SRC_ALPHA_SATURATE: - factor = NV_PGRAPH_BLEND_DFACTOR_SRC_ALPHA_SATURATE; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_CONSTANT_COLOR: - factor = NV_PGRAPH_BLEND_DFACTOR_CONSTANT_COLOR; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_CONSTANT_COLOR: - factor = NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_CONSTANT_COLOR; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_CONSTANT_ALPHA: - factor = NV_PGRAPH_BLEND_DFACTOR_CONSTANT_ALPHA; break; - case NV097_SET_BLEND_FUNC_DFACTOR_V_ONE_MINUS_CONSTANT_ALPHA: - factor = NV_PGRAPH_BLEND_DFACTOR_ONE_MINUS_CONSTANT_ALPHA; break; - default: - log_warning("Unknown blend destination factor: 0x%x\n", parameter); - assert(false); - break; - } - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_BLEND], NV_PGRAPH_BLEND_DFACTOR, factor); - - break; - } - - case NV097_SET_BLEND_COLOR: - m_PGRAPH.regs[NV_PGRAPH_BLENDCOLOR] = parameter; - break; - - case NV097_SET_BLEND_EQUATION: - { - unsigned int equation; - switch (parameter) { - case NV097_SET_BLEND_EQUATION_V_FUNC_SUBTRACT: - equation = 0; break; - case NV097_SET_BLEND_EQUATION_V_FUNC_REVERSE_SUBTRACT: - equation = 1; break; - case NV097_SET_BLEND_EQUATION_V_FUNC_ADD: - equation = 2; break; - case NV097_SET_BLEND_EQUATION_V_MIN: - equation = 3; break; - case NV097_SET_BLEND_EQUATION_V_MAX: - equation = 4; break; - case NV097_SET_BLEND_EQUATION_V_FUNC_REVERSE_SUBTRACT_SIGNED: - equation = 5; break; - case NV097_SET_BLEND_EQUATION_V_FUNC_ADD_SIGNED: - equation = 6; break; - default: - assert(false); - break; - } - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_BLEND], NV_PGRAPH_BLEND_EQN, equation); - - break; - } - - case NV097_SET_DEPTH_FUNC: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], NV_PGRAPH_CONTROL_0_ZFUNC, - parameter & 0xF); - break; - - case NV097_SET_COLOR_MASK: - { - m_PGRAPH.surface_color.write_enabled_cache |= pgraph_color_write_enabled(); - - bool alpha = parameter & NV097_SET_COLOR_MASK_ALPHA_WRITE_ENABLE; - bool red = parameter & NV097_SET_COLOR_MASK_RED_WRITE_ENABLE; - bool green = parameter & NV097_SET_COLOR_MASK_GREEN_WRITE_ENABLE; - bool blue = parameter & NV097_SET_COLOR_MASK_BLUE_WRITE_ENABLE; - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_ALPHA_WRITE_ENABLE, alpha); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_RED_WRITE_ENABLE, red); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_GREEN_WRITE_ENABLE, green); - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_BLUE_WRITE_ENABLE, blue); - break; - } - case NV097_SET_DEPTH_MASK: - m_PGRAPH.surface_zeta.write_enabled_cache |= pgraph_zeta_write_enabled(); - - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_0], - NV_PGRAPH_CONTROL_0_ZWRITEENABLE, parameter); - break; - case NV097_SET_STENCIL_MASK: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_1], - NV_PGRAPH_CONTROL_1_STENCIL_MASK_WRITE, parameter); - break; - case NV097_SET_STENCIL_FUNC: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_1], - NV_PGRAPH_CONTROL_1_STENCIL_FUNC, parameter & 0xF); - break; - case NV097_SET_STENCIL_FUNC_REF: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_1], - NV_PGRAPH_CONTROL_1_STENCIL_REF, parameter); - break; - case NV097_SET_STENCIL_FUNC_MASK: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_1], - NV_PGRAPH_CONTROL_1_STENCIL_MASK_READ, parameter); - break; - case NV097_SET_STENCIL_OP_FAIL: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_2], - NV_PGRAPH_CONTROL_2_STENCIL_OP_FAIL, - kelvin_map_stencil_op(parameter)); - break; - case NV097_SET_STENCIL_OP_ZFAIL: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_2], - NV_PGRAPH_CONTROL_2_STENCIL_OP_ZFAIL, - kelvin_map_stencil_op(parameter)); - break; - case NV097_SET_STENCIL_OP_ZPASS: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CONTROL_2], - NV_PGRAPH_CONTROL_2_STENCIL_OP_ZPASS, - kelvin_map_stencil_op(parameter)); - break; - - case NV097_SET_POLYGON_OFFSET_SCALE_FACTOR: - m_PGRAPH.regs[NV_PGRAPH_ZOFFSETFACTOR] = parameter; - break; - case NV097_SET_POLYGON_OFFSET_BIAS: - m_PGRAPH.regs[NV_PGRAPH_ZOFFSETBIAS] = parameter; - break; - case NV097_SET_FRONT_POLYGON_MODE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_FRONTFACEMODE, - kelvin_map_polygon_mode(parameter)); - break; - case NV097_SET_BACK_POLYGON_MODE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_BACKFACEMODE, - kelvin_map_polygon_mode(parameter)); - break; - case NV097_SET_CLIP_MIN: - m_PGRAPH.regs[NV_PGRAPH_ZCLIPMIN] = parameter; - break; - case NV097_SET_CLIP_MAX: - m_PGRAPH.regs[NV_PGRAPH_ZCLIPMAX] = parameter; - break; - case NV097_SET_CULL_FACE: - { - unsigned int face; - switch (parameter) { - case NV097_SET_CULL_FACE_V_FRONT: - face = NV_PGRAPH_SETUPRASTER_CULLCTRL_FRONT; break; - case NV097_SET_CULL_FACE_V_BACK: - face = NV_PGRAPH_SETUPRASTER_CULLCTRL_BACK; break; - case NV097_SET_CULL_FACE_V_FRONT_AND_BACK: - face = NV_PGRAPH_SETUPRASTER_CULLCTRL_FRONT_AND_BACK; break; - default: - assert(false); - break; - } - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_CULLCTRL, - face); - break; - } - case NV097_SET_FRONT_FACE: - { - bool ccw; - switch (parameter) { - case NV097_SET_FRONT_FACE_V_CW: - ccw = false; break; - case NV097_SET_FRONT_FACE_V_CCW: - ccw = true; break; - default: - log_warning("Unknown front face: 0x%x\n", parameter); - assert(false); - break; - } - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_SETUPRASTER], - NV_PGRAPH_SETUPRASTER_FRONTFACE, - ccw ? 1 : 0); - break; - } - case NV097_SET_NORMALIZATION_ENABLE: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CSV0_C], - NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE, - parameter); - break; - - case NV097_SET_LIGHT_ENABLE_MASK: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CSV0_D], - NV_PGRAPH_CSV0_D_LIGHTS, - parameter); - break; - - CASE_4(NV097_SET_TEXGEN_S, 16) : { - slot = (method - NV097_SET_TEXGEN_S) / 16; - unsigned int reg = (slot < 2) ? NV_PGRAPH_CSV1_A - : NV_PGRAPH_CSV1_B; - unsigned int mask = (slot % 2) ? NV_PGRAPH_CSV1_A_T1_S - : NV_PGRAPH_CSV1_A_T0_S; - SET_MASK(m_PGRAPH.regs[reg], mask, kelvin_map_texgen(parameter, 0)); - break; - } - CASE_4(NV097_SET_TEXGEN_T, 16) : { - slot = (method - NV097_SET_TEXGEN_T) / 16; - unsigned int reg = (slot < 2) ? NV_PGRAPH_CSV1_A - : NV_PGRAPH_CSV1_B; - unsigned int mask = (slot % 2) ? NV_PGRAPH_CSV1_A_T1_T - : NV_PGRAPH_CSV1_A_T0_T; - SET_MASK(m_PGRAPH.regs[reg], mask, kelvin_map_texgen(parameter, 1)); - break; - } - CASE_4(NV097_SET_TEXGEN_R, 16) : { - slot = (method - NV097_SET_TEXGEN_R) / 16; - unsigned int reg = (slot < 2) ? NV_PGRAPH_CSV1_A - : NV_PGRAPH_CSV1_B; - unsigned int mask = (slot % 2) ? NV_PGRAPH_CSV1_A_T1_R - : NV_PGRAPH_CSV1_A_T0_R; - SET_MASK(m_PGRAPH.regs[reg], mask, kelvin_map_texgen(parameter, 2)); - break; - } - CASE_4(NV097_SET_TEXGEN_Q, 16) : { - slot = (method - NV097_SET_TEXGEN_Q) / 16; - unsigned int reg = (slot < 2) ? NV_PGRAPH_CSV1_A - : NV_PGRAPH_CSV1_B; - unsigned int mask = (slot % 2) ? NV_PGRAPH_CSV1_A_T1_Q - : NV_PGRAPH_CSV1_A_T0_Q; - SET_MASK(m_PGRAPH.regs[reg], mask, kelvin_map_texgen(parameter, 3)); - break; - } - CASE_4(NV097_SET_TEXTURE_MATRIX_ENABLE, 4) : - slot = (method - NV097_SET_TEXTURE_MATRIX_ENABLE) / 4; - m_PGRAPH.texture_matrix_enable[slot] = parameter; - break; - - case NV097_SET_TEXGEN_VIEW_MODEL: - SET_MASK(m_PGRAPH.regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_TEXGEN_REF, parameter); - break; - default: - if (method >= NV097_SET_COMBINER_ALPHA_ICW && method <= NV097_SET_COMBINER_ALPHA_ICW + 28) { - slot = (method - NV097_SET_COMBINER_ALPHA_ICW) / 4; - m_PGRAPH.regs[NV_PGRAPH_COMBINEALPHAI0 + slot * 4] = parameter; - break; - } - - if (method >= NV097_SET_PROJECTION_MATRIX && method <= NV097_SET_PROJECTION_MATRIX + 0x3c) { - slot = (method - NV097_SET_PROJECTION_MATRIX) / 4; - // pg->projection_matrix[slot] = *(float*)¶meter; - unsigned int row = NV_IGRAPH_XF_XFCTX_PMAT0 + slot / 4; - m_PGRAPH.vsh_constants[row][slot % 4] = parameter; - m_PGRAPH.vsh_constants_dirty[row] = true; - break; - } - - if (method >= NV097_SET_MODEL_VIEW_MATRIX && method <= NV097_SET_MODEL_VIEW_MATRIX + 0xfc) { - slot = (method - NV097_SET_MODEL_VIEW_MATRIX) / 4; - unsigned int matnum = slot / 16; - unsigned int entry = slot % 16; - unsigned int row = NV_IGRAPH_XF_XFCTX_MMAT0 + matnum * 8 + entry / 4; - m_PGRAPH.vsh_constants[row][entry % 4] = parameter; - m_PGRAPH.vsh_constants_dirty[row] = true; - break; - } - - if (method >= NV097_SET_INVERSE_MODEL_VIEW_MATRIX && method <= NV097_SET_INVERSE_MODEL_VIEW_MATRIX + 0xfc) { - slot = (method - NV097_SET_INVERSE_MODEL_VIEW_MATRIX) / 4; - unsigned int matnum = slot / 16; - unsigned int entry = slot % 16; - unsigned int row = NV_IGRAPH_XF_XFCTX_IMMAT0 + matnum * 8 + entry / 4; - m_PGRAPH.vsh_constants[row][entry % 4] = parameter; - m_PGRAPH.vsh_constants_dirty[row] = true; - break; - } - - if (method >= NV097_SET_COMPOSITE_MATRIX && method <= NV097_SET_COMPOSITE_MATRIX + 0x3c) { - slot = (method - NV097_SET_COMPOSITE_MATRIX) / 4; - unsigned int row = NV_IGRAPH_XF_XFCTX_CMAT0 + slot / 4; - m_PGRAPH.vsh_constants[row][slot % 4] = parameter; - m_PGRAPH.vsh_constants_dirty[row] = true; - break; - } - - if (method >= NV097_SET_TEXTURE_MATRIX && method <= NV097_SET_TEXTURE_MATRIX + 0xfc) { - slot = (method - NV097_SET_TEXTURE_MATRIX) / 4; - unsigned int tex = slot / 16; - unsigned int entry = slot % 16; - unsigned int row = NV_IGRAPH_XF_XFCTX_T0MAT + tex * 8 + entry / 4; - m_PGRAPH.vsh_constants[row][entry % 4] = parameter; - m_PGRAPH.vsh_constants_dirty[row] = true; - break; - } - - if (method >= NV097_SET_FOG_PARAMS && method <= NV097_SET_FOG_PARAMS + 8) { - slot = (method - NV097_SET_FOG_PARAMS) / 4; - if (slot < 2) { - m_PGRAPH.regs[NV_PGRAPH_FOGPARAM0 + slot * 4] = parameter; - } - else { - /* FIXME: No idea where slot = 2 is */ - } - - m_PGRAPH.ltctxa[NV_IGRAPH_XF_LTCTXA_FOG_K][slot] = parameter; - m_PGRAPH.ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_FOG_K] = true; - break; - } - - /* Handles NV097_SET_TEXGEN_PLANE_S,T,R,Q */ - if (method >= NV097_SET_TEXGEN_PLANE_S && method <= NV097_SET_TEXGEN_PLANE_S + 0xfc) { - slot = (method - NV097_SET_TEXGEN_PLANE_S) / 4; - unsigned int tex = slot / 16; - unsigned int entry = slot % 16; - unsigned int row = NV_IGRAPH_XF_XFCTX_TG0MAT + tex * 8 + entry / 4; - m_PGRAPH.vsh_constants[row][entry % 4] = parameter; - m_PGRAPH.vsh_constants_dirty[row] = true; - break; - } - - if (method >= NV097_SET_FOG_PLANE && method <= NV097_SET_FOG_PLANE + 12) { - slot = (method - NV097_SET_FOG_PLANE) / 4; - m_PGRAPH.vsh_constants[NV_IGRAPH_XF_XFCTX_FOG][slot] = parameter; - m_PGRAPH.vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_FOG] = true; - break; - } - - if (method >= NV097_SET_SCENE_AMBIENT_COLOR && method <= NV097_SET_SCENE_AMBIENT_COLOR + 8) { - slot = (method - NV097_SET_SCENE_AMBIENT_COLOR) / 4; - // ?? - m_PGRAPH.ltctxa[NV_IGRAPH_XF_LTCTXA_FR_AMB][slot] = parameter; - m_PGRAPH.ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_FR_AMB] = true; - break; - } - - if (method >= NV097_SET_VIEWPORT_OFFSET && method <= NV097_SET_VIEWPORT_OFFSET + 12) { - slot = (method - NV097_SET_VIEWPORT_OFFSET) / 4; - m_PGRAPH.vsh_constants[NV_IGRAPH_XF_XFCTX_VPOFF][slot] = parameter; - m_PGRAPH.vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_VPOFF] = true; - break; - } - - if (method >= NV097_SET_EYE_POSITION && method <= NV097_SET_EYE_POSITION + 12) { - slot = (method - NV097_SET_EYE_POSITION) / 4; - m_PGRAPH.vsh_constants[NV_IGRAPH_XF_XFCTX_EYEP][slot] = parameter; - m_PGRAPH.vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_EYEP] = true; - break; - } - - if (method >= NV097_SET_COMBINER_FACTOR0 && method <= NV097_SET_COMBINER_FACTOR0 + 28) { - slot = (method - NV097_SET_COMBINER_FACTOR0) / 4; - m_PGRAPH.regs[NV_PGRAPH_COMBINEFACTOR0 + slot * 4] = parameter; - break; - } - - if (method >= NV097_SET_COMBINER_FACTOR1 && method <= NV097_SET_COMBINER_FACTOR1 + 28) { - slot = (method - NV097_SET_COMBINER_FACTOR1) / 4; - m_PGRAPH.regs[NV_PGRAPH_COMBINEFACTOR1 + slot * 4] = parameter; - break; - } - - if (method >= NV097_SET_COMBINER_ALPHA_OCW && method <= NV097_SET_COMBINER_ALPHA_OCW + 28) { - slot = (method - NV097_SET_COMBINER_ALPHA_OCW) / 4; - m_PGRAPH.regs[NV_PGRAPH_COMBINEALPHAO0 + slot * 4] = parameter; - break; - } - - if (method >= NV097_SET_COMBINER_COLOR_ICW && method <= NV097_SET_COMBINER_COLOR_ICW + 28) { - slot = (method - NV097_SET_COMBINER_COLOR_ICW) / 4; - m_PGRAPH.regs[NV_PGRAPH_COMBINECOLORI0 + slot * 4] = parameter; - break; - } - - if (method >= NV097_SET_VIEWPORT_SCALE && method <= NV097_SET_VIEWPORT_SCALE + 12) { - slot = (method - NV097_SET_VIEWPORT_SCALE) / 4; - m_PGRAPH.vsh_constants[NV_IGRAPH_XF_XFCTX_VPSCL][slot] = parameter; - m_PGRAPH.vsh_constants_dirty[NV_IGRAPH_XF_XFCTX_VPSCL] = true; - break; - } - - log_warning("EmuNV2A: Unknown NV_KELVIN_PRIMITIVE Method: 0x%08X\n", method); - } - break; - } - - default: - log_warning("EmuNV2A: Unknown Graphics Class/Method 0x%08X/0x%08X\n", object->graphics_class, method); - break; - } -} - -void NV2ADevice::pfifo_run_pusher() { - uint8_t channel_id; - ChannelControl *control; - Cache1State *state; - //CacheEntry *command; - uint8_t *dma; - uint32_t dma_len; - uint32_t word; - - /* TODO: How is cache1 selected? */ - state = &m_PFIFO.cache1; - channel_id = state->channel_id; - control = &m_User.channel_control[channel_id]; - - if (!state->push_enabled) return; - - /* only handling DMA for now... */ - - /* Channel running DMA */ - uint32_t channel_modes = m_PFIFO.regs[NV_PFIFO_MODE]; - assert(channel_modes & (1 << channel_id)); - assert(state->mode == FIFO_DMA); - - if (!state->dma_push_enabled) return; - if (state->dma_push_suspended) return; - - /* We're running so there should be no pending errors... */ - assert(state->error == NV_PFIFO_CACHE1_DMA_STATE_ERROR_NONE); - - dma = (uint8_t*)nv_dma_map(state->dma_instance, &dma_len); - - log_debug("DMA pusher: max 0x%08X, 0x%08X - 0x%08X\n", - dma_len, control->dma_get, control->dma_put); - - /* based on the convenient pseudocode in envytools */ - /* See: http://envytools.readthedocs.io/en/latest/hw/fifo/dma-pusher.html */ - while (control->dma_get != control->dma_put) { - if (control->dma_get >= dma_len) { - state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_PROTECTION; - break; - } - - word = ldl_le_p((uint32_t*)(dma + control->dma_get)); - control->dma_get += 4; - - if (state->method_count) { - /* data word of methods command */ - state->data_shadow = word; - - CacheEntry* command = (CacheEntry*)calloc(1, sizeof(CacheEntry)); - command->method = state->method; - command->subchannel = state->subchannel; - command->nonincreasing = state->method_nonincreasing; - command->parameter = word; - - std::lock_guard lk(state->mutex); - state->cache.push(command); - state->cache_cond.notify_all(); - - if (!state->method_nonincreasing) { - state->method += 4; - } - - state->method_count--; - state->dcount++; - } - else { - /* no command active - this is the first word of a new one */ - state->rsvd_shadow = word; - /* match all forms */ - if ((word & 0xe0000003) == 0x20000000) { - /* old jump */ - state->get_jmp_shadow = control->dma_get; - control->dma_get = word & 0x1fffffff; - log_debug("pb OLD_JMP 0x%08X\n", control->dma_get); - } - else if ((word & 3) == 1) { - /* jump */ - state->get_jmp_shadow = control->dma_get; - control->dma_get = word & 0xfffffffc; - log_debug("pb JMP 0x%08X\n", control->dma_get); - } - else if ((word & 3) == 2) { - /* call */ - if (state->subroutine_active) { - state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_CALL; - break; - } - state->subroutine_return = control->dma_get; - state->subroutine_active = true; - control->dma_get = word & 0xfffffffc; - log_debug("pb CALL 0x%08X\n", control->dma_get); - } - else if (word == 0x00020000) { - /* return */ - if (!state->subroutine_active) { - state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RETURN; - break; - } - control->dma_get = state->subroutine_return; - state->subroutine_active = false; - log_debug("pb RET 0x%08X\n", control->dma_get); - } - else if ((word & 0xe0030003) == 0) { - /* increasing methods */ - state->method = word & 0x1fff; - state->subchannel = (word >> 13) & 7; - state->method_count = (word >> 18) & 0x7ff; - state->method_nonincreasing = false; - state->dcount = 0; - } - else if ((word & 0xe0030003) == 0x40000000) { - /* non-increasing methods */ - state->method = word & 0x1fff; - state->subchannel = (word >> 13) & 7; - state->method_count = (word >> 18) & 0x7ff; - state->method_nonincreasing = true; - state->dcount = 0; - } - else { - log_debug("pb reserved cmd 0x%08X - 0x%08X\n", - control->dma_get, word); - state->error = NV_PFIFO_CACHE1_DMA_STATE_ERROR_RESERVED_CMD; - break; - } - } - } - - log_debug("DMA pusher done: max 0x%08X, 0x%08X - 0x%08X\n", - dma_len, control->dma_get, control->dma_put); - - if (state->error) { - log_warning("pb error: %d\n", state->error); - assert(false); - - state->dma_push_suspended = true; - - m_PFIFO.pending_interrupts |= NV_PFIFO_INTR_0_DMA_PUSHER; - UpdateIRQ(); - } -} - -void NV2ADevice::PFIFO_Puller_Thread(NV2ADevice *nv2a) { - Thread_SetName("[HW] NV2A PFIFO Puller"); - - Cache1State *state = &nv2a->m_PFIFO.cache1; - while (nv2a->m_running) { - // Scope the lock so that it automatically unlocks at tne end of this block - { - std::unique_lock lk(state->mutex); - - while (state->cache.empty() || !state->pull_enabled) { - state->cache_cond.wait(lk); - if (!nv2a->m_running) { - break; - } - } - - // Copy cache to working_cache - while (!state->cache.empty()) { - state->working_cache.push(state->cache.front()); - state->cache.pop(); - } - } - - while (!state->working_cache.empty()) { - CacheEntry* command = state->working_cache.front(); - state->working_cache.pop(); - - if (command->method == 0) { - // qemu_mutex_lock_iothread(); - RAMHTEntry entry = nv2a->ramht_lookup(command->parameter); - assert(entry.valid); - - assert(entry.channel_id == state->channel_id); - // qemu_mutex_unlock_iothread(); - - switch (entry.engine) { - case ENGINE_GRAPHICS: - nv2a->pgraph_context_switch(entry.channel_id); - nv2a->pgraph_wait_fifo_access(); - nv2a->pgraph_method(command->subchannel, 0, entry.instance); - break; - default: - assert(false); - break; - } - - /* the engine is bound to the subchannel */ - std::lock_guard lk(nv2a->m_PFIFO.cache1.mutex); - state->bound_engines[command->subchannel] = entry.engine; - state->last_engine = entry.engine; - } - else if (command->method >= 0x100) { - /* method passed to engine */ - - uint32_t parameter = command->parameter; - - /* methods that take objects. - * TODO: Check this range is correct for the nv2a */ - if (command->method >= 0x180 && command->method < 0x200) { - //qemu_mutex_lock_iothread(); - RAMHTEntry entry = nv2a->ramht_lookup(parameter); - assert(entry.valid); - assert(entry.channel_id == state->channel_id); - parameter = entry.instance; - //qemu_mutex_unlock_iothread(); - } - - // qemu_mutex_lock(&state->cache_lock); - enum FIFOEngine engine = state->bound_engines[command->subchannel]; - // qemu_mutex_unlock(&state->cache_lock); - - switch (engine) { - case ENGINE_GRAPHICS: - nv2a->pgraph_wait_fifo_access(); - nv2a->pgraph_method(command->subchannel, command->method, parameter); - break; - default: - assert(false); - break; - } - - // qemu_mutex_lock(&state->cache_lock); - state->last_engine = state->bound_engines[command->subchannel]; - // qemu_mutex_unlock(&state->cache_lock); - } - - free(command); - } - } -} - -void NV2ADevice::UpdateIRQ() { - // Update pending hardware interrupts - if (m_PFIFO.pending_interrupts & m_PFIFO.enabled_interrupts) { - m_PMC.pendingInterrupts |= NV_PMC_INTR_0_PFIFO; - } - else { - m_PMC.pendingInterrupts &= ~NV_PMC_INTR_0_PFIFO; - } - - if (m_PCRTC.pendingInterrupts & m_PCRTC.enabledInterrupts) { - m_PMC.pendingInterrupts |= NV_PMC_INTR_0_PCRTC; - } - else { - m_PMC.pendingInterrupts &= ~NV_PMC_INTR_0_PCRTC; - } - - if (m_PGRAPH.pending_interrupts & m_PGRAPH.enabled_interrupts) { - m_PMC.pendingInterrupts |= NV_PMC_INTR_0_PGRAPH; - } - else { - m_PMC.pendingInterrupts &= ~NV_PMC_INTR_0_PGRAPH; - } - - uint8_t irq = Read8(m_configSpace, PCI_INTERRUPT_PIN); - - // Raise IRQ if one of the following is true: - // - Hardware interrupts are enabled and there is any pending interrupt bit set other than software - // - Software interrupts are enabled and the pending software interrupt bit is set - if ((m_PMC.enabledInterrupts & NV_PMC_INTR_EN_0_HARDWARE) && (m_PMC.pendingInterrupts & ~NV_PMC_INTR_0_SOFTWARE) || - (m_PMC.enabledInterrupts & NV_PMC_INTR_EN_0_SOFTWARE) && (m_PMC.pendingInterrupts & NV_PMC_INTR_0_SOFTWARE)) { - m_irqHandler.HandleIRQ(irq, true); - } - else { - m_irqHandler.HandleIRQ(irq, false); - } -} - -void NV2ADevice::VBlankThread(NV2ADevice *nv2a) { - Thread_SetName("[HW] NV2A VBlank"); - - using namespace std::chrono; - auto nextStop = high_resolution_clock::now(); - auto interval = duration>((long long)(1000000.0f / 60.0f)); - - while (nv2a->m_running) { - // TODO: wait for a condition variable instead of checking like this - if (nv2a->m_PCRTC.enabledInterrupts & NV_PCRTC_INTR_0_VBLANK) { - nv2a->m_PCRTC.pendingInterrupts |= NV_PCRTC_INTR_0_VBLANK; - nv2a->UpdateIRQ(); - } - - nextStop += interval; - std::this_thread::sleep_until(nextStop); - } + log_spew("NV2ADevice::PCIMMIOWrite: Unimplemented write! bar = %d, address = 0x%x, value = 0x%x, size = %u\n", barIndex, addr, value, size); } } diff --git a/modules/core/src/common/strikebox/hw/pci/nvapu.cpp b/modules/core/src/common/strikebox/hw/pci/nvapu.cpp index 21f3fe7..1cf8a93 100644 --- a/modules/core/src/common/strikebox/hw/pci/nvapu.cpp +++ b/modules/core/src/common/strikebox/hw/pci/nvapu.cpp @@ -1,43 +1,3 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's APU emulator. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * src->devices->APUDevice.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 Luke Usher -// * -// * All rights reserved -// * -// ****************************************************************** - #include "strikebox/hw/pci/nvapu.h" #include "strikebox/log.h" @@ -50,9 +10,6 @@ uint32_t GetAPUTime() { return static_cast(t.time_since_epoch().count() * 0.000048000); } -// TODO: Everything :P -// TODO: Audio Processing/Thread - NVAPUDevice::NVAPUDevice() : PCIDevice(PCI_HEADER_TYPE_NORMAL, PCI_VENDOR_ID_NVIDIA, 0x01B0, 0xB1, 0x04, 0x01, 0x00) // Multimedia Audio Controller @@ -89,84 +46,33 @@ void NVAPUDevice::Reset() { } void NVAPUDevice::PCIIORead(int barIndex, uint32_t port, uint32_t *value, uint8_t size) { - log_spew("NVAPUDevice::PCIIORead: Unimplemented! bar = %d, port = 0x%x, size = %u\n", barIndex, port, size); + log_spew("NVAPUDevice::PCIIORead: Unimplemented read! bar = %d, port = 0x%x, size = %u\n", barIndex, port, size); + *value = 0; } void NVAPUDevice::PCIIOWrite(int barIndex, uint32_t port, uint32_t value, uint8_t size) { - log_spew("NVAPUDevice::PCIIOWrite: Unimplemented! bar = %d, port = 0x%x, value = 0x%x, size = %u\n", barIndex, port, value, size); + log_spew("NVAPUDevice::PCIIOWrite: Unimplemented write! bar = %d, port = 0x%x, value = 0x%x, size = %u\n", barIndex, port, value, size); } void NVAPUDevice::PCIMMIORead(int barIndex, uint32_t addr, uint32_t *value, uint8_t size) { - if (addr >= APU_VP_BASE && addr < APU_VP_BASE + APU_VP_SIZE) { - VPRead(addr - APU_VP_BASE, value, size); - return; - } - - if (addr >= APU_GP_BASE && addr < APU_GP_BASE + APU_GP_SIZE) { - GPRead(addr - APU_GP_BASE, value, size); - return; - } - - if (addr >= APU_EP_BASE && addr < APU_EP_BASE + APU_EP_SIZE) { - EPRead(addr - APU_EP_BASE, value, size); - return; - } - // FIXME: this satisfies the most basic needs of the guest software if (addr == 0x200C) { *value = GetAPUTime(); + log_spew("NVAPUDevice::PCIMMIORead: Reading dummy value! bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); + } + // HACK: Pretend the FIFO is always empty, bypasses hangs when APU isn't fully implemented + else if (addr == 0x20010) { + *value = 0x80; + log_spew("NVAPUDevice::PCIMMIORead: Reading dummy value! bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); + } + else { + *value = 0; + log_spew("NVAPUDevice::PCIMMIORead: Unimplemented read! bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); } - - log_spew("NVAPUDevice::PCIMMIORead: Unhandled read! bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); } void NVAPUDevice::PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint8_t size) { - if (addr >= APU_VP_BASE && addr < APU_VP_BASE + APU_VP_SIZE) { - VPWrite(addr - APU_VP_BASE, value, size); - return; - } - - if (addr >= APU_GP_BASE && addr < APU_GP_BASE + APU_GP_SIZE) { - VPWrite(addr - APU_GP_BASE, value, size); - return; - } - - if (addr >= APU_EP_BASE && addr < APU_EP_BASE + APU_EP_SIZE) { - VPWrite(addr - APU_EP_BASE, value, size); - return; - } - - log_spew("NVAPUDevice::PCIMMIOWrite: Unhandled write! bar = %d, address = 0x%x, value = 0x%x, size = %u\n", barIndex, addr, value, size); -} - -void NVAPUDevice::GPRead(uint32_t address, uint32_t *value, uint8_t size) { - log_spew("NVAPUDevice::GPRead: Unimplemented! address = 0x%x, size = %u\n", address, size); -} - -void NVAPUDevice::GPWrite(uint32_t address, uint32_t value, uint8_t size) { - log_spew("NVAPUDevice::GPWrite: Unimplemented! address = 0x%x, value = 0x%x, size = %u\n", address, value, size); -} - -void NVAPUDevice::EPRead(uint32_t address, uint32_t *value, uint8_t size) { - log_spew("NVAPUDevice::EPRead: Unimplemented! address = 0x%x, size = %u\n", address, size); -} - -void NVAPUDevice::EPWrite(uint32_t address, uint32_t value, uint8_t size) { - log_spew("NVAPUDevice::EPWrite: Unimplemented! address = 0x%x, value = 0x%x, size = %u\n", address, value, size); -} - -void NVAPUDevice::VPRead(uint32_t address, uint32_t *value, uint8_t size) { - // FIXME: HACK: Pretend the FIFO is always empty, bypasses hangs when APU isn't fully implemented - if (address == 0x10) { - *value = 0x80; - return; - } - - log_spew("NVAPUDevice::VPRead: Unimplemented! address = 0x%x, size = %u\n", address, size); -} - -void NVAPUDevice::VPWrite(uint32_t address, uint32_t value, uint8_t size) { - log_spew("NVAPUDevice::VPWrite: Unimplemented! address = 0x%x, value = 0x%x, size = %u\n", address, value, size); + log_spew("NVAPUDevice::PCIMMIOWrite: Unimplemented write! bar = %d, address = 0x%x, value = 0x%x, size = %u\n", barIndex, addr, value, size); } } diff --git a/modules/core/src/common/strikebox/hw/pci/nvnet.cpp b/modules/core/src/common/strikebox/hw/pci/nvnet.cpp index 4c3b732..16c83b5 100644 --- a/modules/core/src/common/strikebox/hw/pci/nvnet.cpp +++ b/modules/core/src/common/strikebox/hw/pci/nvnet.cpp @@ -1,483 +1,9 @@ -/* - * Portions of the code are based on XQEMU's nForce Ethernet Controller implementation. - * The original copyright header is included below. - */ -/* - * QEMU nForce Ethernet Controller implementation - * - * Copyright (c) 2013 espes - * Copyright (c) 2015 Matt Borgerson - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ #include "strikebox/hw/pci/nvnet.h" #include "strikebox/log.h" namespace strikebox { -// NVNET Register Definitions -// Taken from XQEMU -enum { - NvRegIrqStatus = 0x000, -# define NVREG_IRQSTAT_BIT1 0x002 -# define NVREG_IRQSTAT_BIT4 0x010 -# define NVREG_IRQSTAT_MIIEVENT 0x040 -# define NVREG_IRQSTAT_MASK 0x1ff - NvRegIrqMask = 0x004, -# define NVREG_IRQ_RX 0x0002 -# define NVREG_IRQ_RX_NOBUF 0x0004 -# define NVREG_IRQ_TX_ERR 0x0008 -# define NVREG_IRQ_TX2 0x0010 -# define NVREG_IRQ_TIMER 0x0020 -# define NVREG_IRQ_LINK 0x0040 -# define NVREG_IRQ_TX1 0x0100 -# define NVREG_IRQMASK_WANTED_1 0x005f -# define NVREG_IRQMASK_WANTED_2 0x0147 -# define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|\ - NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|\ - NVREG_IRQ_TX1)) - NvRegUnknownSetupReg6 = 0x008, -# define NVREG_UNKSETUP6_VAL 3 - /* - * NVREG_POLL_DEFAULT is the interval length of the timer source on the nic - * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms - */ - NvRegPollingInterval = 0x00c, -# define NVREG_POLL_DEFAULT 970 - NvRegMisc1 = 0x080, -# define NVREG_MISC1_HD 0x02 -# define NVREG_MISC1_FORCE 0x3b0f3c - NvRegTransmitterControl = 0x084, -# define NVREG_XMITCTL_START 0x01 - NvRegTransmitterStatus = 0x088, -# define NVREG_XMITSTAT_BUSY 0x01 - NvRegPacketFilterFlags = 0x8c, -# define NVREG_PFF_ALWAYS 0x7F0008 -# define NVREG_PFF_PROMISC 0x80 -# define NVREG_PFF_MYADDR 0x20 - NvRegOffloadConfig = 0x90, -# define NVREG_OFFLOAD_HOMEPHY 0x601 -# define NVREG_OFFLOAD_NORMAL 0x5ee - NvRegReceiverControl = 0x094, -# define NVREG_RCVCTL_START 0x01 - NvRegReceiverStatus = 0x98, -# define NVREG_RCVSTAT_BUSY 0x01 - NvRegRandomSeed = 0x9c, -# define NVREG_RNDSEED_MASK 0x00ff -# define NVREG_RNDSEED_FORCE 0x7f00 - NvRegUnknownSetupReg1 = 0xA0, -# define NVREG_UNKSETUP1_VAL 0x16070f - NvRegUnknownSetupReg2 = 0xA4, -# define NVREG_UNKSETUP2_VAL 0x16 - NvRegMacAddrA = 0xA8, - NvRegMacAddrB = 0xAC, - NvRegMulticastAddrA = 0xB0, -# define NVREG_MCASTADDRA_FORCE 0x01 - NvRegMulticastAddrB = 0xB4, - NvRegMulticastMaskA = 0xB8, - NvRegMulticastMaskB = 0xBC, - NvRegTxRingPhysAddr = 0x100, - NvRegRxRingPhysAddr = 0x104, - NvRegRingSizes = 0x108, -# define NVREG_RINGSZ_TXSHIFT 0 -# define NVREG_RINGSZ_RXSHIFT 16 - NvRegUnknownTransmitterReg = 0x10c, - NvRegLinkSpeed = 0x110, -# define NVREG_LINKSPEED_FORCE 0x10000 -# define NVREG_LINKSPEED_10 10 -# define NVREG_LINKSPEED_100 100 -# define NVREG_LINKSPEED_1000 1000 - NvRegUnknownSetupReg5 = 0x130, -# define NVREG_UNKSETUP5_BIT31 (1<<31) - NvRegUnknownSetupReg3 = 0x134, -# define NVREG_UNKSETUP3_VAL1 0x200010 - NvRegUnknownSetupReg8 = 0x13C, -# define NVREG_UNKSETUP8_VAL1 0x300010 - NvRegUnknownSetupReg7 = 0x140, -# define NVREG_UNKSETUP7_VAL 0x300010 - NvRegTxRxControl = 0x144, -# define NVREG_TXRXCTL_KICK 0x0001 -# define NVREG_TXRXCTL_BIT1 0x0002 -# define NVREG_TXRXCTL_BIT2 0x0004 -# define NVREG_TXRXCTL_IDLE 0x0008 -# define NVREG_TXRXCTL_RESET 0x0010 - NvRegMIIStatus = 0x180, -# define NVREG_MIISTAT_ERROR 0x0001 -# define NVREG_MIISTAT_LINKCHANGE 0x0008 -# define NVREG_MIISTAT_MASK 0x000f -# define NVREG_MIISTAT_MASK2 0x000f - NvRegUnknownSetupReg4 = 0x184, -# define NVREG_UNKSETUP4_VAL 8 - NvRegAdapterControl = 0x188, -# define NVREG_ADAPTCTL_START 0x02 -# define NVREG_ADAPTCTL_LINKUP 0x04 -# define NVREG_ADAPTCTL_PHYVALID 0x4000 -# define NVREG_ADAPTCTL_RUNNING 0x100000 -# define NVREG_ADAPTCTL_PHYSHIFT 24 - NvRegMIISpeed = 0x18c, -# define NVREG_MIISPEED_BIT8 (1<<8) -# define NVREG_MIIDELAY 5 - NvRegMIIControl = 0x190, -# define NVREG_MIICTL_INUSE 0x10000 -# define NVREG_MIICTL_WRITE 0x08000 -# define NVREG_MIICTL_ADDRSHIFT 5 - NvRegMIIData = 0x194, - NvRegWakeUpFlags = 0x200, -# define NVREG_WAKEUPFLAGS_VAL 0x7770 -# define NVREG_WAKEUPFLAGS_BUSYSHIFT 24 -# define NVREG_WAKEUPFLAGS_ENABLESHIFT 16 -# define NVREG_WAKEUPFLAGS_D3SHIFT 12 -# define NVREG_WAKEUPFLAGS_D2SHIFT 8 -# define NVREG_WAKEUPFLAGS_D1SHIFT 4 -# define NVREG_WAKEUPFLAGS_D0SHIFT 0 -# define NVREG_WAKEUPFLAGS_ACCEPT_MAGPAT 0x01 -# define NVREG_WAKEUPFLAGS_ACCEPT_WAKEUPPAT 0x02 -# define NVREG_WAKEUPFLAGS_ACCEPT_LINKCHANGE 0x04 - NvRegPatternCRC = 0x204, - NvRegPatternMask = 0x208, - NvRegPowerCap = 0x268, -# define NVREG_POWERCAP_D3SUPP (1<<30) -# define NVREG_POWERCAP_D2SUPP (1<<26) -# define NVREG_POWERCAP_D1SUPP (1<<25) - NvRegPowerState = 0x26c, -# define NVREG_POWERSTATE_POWEREDUP 0x8000 -# define NVREG_POWERSTATE_VALID 0x0100 -# define NVREG_POWERSTATE_MASK 0x0003 -# define NVREG_POWERSTATE_D0 0x0000 -# define NVREG_POWERSTATE_D1 0x0001 -# define NVREG_POWERSTATE_D2 0x0002 -# define NVREG_POWERSTATE_D3 0x0003 -}; - -#define IOPORT_SIZE 0x8 -#define MMIO_SIZE 0x400 - -#define NV_TX_LASTPACKET (1<<0) -#define NV_TX_RETRYERROR (1<<3) -#define NV_TX_LASTPACKET1 (1<<8) -#define NV_TX_DEFERRED (1<<10) -#define NV_TX_CARRIERLOST (1<<11) -#define NV_TX_LATECOLLISION (1<<12) -#define NV_TX_UNDERFLOW (1<<13) -#define NV_TX_ERROR (1<<14) -#define NV_TX_VALID (1<<15) -#define NV_RX_DESCRIPTORVALID (1<<0) -#define NV_RX_MISSEDFRAME (1<<1) -#define NV_RX_SUBSTRACT1 (1<<3) -#define NV_RX_BIT4 (1<<4) -#define NV_RX_ERROR1 (1<<7) -#define NV_RX_ERROR2 (1<<8) -#define NV_RX_ERROR3 (1<<9) -#define NV_RX_ERROR4 (1<<10) -#define NV_RX_CRCERR (1<<11) -#define NV_RX_OVERFLOW (1<<12) -#define NV_RX_FRAMINGERR (1<<13) -#define NV_RX_ERROR (1<<14) -#define NV_RX_AVAIL (1<<15) - -/* Miscelaneous hardware related defines: */ -#define NV_PCI_REGSZ 0x270 - -/* various timeout delays: all in usec */ -#define NV_TXRX_RESET_DELAY 4 -#define NV_TXSTOP_DELAY1 10 -#define NV_TXSTOP_DELAY1MAX 500000 -#define NV_TXSTOP_DELAY2 100 -#define NV_RXSTOP_DELAY1 10 -#define NV_RXSTOP_DELAY1MAX 500000 -#define NV_RXSTOP_DELAY2 100 -#define NV_SETUP5_DELAY 5 -#define NV_SETUP5_DELAYMAX 50000 -#define NV_POWERUP_DELAY 5 -#define NV_POWERUP_DELAYMAX 5000 -#define NV_MIIBUSY_DELAY 50 -#define NV_MIIPHY_DELAY 10 -#define NV_MIIPHY_DELAYMAX 10000 -#define NV_WAKEUPPATTERNS 5 -#define NV_WAKEUPMASKENTRIES 4 - -/* General driver defaults */ -#define NV_WATCHDOG_TIMEO (2*HZ) -#define DEFAULT_MTU 1500 - -#define RX_RING 4 -#define TX_RING 2 -/* limited to 1 packet until we understand NV_TX_LASTPACKET */ -#define TX_LIMIT_STOP 10 -#define TX_LIMIT_START 5 - -/* rx/tx mac addr + type + vlan + align + slack*/ -#define RX_NIC_BUFSIZE (DEFAULT_MTU + 64) -/* even more slack */ -#define RX_ALLOC_BUFSIZE (DEFAULT_MTU + 128) - -#define OOM_REFILL (1+HZ/20) -#define POLL_WAIT (1+HZ/100) - -#define MII_READ (-1) -#define MII_PHYSID1 0x02 /* PHYS ID 1 */ -#define MII_PHYSID2 0x03 /* PHYS ID 2 */ -#define MII_BMCR 0x00 /* Basic mode control register */ -#define MII_BMSR 0x01 /* Basic mode status register */ -#define MII_ADVERTISE 0x04 /* Advertisement control reg */ -#define MII_LPA 0x05 /* Link partner ability reg */ - -#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ -#define BMSR_BIT2 0x0004 /* Unknown... */ - -/* Link partner ability register. */ -#define LPA_SLCT 0x001f /* Same as advertise selector */ -#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */ -#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */ -#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */ -#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */ -#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */ -#define LPA_RESV 0x1c00 /* Unused... */ -#define LPA_RFAULT 0x2000 /* Link partner faulted */ -#define LPA_LPACK 0x4000 /* Link partner acked us */ -#define LPA_NPAGE 0x8000 /* Next page bit */ - -/******************************************************************************* -* Primary State Structure -******************************************************************************/ - -struct NvNetState { - uint8_t regs[MMIO_SIZE / 4]; - uint32_t phy_regs[6]; - uint8_t tx_ring_index; - uint8_t tx_ring_size; - uint8_t rx_ring_index; - uint8_t rx_ring_size; - uint8_t txrx_dma_buf[RX_ALLOC_BUFSIZE]; - FILE *packet_dump_file; - char *packet_dump_path; -} NvNetState; - -struct RingDesc { - uint32_t packet_buffer; - uint16_t length; - uint16_t flags; -}; - -const char* EmuNVNet_GetRegisterName(uint32_t addr) { - switch (addr) { - case NvRegIrqStatus: return "NvRegIrqStatus"; - case NvRegIrqMask: return "NvRegIrqMask"; - case NvRegUnknownSetupReg6: return "NvRegUnknownSetupReg6"; - case NvRegPollingInterval: return "NvRegPollingInterval"; - case NvRegMisc1: return "NvRegMisc1"; - case NvRegTransmitterControl: return "NvRegTransmitterControl"; - case NvRegTransmitterStatus: return "NvRegTransmitterStatus"; - case NvRegPacketFilterFlags: return "NvRegPacketFilterFlags"; - case NvRegOffloadConfig: return "NvRegOffloadConfig"; - case NvRegReceiverControl: return "NvRegReceiverControl"; - case NvRegReceiverStatus: return "NvRegReceiverStatus"; - case NvRegRandomSeed: return "NvRegRandomSeed"; - case NvRegUnknownSetupReg1: return "NvRegUnknownSetupReg1"; - case NvRegUnknownSetupReg2: return "NvRegUnknownSetupReg2"; - case NvRegMacAddrA: return "NvRegMacAddrA"; - case NvRegMacAddrB: return "NvRegMacAddrB"; - case NvRegMulticastAddrA: return "NvRegMulticastAddrA"; - case NvRegMulticastAddrB: return "NvRegMulticastAddrB"; - case NvRegMulticastMaskA: return "NvRegMulticastMaskA"; - case NvRegMulticastMaskB: return "NvRegMulticastMaskB"; - case NvRegTxRingPhysAddr: return "NvRegTxRingPhysAddr"; - case NvRegRxRingPhysAddr: return "NvRegRxRingPhysAddr"; - case NvRegRingSizes: return "NvRegRingSizes"; - case NvRegUnknownTransmitterReg: return "NvRegUnknownTransmitterReg"; - case NvRegLinkSpeed: return "NvRegLinkSpeed"; - case NvRegUnknownSetupReg5: return "NvRegUnknownSetupReg5"; - case NvRegUnknownSetupReg3: return "NvRegUnknownSetupReg3"; - case NvRegUnknownSetupReg8: return "NvRegUnknownSetupReg8"; - case NvRegUnknownSetupReg7: return "NvRegUnknownSetupReg7"; - case NvRegTxRxControl: return "NvRegTxRxControl"; - case NvRegMIIStatus: return "NvRegMIIStatus"; - case NvRegUnknownSetupReg4: return "NvRegUnknownSetupReg4"; - case NvRegAdapterControl: return "NvRegAdapterControl"; - case NvRegMIISpeed: return "NvRegMIISpeed"; - case NvRegMIIControl: return "NvRegMIIControl"; - case NvRegMIIData: return "NvRegMIIData"; - case NvRegWakeUpFlags: return "NvRegWakeUpFlags"; - case NvRegPatternCRC: return "NvRegPatternCRC"; - case NvRegPatternMask: return "NvRegPatternMask"; - case NvRegPowerCap: return "NvRegPowerCap"; - case NvRegPowerState: return "NvRegPowerState"; - default: return "Unknown"; - } -} - -const char* EmuNVNet_GetMiiRegisterName(uint8_t reg) { - switch (reg) { - case MII_PHYSID1: return "MII_PHYSID1"; - case MII_PHYSID2: return "MII_PHYSID2"; - case MII_BMCR: return "MII_BMCR"; - case MII_BMSR: return "MII_BMSR"; - case MII_ADVERTISE: return "MII_ADVERTISE"; - case MII_LPA: return "MII_LPA"; - default: return "Unknown"; - } -} - -uint32_t EmuNVNet_GetRegister(uint32_t addr, unsigned int size) { - switch (size) { - case sizeof(uint32_t) : - return ((uint32_t *)NvNetState.regs)[addr >> 2]; - case sizeof(uint16_t) : - return ((uint16_t *)NvNetState.regs)[addr >> 1]; - case sizeof(uint8_t) : - return NvNetState.regs[addr]; - } - - return 0; -} - -void EmuNVNet_SetRegister(uint32_t addr, uint32_t value, unsigned int size) { - switch (size) { - case sizeof(uint32_t) : - ((uint32_t *)NvNetState.regs)[addr >> 2] = value; - break; - case sizeof(uint16_t) : - ((uint16_t *)NvNetState.regs)[addr >> 1] = (uint16_t)value; - break; - case sizeof(uint8_t) : - NvNetState.regs[addr] = (uint8_t)value; - break; - } -} - -void EmuNVNet_UpdateIRQ() { - if (EmuNVNet_GetRegister(NvRegIrqMask, 4) && - EmuNVNet_GetRegister(NvRegIrqStatus, 4)) { - log_debug("EmuNVNet: Asserting IRQ\n"); - // TODO: HalSystemInterrupts[4].Assert(true); - } - else { - // TODO: HalSystemInterrupts[4].Assert(false); - } -} - -int EmuNVNet_MiiReadWrite(uint64_t val) { - uint32_t mii_ctl; - int write, retval, phy_addr, reg; - - retval = 0; - mii_ctl = EmuNVNet_GetRegister(NvRegMIIControl, 4); - - phy_addr = (mii_ctl >> NVREG_MIICTL_ADDRSHIFT) & 0x1f; - reg = mii_ctl & ((1 << NVREG_MIICTL_ADDRSHIFT) - 1); - write = mii_ctl & NVREG_MIICTL_WRITE; - - log_debug("nvnet mii %s: phy 0x%x %s [0x%x]\n", write ? "write" : "read", phy_addr, EmuNVNet_GetMiiRegisterName(reg), reg); - - if (phy_addr != 1) { - return -1; - } - - if (write) { - return retval; - } - - switch (reg) { - case MII_BMSR: - /* Phy initialization code waits for BIT2 to be set.. If not set, - * software may report controller as not running */ - retval = BMSR_ANEGCOMPLETE | BMSR_BIT2; - break; - case MII_ADVERTISE: - /* Fall through... */ - case MII_LPA: - retval = LPA_10HALF | LPA_10FULL; - retval |= LPA_100HALF | LPA_100FULL | LPA_100BASE4; - break; - default: - break; - } - - return retval; -} - -uint32_t EmuNVNet_Read(uint32_t addr, int size) { - //log_debug("NET : Read%d: %s (0x%.8X)\n", size, EmuNVNet_GetRegisterName(addr), addr); - - switch (addr) { - case NvRegMIIData: - return EmuNVNet_MiiReadWrite(MII_READ); - case NvRegMIIControl: - return EmuNVNet_GetRegister(addr, size) & ~NVREG_MIICTL_INUSE; - case NvRegMIIStatus: - return 0; - } - - return EmuNVNet_GetRegister(addr, size); -} - -void EmuNVNet_Write(uint32_t addr, uint32_t value, int size) { - switch (addr) { - case NvRegRingSizes: - EmuNVNet_SetRegister(addr, value, size); - NvNetState.rx_ring_size = ((value >> NVREG_RINGSZ_RXSHIFT) & 0xffff) + 1; - NvNetState.tx_ring_size = ((value >> NVREG_RINGSZ_TXSHIFT) & 0xffff) + 1; - break; - case NvRegMIIData: - EmuNVNet_MiiReadWrite(value); - break; - case NvRegTxRxControl: - if (value == NVREG_TXRXCTL_KICK) { - //log_debug("NvRegTxRxControl = NVREG_TXRXCTL_KICK!\n"); - //log_warning("TODO: nvnet_dma_packet_from_guest"); - // nvnet_dma_packet_from_guest(s); - } - - if (value & NVREG_TXRXCTL_BIT2) { - EmuNVNet_SetRegister(NvRegTxRxControl, NVREG_TXRXCTL_IDLE, 4); - break; - } - - if (value & NVREG_TXRXCTL_BIT1) { - EmuNVNet_SetRegister(NvRegIrqStatus, 0, 4); - break; - } - else if (value == 0) { - uint32_t temp = EmuNVNet_GetRegister(NvRegUnknownSetupReg3, 4); - if (temp == NVREG_UNKSETUP3_VAL1) { - /* forcedeth waits for this bit to be set... */ - EmuNVNet_SetRegister(NvRegUnknownSetupReg5, - NVREG_UNKSETUP5_BIT31, 4); - break; - } - } - EmuNVNet_SetRegister(NvRegTxRxControl, value, size); - break; - case NvRegIrqMask: - EmuNVNet_SetRegister(addr, value, size); - EmuNVNet_UpdateIRQ(); - break; - case NvRegIrqStatus: - EmuNVNet_SetRegister(addr, EmuNVNet_GetRegister(addr, size) & ~value, size); - EmuNVNet_UpdateIRQ(); - break; - default: - EmuNVNet_SetRegister(addr, value, size); - break; - } - - //log_debug("NET : Write%d: %s (0x%.8X) = 0x%.8X\n", size, EmuNVNet_GetRegisterName(addr), addr, value); -} - -/* NVNetDevice */ - NVNetDevice::NVNetDevice() : PCIDevice(PCI_HEADER_TYPE_NORMAL, PCI_VENDOR_ID_NVIDIA, 0x01C3, 0xB1, 0x02, 0x00, 0x00) // Ethernet controller @@ -541,8 +67,8 @@ void NVNetDevice::PCIMMIORead(int barIndex, uint32_t addr, uint32_t *value, uint return; } - *value = EmuNVNet_Read(addr, size * 8); // For now, forward - return; + *value = 0; + log_warning("NVNetDevice::PCIMMIORead: Unimplemented read! bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); } void NVNetDevice::PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint8_t size) { @@ -552,7 +78,7 @@ void NVNetDevice::PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint return; } - EmuNVNet_Write(addr, value, size * 8); // For now, forward + log_warning("NVNetDevice::PCIMMIOWrite: Unimplemented write! bar = %d, address = 0x%x, value = 0x%x, size = %u\n", barIndex, addr, value, size); } } diff --git a/modules/core/src/common/strikebox/hw/pci/usb_pci.cpp b/modules/core/src/common/strikebox/hw/pci/usb_pci.cpp index e237993..8ba395c 100644 --- a/modules/core/src/common/strikebox/hw/pci/usb_pci.cpp +++ b/modules/core/src/common/strikebox/hw/pci/usb_pci.cpp @@ -1,60 +1,9 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->USBController->USBDevice.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#include -#include -#include +#include "strikebox/hw/pci/usb_pci.h" #include "strikebox/log.h" -#include "strikebox/hw/pci/usb_pci.h" -#include "strikebox/hw/ohci/ohci.h" - namespace strikebox { -#define SETUP_STATE_IDLE 0 -#define SETUP_STATE_SETUP 1 -#define SETUP_STATE_DATA 2 -#define SETUP_STATE_ACK 3 -#define SETUP_STATE_PARAM 4 - USBPCIDevice::USBPCIDevice(uint8_t irqn, virt86::VirtualProcessor& vp) : PCIDevice(PCI_HEADER_TYPE_NORMAL, PCI_VENDOR_ID_NVIDIA, 0x01C2, 0xB1, 0x0c, 0x03, 0x10) // USB OHCI @@ -84,1186 +33,31 @@ void USBPCIDevice::Init() { // Unknown registers Write16(m_configSpace, 0x46, 0xda02); Write32(m_configSpace, 0x4c, 0x2); - - if (m_irqn == 1) { - m_PciPath = "pci.0:02.0"; - } - else { - m_PciPath = "pci.0:03.0"; - } - - m_HostController = new OHCI(m_vp, m_irqn, this); } void USBPCIDevice::Reset() { } void USBPCIDevice::PCIMMIORead(int barIndex, uint32_t addr, uint32_t *value, uint8_t size) { - // barIndex must be zero since we created the USB devices with a zero index in Init() - assert(barIndex == 0); + //log_spew("USBPCIDevice::PCIMMIORead: bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); + if (barIndex != 0) { + log_spew("USBPCIDevice::PCIMMIORead: Unhandled BAR access: %d, address = 0x%x, size = %u\n", barIndex, addr, size); + *value = 0; + return; + } - // read the register of the corresponding HC - *value = m_HostController->OHCI_ReadRegister(addr); + *value = 0; + log_spew("USBPCIDevice::PCIMMIORead: Unimplemented read! bar = %d, address = 0x%x, size = %u\n", barIndex, addr, size); } void USBPCIDevice::PCIMMIOWrite(int barIndex, uint32_t addr, uint32_t value, uint8_t size) { - // barIndex must be zero since we created the USB devices with a zero index in Init() - assert(barIndex == 0); - - // write the register of the corresponding HC - m_HostController->OHCI_WriteRegister(addr, value); -} - - -void USBPCIDevice::USB_RegisterPort(USBPort* Port, int Index, int SpeedMask, USBPortOps* Ops) { - Port->PortIndex = Index; - Port->SpeedMask = SpeedMask; - Port->Operations = Ops; - USB_PortLocation(Port, nullptr, Index + 1); - m_FreePorts.push_back(Port); -} - -void USBPCIDevice::USB_UnregisterPort(USBPort* Port) { - auto it = std::find(m_FreePorts.begin(), m_FreePorts.end(), Port); - assert(it != m_FreePorts.end()); - m_FreePorts.erase(it); -} - -void USBPCIDevice::USB_PortReset(USBPort* Port) { - XboxDeviceState* dev = Port->Dev; - - assert(dev != nullptr); - USB_Detach(Port); - USB_Attach(Port); - USB_DeviceReset(dev); -} - -void USBPCIDevice::USB_Attach(USBPort* Port) { - XboxDeviceState* dev = Port->Dev; - - assert(dev != nullptr); - assert(dev->Attached); - assert(dev->State == USB_STATE_NOTATTACHED); - Port->Operations->attach(Port); - dev->State = USB_STATE_ATTACHED; - USB_DeviceHandleAttach(dev); -} - -void USBPCIDevice::USB_Detach(USBPort* Port) { - XboxDeviceState* dev = Port->Dev; - - assert(dev != nullptr); - assert(dev->State != USB_STATE_NOTATTACHED); - Port->Operations->detach(Port); - dev->State = USB_STATE_NOTATTACHED; -} - -void USBPCIDevice::USB_Wakeup(USBEndpoint* ep) { - XboxDeviceState* dev = ep->Dev; - - if (dev->RemoteWakeup && dev->Port && dev->Port->Operations->wakeup) { - dev->Port->Operations->wakeup(dev->Port); - } -} - -void USBPCIDevice::USB_DeviceReset(XboxDeviceState* dev) { - if (dev == nullptr || !dev->Attached) { + //log_spew("USBPCIDevice::PCIMMIOWrite: bar = %d, address = 0x%x, value = 0x%x, size = %u\n", barIndex, addr, value, size); + if (barIndex != 0) { + log_spew("USBPCIDevice::PCIMMIOWrite: Unhandled BAR access: %d, address = 0x%x, value = 0x%x, size = %u\n", barIndex, addr, value, size); return; } - dev->RemoteWakeup = 0; - dev->Addr = 0; - dev->State = USB_STATE_DEFAULT; - USB_DeviceHandleReset(dev); -} - -XboxDeviceState* USBPCIDevice::USB_FindDevice(USBPort* Port, uint8_t Addr) { - XboxDeviceState* dev = Port->Dev; - - if (dev == nullptr || !dev->Attached || dev->State != USB_STATE_DEFAULT) { - return nullptr; - } - if (dev->Addr == Addr) { - return dev; - } - - return USB_DeviceFindDevice(dev, Addr); -} - -USBEndpoint* USBPCIDevice::USB_GetEP(XboxDeviceState* Dev, int Pid, int Ep) { - USBEndpoint* eps; - - if (Dev == nullptr) { - return nullptr; - } - eps = (Pid == USB_TOKEN_IN) ? Dev->EP_in : Dev->EP_out; - if (Ep == 0) { - return &Dev->EP_ctl; // EndpointNumber zero represents the default control endpoint - } - assert(Pid == USB_TOKEN_IN || Pid == USB_TOKEN_OUT); - assert(Ep > 0 && Ep <= USB_MAX_ENDPOINTS); - - return eps + Ep - 1; -} - -void USBPCIDevice::USB_PacketSetup(USBPacket* p, int Pid, USBEndpoint* Ep, unsigned int Stream, - uint64_t Id, bool ShortNotOK, bool IntReq) { - assert(!USB_IsPacketInflight(p)); - assert(p->IoVec.IoVecStruct != nullptr); - p->Id = Id; - p->Pid = Pid; - p->Endpoint = Ep; - p->Stream = Stream; - p->Status = USB_RET_SUCCESS; - p->ActualLength = 0; - p->Parameter = 0ull; - p->ShortNotOK = ShortNotOK; - p->IntReq = IntReq; - IoVecReset(&p->IoVec); - p->State = USB_PACKET_SETUP; -} - -bool USBPCIDevice::USB_IsPacketInflight(USBPacket* p) { - return (p->State == USB_PACKET_QUEUED || p->State == USB_PACKET_ASYNC); -} - -void USBPCIDevice::USB_PacketAddBuffer(USBPacket* p, void* ptr, size_t len) { - IoVecAdd(&p->IoVec, ptr, len); -} - -void USBPCIDevice::USB_HandlePacket(XboxDeviceState* dev, USBPacket* p) { - if (dev == nullptr) { - p->Status = USB_RET_NODEV; - return; - } - assert(dev == p->Endpoint->Dev); - assert(dev->State == USB_STATE_DEFAULT); - USB_PacketCheckState(p, USB_PACKET_SETUP); - assert(p->Endpoint != nullptr); - - // Submitting a new packet clears halt - if (p->Endpoint->Halted) { - assert(QTAILQ_EMPTY(&p->Endpoint->Queue)); - p->Endpoint->Halted = false; - } - - if (QTAILQ_EMPTY(&p->Endpoint->Queue) || p->Endpoint->Pipeline || p->Stream) { - USB_ProcessOne(p); - if (p->Status == USB_RET_ASYNC) { - // hcd drivers cannot handle async for isoc - assert(p->Endpoint->Type != USB_ENDPOINT_XFER_ISOC); - // using async for interrupt packets breaks migration - assert(p->Endpoint->Type != USB_ENDPOINT_XFER_INT); - p->State = USB_PACKET_ASYNC; - QTAILQ_INSERT_TAIL(&p->Endpoint->Queue, p, Queue); - } - else if (p->Status == USB_RET_ADD_TO_QUEUE) { - USB_QueueOne(p); - } - else { - // When pipelining is enabled usb-devices must always return async, - // otherwise packets can complete out of order! - assert(p->Stream || !p->Endpoint->Pipeline || - QTAILQ_EMPTY(&p->Endpoint->Queue)); - if (p->Status != USB_RET_NAK) { - p->State = USB_PACKET_COMPLETE; - } - } - } - else { - USB_QueueOne(p); - } -} - -void USBPCIDevice::USB_QueueOne(USBPacket* p) { - p->State = USB_PACKET_QUEUED; - QTAILQ_INSERT_TAIL(&p->Endpoint->Queue, p, Queue); - p->Status = USB_RET_ASYNC; -} - -void USBPCIDevice::USB_PacketCheckState(USBPacket* p, USBPacketState expected) { - if (p->State == expected) { - return; - } - - log_warning("USB: packet state check failed!\n"); - assert(0); -} - -void USBPCIDevice::USB_ProcessOne(USBPacket* p) { - XboxDeviceState* dev = p->Endpoint->Dev; - - // Handlers expect status to be initialized to USB_RET_SUCCESS, but it - // can be USB_RET_NAK here from a previous usb_process_one() call, - // or USB_RET_ASYNC from going through usb_queue_one(). - p->Status = USB_RET_SUCCESS; - - if (p->Endpoint->Num == 0) { - // Info: All devices must support endpoint zero. This is the endpoint which receives all of the devices control - // and status requests during enumeration and throughout the duration while the device is operational on the bus - if (p->Parameter) { - USB_DoParameter(dev, p); - return; - } - switch (p->Pid) { - case USB_TOKEN_SETUP: - { - USB_DoTokenSetup(dev, p); - break; - } - case USB_TOKEN_IN: - { - DoTokenIn(dev, p); - break; - } - case USB_TOKEN_OUT: - { - DoTokenOut(dev, p); - break; - } - default: - p->Status = USB_RET_STALL; - } - } - else { - // data pipe - USB_DeviceHandleData(dev, p); - } -} - -void USBPCIDevice::USB_DoParameter(XboxDeviceState* s, USBPacket* p) { - int i, request, value, index; - - for (i = 0; i < 8; i++) { - s->SetupBuffer[i] = p->Parameter >> (i * 8); - } - - s->SetupState = SETUP_STATE_PARAM; - s->SetupLength = (s->SetupBuffer[7] << 8) | s->SetupBuffer[6]; - s->SetupIndex = 0; - - request = (s->SetupBuffer[0] << 8) | s->SetupBuffer[1]; - value = (s->SetupBuffer[3] << 8) | s->SetupBuffer[2]; - index = (s->SetupBuffer[5] << 8) | s->SetupBuffer[4]; - - if (s->SetupLength > sizeof(s->DataBuffer)) { - log_debug("USB: ctrl buffer too small (%d > %zu)\n", s->SetupLength, sizeof(s->DataBuffer)); - p->Status = USB_RET_STALL; - return; - } - - if (p->Pid == USB_TOKEN_OUT) { - USB_PacketCopy(p, s->DataBuffer, s->SetupLength); - } - - USB_DeviceHandleControl(s, p, request, value, index, s->SetupLength, s->DataBuffer); - if (p->Status == USB_RET_ASYNC) { - return; - } - - if (p->ActualLength < s->SetupLength) { - s->SetupLength = p->ActualLength; - } - if (p->Pid == USB_TOKEN_IN) { - p->ActualLength = 0; - USB_PacketCopy(p, s->DataBuffer, s->SetupLength); - } -} - -void USBPCIDevice::USB_DoTokenSetup(XboxDeviceState* s, USBPacket* p) { - int request, value, index; - - // From the standard "Every Setup packet has eight bytes." - if (p->IoVec.Size != 8) { - p->Status = USB_RET_STALL; - return; - } - - // Info: name, offset, size, info (sizes are in bytes) - // bmRequestType, 1, 1, determines the direction of the request, type of request and designated recipient - // bRequest, 1, 1, determines the request being made - // wValue, 2, 2, it is used to pass a parameter to the device, specific to the request - // wIndex, 4, 2, often used in requests to specify an endpoint or an interface - // wLength, 6, 2, number of bytes to transfer if there is a data phase - // The wValue and wIndex fields allow parameters to be passed with the request - - USB_PacketCopy(p, s->SetupBuffer, p->IoVec.Size); - p->ActualLength = 0; - s->SetupLength = (s->SetupBuffer[7] << 8) | s->SetupBuffer[6]; - s->SetupIndex = 0; - - request = (s->SetupBuffer[0] << 8) | s->SetupBuffer[1]; - value = (s->SetupBuffer[3] << 8) | s->SetupBuffer[2]; - index = (s->SetupBuffer[5] << 8) | s->SetupBuffer[4]; - - if (s->SetupBuffer[0] & USB_DIR_IN) { - USB_DeviceHandleControl(s, p, request, value, index, s->SetupLength, s->DataBuffer); - if (p->Status == USB_RET_ASYNC) { - s->SetupState = SETUP_STATE_SETUP; - } - if (p->Status != USB_RET_SUCCESS) { - return; - } - - if (p->ActualLength < s->SetupLength) { - s->SetupLength = p->ActualLength; - } - s->SetupState = SETUP_STATE_DATA; - } - else { - if (s->SetupLength > sizeof(s->DataBuffer)) { - log_debug("USB: ctrl buffer too small (%d > %zu)\n", s->SetupLength, sizeof(s->DataBuffer)); - p->Status = USB_RET_STALL; - return; - } - if (s->SetupLength == 0) { - s->SetupState = SETUP_STATE_ACK; - } - else { - s->SetupState = SETUP_STATE_DATA; - } - } - - p->ActualLength = 8; -} - -void USBPCIDevice::DoTokenIn(XboxDeviceState* s, USBPacket* p) { - int request, value, index; - - assert(p->Endpoint->Num == 0); - - request = (s->SetupBuffer[0] << 8) | s->SetupBuffer[1]; - value = (s->SetupBuffer[3] << 8) | s->SetupBuffer[2]; - index = (s->SetupBuffer[5] << 8) | s->SetupBuffer[4]; - - switch (s->SetupState) { - case SETUP_STATE_ACK: - if (!(s->SetupBuffer[0] & USB_DIR_IN)) { - USB_DeviceHandleControl(s, p, request, value, index, s->SetupLength, s->DataBuffer); - if (p->Status == USB_RET_ASYNC) { - return; - } - s->SetupState = SETUP_STATE_IDLE; - p->ActualLength = 0; - } - break; - - case SETUP_STATE_DATA: - if (s->SetupBuffer[0] & USB_DIR_IN) { - unsigned int len = s->SetupLength - s->SetupIndex; - if (len > p->IoVec.Size) { - len = p->IoVec.Size; - } - USB_PacketCopy(p, s->DataBuffer + s->SetupIndex, len); - s->SetupIndex += len; - if (s->SetupIndex >= s->SetupLength) { - s->SetupState = SETUP_STATE_ACK; - } - return; - } - s->SetupState = SETUP_STATE_IDLE; - p->Status = USB_RET_STALL; - break; - - default: - p->Status = USB_RET_STALL; - } -} - -void USBPCIDevice::DoTokenOut(XboxDeviceState* s, USBPacket* p) { - assert(p->Endpoint->Num == 0); - - switch (s->SetupState) { - case SETUP_STATE_ACK: - if (s->SetupBuffer[0] & USB_DIR_IN) { - s->SetupState = SETUP_STATE_IDLE; - // transfer OK - } - else { - // ignore additional output - } - break; - - case SETUP_STATE_DATA: - if (!(s->SetupBuffer[0] & USB_DIR_IN)) { - unsigned int len = s->SetupLength - s->SetupIndex; - if (len > p->IoVec.Size) { - len = p->IoVec.Size; - } - USB_PacketCopy(p, s->DataBuffer + s->SetupIndex, len); - s->SetupIndex += len; - if (s->SetupIndex >= s->SetupLength) { - s->SetupState = SETUP_STATE_ACK; - } - return; - } - s->SetupState = SETUP_STATE_IDLE; - p->Status = USB_RET_STALL; - break; - - default: - p->Status = USB_RET_STALL; - } -} - -void USBPCIDevice::USB_PacketCopy(USBPacket* p, void* ptr, size_t bytes) { - IOVector* iov = &p->IoVec; - - assert(p->ActualLength >= 0); - assert(p->ActualLength + bytes <= iov->Size); - switch (p->Pid) { - case USB_TOKEN_SETUP: - case USB_TOKEN_OUT: - IoVecTobuffer(iov->IoVecStruct, iov->IoVecNumber, p->ActualLength, ptr, bytes); - break; - case USB_TOKEN_IN: - IoVecFromBuffer(iov->IoVecStruct, iov->IoVecNumber, p->ActualLength, ptr, bytes); - break; - default: - log_fatal("USB: %s has an invalid pid: %x\n", __func__, p->Pid); - break; - } - p->ActualLength += bytes; -} - -int USBPCIDevice::USB_DeviceInit(XboxDeviceState* dev) { - USBDeviceClass * klass = dev->klass; - if (klass->init) { - return klass->init(dev); - - } - - return 0; -} - -XboxDeviceState* USBPCIDevice::USB_DeviceFindDevice(XboxDeviceState* dev, uint8_t Addr) { - USBDeviceClass* klass = dev->klass; - if (klass->find_device) { - return klass->find_device(dev, Addr); - } - - return nullptr; -} - -void USBPCIDevice::USB_DeviceCancelPacket(XboxDeviceState* dev, USBPacket* p) { - USBDeviceClass* klass = dev->klass; - if (klass->cancel_packet) { - klass->cancel_packet(dev, p); - } -} - -void USBPCIDevice::USB_DeviceHandleDestroy(XboxDeviceState* dev) { - USBDeviceClass* klass = dev->klass; - if (klass->handle_destroy) { - klass->handle_destroy(); - } -} - -void USBPCIDevice::USB_DeviceHandleAttach(XboxDeviceState* dev) { - USBDeviceClass* klass = dev->klass; - if (klass->handle_attach) { - klass->handle_attach(dev); - } -} - -void USBPCIDevice::USB_DeviceHandleReset(XboxDeviceState* dev) { - USBDeviceClass* klass = dev->klass; - if (klass->handle_reset) { - klass->handle_reset(dev); - } -} - -void USBPCIDevice::USB_DeviceHandleControl(XboxDeviceState* dev, USBPacket* p, int request, int value, int index, int length, uint8_t* data) { - USBDeviceClass* klass = dev->klass; - if (klass->handle_control) { - klass->handle_control(dev, p, request, value, index, length, data); - } -} - -void USBPCIDevice::USB_DeviceHandleData(XboxDeviceState* dev, USBPacket* p) { - USBDeviceClass* klass = dev->klass; - if (klass->handle_data) { - klass->handle_data(dev, p); - } -} - -void USBPCIDevice::USB_DeviceSetInterface(XboxDeviceState* dev, int iface, int alt_old, int alt_new) { - USBDeviceClass* klass = dev->klass; - if (klass->set_interface) { - klass->set_interface(dev, iface, alt_old, alt_new); - } -} - -void USBPCIDevice::USB_DeviceFlushEPqueue(XboxDeviceState* dev, USBEndpoint* ep) { - USBDeviceClass *klass = dev->klass; - if (klass->flush_ep_queue) { - klass->flush_ep_queue(dev, ep); - } -} - - -void USBPCIDevice::USB_DeviceEPstopped(XboxDeviceState* dev, USBEndpoint* EP) { - USBDeviceClass* klass = dev->klass; - if (klass->ep_stopped) { - klass->ep_stopped(dev, EP); - - } -} - -void USBPCIDevice::USB_CancelPacket(USBPacket* p) { - bool callback = (p->State == USB_PACKET_ASYNC); - assert(USB_IsPacketInflight(p)); - p->State = USB_PACKET_CANCELED; - QTAILQ_REMOVE(&p->Endpoint->Queue, p, Queue); - if (callback) { - USB_DeviceCancelPacket(p->Endpoint->Dev, p); - } -} - -void USBPCIDevice::USB_EPsetType(XboxDeviceState* dev, int pid, int ep, uint8_t type) { - USBEndpoint* uep = USB_GetEP(dev, pid, ep); - uep->Type = type; -} - -void USBPCIDevice::USB_EPsetIfnum(XboxDeviceState* dev, int pid, int ep, uint8_t ifnum) { - USBEndpoint* uep = USB_GetEP(dev, pid, ep); - uep->IfNum = ifnum; -} - -void USBPCIDevice::USB_EPsetMaxPacketSize(XboxDeviceState* dev, int pid, int ep, uint16_t raw) { - USBEndpoint* uep = USB_GetEP(dev, pid, ep); - - // Dropped from XQEMU the calculation max_packet_size = size * microframes since that's only true - // for high speed (usb 2.0) devices - uep->MaxPacketSize = raw & 0x7FF; -} - -void USBPCIDevice::USB_PortLocation(USBPort* downstream, USBPort* upstream, int portnr) { - if (upstream) { - downstream->Path = upstream->Path + '.' + std::to_string(portnr); - } - else { - downstream->Path = std::to_string(portnr); - } -} - -void USBPCIDevice::USB_DeviceAttach(XboxDeviceState* dev) { - USBPort * port = dev->Port; - - assert(port != nullptr); - assert(!dev->Attached); - - dev->Attached++; - USB_Attach(port); -} - -void USBPCIDevice::USB_DeviceDetach(XboxDeviceState* dev) { - USBPort* port = dev->Port; - - assert(port != nullptr); - assert(dev->Attached); - - USB_Detach(port); - dev->Attached--; -} - -void USBPCIDevice::USB_EpInit(XboxDeviceState* dev) { - USB_EpReset(dev); - QTAILQ_INIT(&dev->EP_ctl.Queue); - for (int ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { - QTAILQ_INIT(&dev->EP_in[ep].Queue); - QTAILQ_INIT(&dev->EP_out[ep].Queue); - } -} - -void USBPCIDevice::USB_EpReset(XboxDeviceState* dev) { - dev->EP_ctl.Num = 0; - dev->EP_ctl.Type = USB_ENDPOINT_XFER_CONTROL; - dev->EP_ctl.IfNum = 0; - dev->EP_ctl.MaxPacketSize = 64; - dev->EP_ctl.Dev = dev; - dev->EP_ctl.Pipeline = false; - for (int ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { - dev->EP_in[ep].Num = ep + 1; - dev->EP_out[ep].Num = ep + 1; - dev->EP_in[ep].pid = USB_TOKEN_IN; - dev->EP_out[ep].pid = USB_TOKEN_OUT; - dev->EP_in[ep].Type = USB_ENDPOINT_XFER_INVALID; - dev->EP_out[ep].Type = USB_ENDPOINT_XFER_INVALID; - dev->EP_in[ep].IfNum = USB_INTERFACE_INVALID; - dev->EP_out[ep].IfNum = USB_INTERFACE_INVALID; - dev->EP_in[ep].MaxPacketSize = 0; - dev->EP_out[ep].MaxPacketSize = 0; - dev->EP_in[ep].Dev = dev; - dev->EP_out[ep].Dev = dev; - dev->EP_in[ep].Pipeline = false; - dev->EP_out[ep].Pipeline = false; - } -} - -/* - * From XQEMU: - * This function creates a serial number for a usb device. - * The serial number should: - * (a) Be unique within the emulator. - * (b) Be constant, so you don't get a new one each - * time the guest is started. - * So we are using the physical location to generate a serial number - * from it. It has three pieces: First a fixed, device-specific - * prefix. Second the device path of the host controller (which is - * the pci address in most cases). Third the physical port path. - * Results in serial numbers like this: "314159-0000:00:1d.7-3". - */ -void USBPCIDevice::USB_CreateSerial(XboxDeviceState* dev, std::string&& str) { - const USBDesc* desc = USBDesc_GetUsbDeviceDesc(dev); - int index = desc->id.iSerialNumber; - - assert(index != 0 && str.empty() == false); - str += '-'; - str += m_PciPath; - str += ('-' + dev->Port->Path); - - USBDesc_SetString(dev, index, std::move(str)); -} - -const USBDesc* USBPCIDevice::USBDesc_GetUsbDeviceDesc(XboxDeviceState* dev) { - USBDeviceClass* klass = dev->klass; - if (dev->UsbDesc) { - return dev->UsbDesc; - } - return klass->usb_desc; -} - -void USBPCIDevice::USBDesc_Init(XboxDeviceState* dev) { - const USBDesc* desc = USBDesc_GetUsbDeviceDesc(dev); - - assert(desc != nullptr); - dev->Speed = USB_SPEED_FULL; - dev->SpeedMask = 0; - if (desc->full) { - dev->SpeedMask |= USB_SPEED_MASK_FULL; - } - USBDesc_SetDefaults(dev); -} - -void USBPCIDevice::USBDesc_SetDefaults(XboxDeviceState* dev) { - const USBDesc *desc = USBDesc_GetUsbDeviceDesc(dev); - - assert(desc != nullptr); - switch (dev->Speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - { - dev->Device = desc->full; - break; - } - default: - log_warning("USB: Unknown speed parameter %d set in %s", dev->ProductDesc.c_str()); - } - USBDesc_SetConfig(dev, 0); -} - -int USBPCIDevice::USBDesc_SetConfig(XboxDeviceState* dev, int value) { - int i; - - if (value == 0) { // default configuration - dev->Configuration = 0; - dev->NumInterfaces = 0; - dev->Config = nullptr; - } - else { - for (i = 0; i < dev->Device->bNumConfigurations; i++) { // select the configuration specified - if (dev->Device->confs[i].bConfigurationValue == value) { - dev->Configuration = value; - dev->NumInterfaces = dev->Device->confs[i].bNumInterfaces; - dev->Config = dev->Device->confs + i; - assert(dev->NumInterfaces <= USB_MAX_INTERFACES); - } - } - if (i < dev->Device->bNumConfigurations) { - return -1; - } - } - - for (i = 0; i < dev->NumInterfaces; i++) { // setup all interfaces for the selected configuration - USBDesc_SetInterface(dev, i, 0); - } - for (; i < USB_MAX_INTERFACES; i++) { // null the remaining interfaces - dev->AltSetting[i] = 0; - dev->Ifaces[i] = nullptr; - } - - return 0; -} - -int USBPCIDevice::USBDesc_SetInterface(XboxDeviceState* dev, int index, int value) { - const USBDescIface* iface; - int old; - - iface = USBDesc_FindInterface(dev, index, value); - if (iface == nullptr) { - return -1; - } - - old = dev->AltSetting[index]; - dev->AltSetting[index] = value; - dev->Ifaces[index] = iface; - USBDesc_EpInit(dev); - - if (old != value) { - USB_DeviceSetInterface(dev, index, old, value); - } - return 0; -} - -const USBDescIface* USBPCIDevice::USBDesc_FindInterface(XboxDeviceState* dev, int nif, int alt) { - const USBDescIface* iface; - int i; - - if (!dev->Config) { // no configuration descriptor here, nothing to search - return nullptr; - } - for (i = 0; i < dev->Config->nif; i++) { // find the desired interface - iface = &dev->Config->ifs[i]; - if (iface->bInterfaceNumber == nif && - iface->bAlternateSetting == alt) { - return iface; - } - } - return nullptr; // not found -} - -void USBPCIDevice::USBDesc_EpInit(XboxDeviceState* dev) { - const USBDescIface *iface; - int i, e, pid, ep; - - USB_EpInit(dev); // reset endpoints (because we changed descriptors in use?) - for (i = 0; i < dev->NumInterfaces; i++) { - iface = dev->Ifaces[i]; - if (iface == nullptr) { - continue; - } - for (e = 0; e < iface->bNumEndpoints; e++) { - // From the standard: - // "bEndpointAddress: - // Bit 3...0: The endpoint number - // Bit 6...4: Reserved, reset to zero - // Bit 7: Direction -> 0 = OUT endpoint, 1 = IN endpoint - // bmAttributes: - // Bit 1..0: Transfer Type - // 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt. All other bits are reserved" - pid = (iface->eps[e].bEndpointAddress & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; - ep = iface->eps[e].bEndpointAddress & 0xF; - USB_EPsetType(dev, pid, ep, iface->eps[e].bmAttributes & 0x03); - USB_EPsetIfnum(dev, pid, ep, iface->bInterfaceNumber); - USB_EPsetMaxPacketSize(dev, pid, ep, iface->eps[e].wMaxPacketSize); - } - } -} - -int USBPCIDevice::USBDesc_HandleControl(XboxDeviceState* dev, USBPacket *p, int request, int value, int index, int length, uint8_t* data) { - const USBDesc* desc = USBDesc_GetUsbDeviceDesc(dev); - int ret = -1; - - assert(desc != nullptr); - switch (request) { - case DeviceOutRequest | USB_REQ_SET_ADDRESS: - { - // From the standard: "This request sets the device address for all future device accesses. - // The wValue field specifies the device address to use for all subsequent accesses" - dev->Addr = value; - log_debug("USB: Address 0x%X set for device %s", dev->Addr, dev->ProductDesc.c_str()); - ret = 0; - break; - } - - case DeviceRequest | USB_REQ_GET_DESCRIPTOR: - { - // From the standard: "This request returns the specified descriptor if the descriptor exists. - // The wValue field specifies the descriptor type in the high byte and the descriptor index in the low byte. - // The wIndex field specifies the Language ID for string descriptors or is reset to zero for other descriptors" - ret = USBDesc_HandleStandardGetDescriptor(dev, p, value, data, length); - break; - } - - case DeviceRequest | USB_REQ_GET_CONFIGURATION: - { - // From the standard: "This request returns the current device configuration value. - // If the returned value is zero, the device is not configured" - data[0] = dev->Config ? dev->Config->bConfigurationValue : 0; - p->ActualLength = 1; - ret = 0; - break; - } - - case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: - { - // From the standard: "This request sets the device configuration. The lower byte of the wValue field specifies the desired configuration. - // This configuration value must be zero or match a configuration value from a configuration descriptor" - ret = USBDesc_SetConfig(dev, value); - log_debug("USB: Received standard SetConfiguration() request for device at address 0x%X. Configuration selected is %d and returned %d", - dev->Addr, value, ret); - break; - } - - case DeviceRequest | USB_REQ_GET_STATUS: - { - // From the standard: "This request returns the status for the specified recipient. The Recipient bits of the bmRequestType field - // specify the desired recipient. The data returned is the current status of the specified recipient." - // From XQEMU: - /* Default state: Device behavior when this request is received while - * the device is in the Default state is not specified. - * We return the same value that a configured device would return if - * it used the first configuration. */ - const USBDescConfig* config = dev->Config ? dev->Config : &dev->Device->confs[0]; - data[0] = 0; - if (config->bmAttributes & 0x40) { - data[0] |= 1 << USB_DEVICE_SELF_POWERED; - } - if (dev->RemoteWakeup) { - data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP; - } - data[1] = 0x00; - p->ActualLength = 2; - ret = 0; - break; - } - - case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: - { - // From the standard: "This request is used to clear or disable a specific feature. - // Feature selector values in wValue must be appropriate to the recipient" - if (value == USB_DEVICE_REMOTE_WAKEUP) { - dev->RemoteWakeup = 0; - ret = 0; - } - log_debug("USB: Received standard ClearFeature() request for device at address 0x%X. Feature selected is %d and returned %d", - dev->Addr, value, ret); - break; - } - - case DeviceOutRequest | USB_REQ_SET_FEATURE: - { - // From the standard: "This request is used to set or enable a specific feature. - // Feature selector values in wValue must be appropriate to the recipient" - if (value == USB_DEVICE_REMOTE_WAKEUP) { - dev->RemoteWakeup = 1; - ret = 0; - } - log_debug("USB: Received standard SetFeature() request for device at address 0x%X. Feature selected is %d and returned %d", - dev->Addr, value, ret); - break; - } - - case InterfaceRequest | USB_REQ_GET_INTERFACE: - { - // From the standard: "This request returns the selected alternate setting for the specified interface. - // wValue = Zero; wIndex = Interface" - if (index < 0 || index >= dev->NumInterfaces) { - break; - } - data[0] = dev->AltSetting[index]; - p->ActualLength = 1; - ret = 0; - break; - } - - case InterfaceOutRequest | USB_REQ_SET_INTERFACE: - { - // From the standard: "This request allows the host to select an alternate setting for the specified interface" - // wValue = Alternative Setting; wIndex = Interface - ret = USBDesc_SetInterface(dev, index, value); - log_debug("USB: Received standard SetInterface() request for device at address 0x%X. Interface selected is %d, Alternative Setting is %d and returned %d", dev->Addr, index, value, ret); - break; - } - - default: - break; - } - return ret; -} - -int USBPCIDevice::USBDesc_HandleStandardGetDescriptor(XboxDeviceState* dev, USBPacket* p, - int value, uint8_t* dest, size_t len) { - const USBDesc* desc = USBDesc_GetUsbDeviceDesc(dev); - uint8_t buf[256]; - uint8_t type = value >> 8; // recover descriptor type from wValue - uint8_t index = value & 0xFF; // recover descriptor index from wValue - int ret = -1; - int flags = 0; - - // Dropped from XQEMU bcdUSB check for usb 3.0 devices - - // From the standard: "The standard request to a device supports three types of descriptors: DEVICE, CONFIGURATION, and STRING." - - switch (type) { - case USB_DT_DEVICE: - { - ret = USB_ReadDeviceDesc(&desc->id, dev->Device, buf, sizeof(buf)); - log_debug("USB: Read operation of device descriptor of device 0x%X returns %d", dev->Addr, ret); - break; - } - - case USB_DT_CONFIG: - { - if (index < dev->Device->bNumConfigurations) { - ret = USB_ReadConfigurationDesc(dev->Device->confs + index, flags, buf, sizeof(buf)); - } - log_debug("USB: Read operation of configuration descriptor %d of device 0x%X returns %d", index, dev->Addr, ret); - break; - } - - case USB_DT_STRING: - { - ret = USB_ReadStringDesc(dev, index, buf, sizeof(buf)); - log_debug("USB: Read operation of string descriptor %d of device 0x%X returns %d", index, dev->Addr, ret); - break; - } - - // Dropped from XQEMU descriptor types USB_DT_DEVICE_QUALIFIER (6), USB_DT_OTHER_SPEED_CONFIG (7) -> usb 2.0 only and reserved in usb 3.0, - // USB_DT_BOS (15) and USB_DT_DEBUG (10) -> usb 3.0 only - - default: - log_warning("USB: %s: device address %d unknown type %d (len %zd)", __func__, dev->Addr, type, len); - break; - } - - if (ret > 0) { - if ((unsigned int)ret > len) { - ret = len; - } - memcpy(dest, buf, ret); - p->ActualLength = ret; - ret = 0; - } - return ret; -} - -int USBPCIDevice::USB_ReadDeviceDesc(const USBDescID* id, const USBDescDevice* dev, uint8_t* dest, size_t len) { - uint8_t bLength = 0x12; // a device descriptor is 18 bytes large - USBDescriptor* d = reinterpret_cast(dest); - - if (len < bLength) { - return -1; - } - - d->bLength = bLength; - d->bDescriptorType = USB_DT_DEVICE; - - d->u.device.bcdUSB_lo = GET_WORD_LOW(dev->bcdUSB); - d->u.device.bcdUSB_hi = GET_WORD_HIGH(dev->bcdUSB); - d->u.device.bDeviceClass = dev->bDeviceClass; - d->u.device.bDeviceSubClass = dev->bDeviceSubClass; - d->u.device.bDeviceProtocol = dev->bDeviceProtocol; - d->u.device.bMaxPacketSize0 = dev->bMaxPacketSize0; - - d->u.device.idVendor_lo = GET_WORD_LOW(id->idVendor); - d->u.device.idVendor_hi = GET_WORD_HIGH(id->idVendor); - d->u.device.idProduct_lo = GET_WORD_LOW(id->idProduct); - d->u.device.idProduct_hi = GET_WORD_HIGH(id->idProduct); - d->u.device.bcdDevice_lo = GET_WORD_LOW(id->bcdDevice); - d->u.device.bcdDevice_hi = GET_WORD_HIGH(id->bcdDevice); - d->u.device.iManufacturer = id->iManufacturer; - d->u.device.iProduct = id->iProduct; - d->u.device.iSerialNumber = id->iSerialNumber; - - d->u.device.bNumConfigurations = dev->bNumConfigurations; - - return bLength; -} - -int USBPCIDevice::USB_ReadConfigurationDesc(const USBDescConfig* conf, int flags, uint8_t* dest, size_t len) { - uint8_t bLength = 0x09; // a configuration descriptor is 9 bytes large - uint16_t wTotalLength = 0; - USBDescriptor* d = reinterpret_cast(dest); - int i, rc; - - if (len < bLength) { - return -1; - } - - // From the standard: "A request for a configuration descriptor returns the configuration descriptor, all interface - // descriptors, and endpoint descriptors for all of the interfaces in a single request." - - d->bLength = bLength; - d->bDescriptorType = USB_DT_CONFIG; - - d->u.config.bNumInterfaces = conf->bNumInterfaces; - d->u.config.bConfigurationValue = conf->bConfigurationValue; - d->u.config.iConfiguration = conf->iConfiguration; - d->u.config.bmAttributes = conf->bmAttributes; - d->u.config.bMaxPower = conf->bMaxPower; - wTotalLength += bLength; - - for (i = 0; i < conf->nif; i++) { - rc = USB_ReadInterfaceDesc(conf->ifs + i, flags, dest + wTotalLength, len - wTotalLength); - if (rc < 0) { - return rc; - } - wTotalLength += rc; - } - - d->u.config.wTotalLength_lo = GET_WORD_LOW(wTotalLength); - d->u.config.wTotalLength_hi = GET_WORD_HIGH(wTotalLength); - return wTotalLength; -} - -int USBPCIDevice::USB_ReadInterfaceDesc(const USBDescIface* iface, int flags, uint8_t* dest, size_t len) { - uint8_t bLength = 0x09; // an interface descriptor is 9 bytes large - int i, rc, pos = 0; - USBDescriptor* d = reinterpret_cast(dest); - - if (len < bLength) { - return -1; - } - - // From the standard: "The first interface descriptor follows the configuration descriptor. - // The endpoint descriptors for the first interface follow the first interface descriptor. - // If there are additional interfaces, their interface descriptor and endpoint descriptors - // follow the first interface's endpoint descriptors. Class-specific and/or vendor-specific - // descriptors follow the standard descriptors they extend or modify." - - d->bLength = bLength; - d->bDescriptorType = USB_DT_INTERFACE; - - d->u.iface.bInterfaceNumber = iface->bInterfaceNumber; - d->u.iface.bAlternateSetting = iface->bAlternateSetting; - d->u.iface.bNumEndpoints = iface->bNumEndpoints; - d->u.iface.bInterfaceClass = iface->bInterfaceClass; - d->u.iface.bInterfaceSubClass = iface->bInterfaceSubClass; - d->u.iface.bInterfaceProtocol = iface->bInterfaceProtocol; - d->u.iface.iInterface = iface->iInterface; - pos += bLength; - - for (i = 0; i < iface->ndesc; i++) { - rc = USB_ReadOtherDesc(iface->descs + i, dest + pos, len - pos); - if (rc < 0) { - return rc; - } - pos += rc; - } - - for (i = 0; i < iface->bNumEndpoints; i++) { - rc = USB_ReadEndpointDesc(iface->eps + i, flags, dest + pos, len - pos); - if (rc < 0) { - return rc; - } - pos += rc; - } - - return pos; -} - -size_t USBPCIDevice::USB_ReadOtherDesc(const USBDescOther* desc, uint8_t* dest, size_t len) { - size_t bLength = desc->length ? desc->length : desc->data[0]; - - if (len < bLength) { - return -1; - } - - memcpy(dest, desc->data, bLength); - return bLength; -} - -int USBPCIDevice::USB_ReadEndpointDesc(const USBDescEndpoint* ep, int flags, uint8_t* dest, size_t len) { - size_t bLength = ep->is_audio ? 0x09 : 0x07; // an endpoint descriptor is 7 bytes large (or 9 if it is an audio device) - size_t extralen = ep->extra ? ep->extra[0] : 0; - USBDescriptor* d = reinterpret_cast(dest); - - if (len < bLength + extralen) { - return -1; - } - - d->bLength = static_cast(bLength); - d->bDescriptorType = USB_DT_ENDPOINT; - - d->u.endpoint.bEndpointAddress = ep->bEndpointAddress; - d->u.endpoint.bmAttributes = ep->bmAttributes; - d->u.endpoint.wMaxPacketSize_lo = GET_WORD_LOW(ep->wMaxPacketSize); - d->u.endpoint.wMaxPacketSize_hi = GET_WORD_HIGH(ep->wMaxPacketSize); - d->u.endpoint.bInterval = ep->bInterval; - if (ep->is_audio) { - d->u.endpoint.bRefresh = ep->bRefresh; - d->u.endpoint.bSynchAddress = ep->bSynchAddress; - } - - // Dropped from XQEMU the reading of SuperSpeed Endpoint Companion descriptors since those are usb 3.0 specific - - if (ep->extra) { - memcpy(dest + bLength, ep->extra, extralen); - } - - return bLength + extralen; -} - -int USBPCIDevice::USB_ReadStringDesc(XboxDeviceState* dev, int index, uint8_t* dest, size_t len) { - size_t bLength, i; - unsigned int pos; - const char* str; - - if (len < 4) { - return -1; - } - - // From the standard: "String index zero for all languages returns a string descriptor - // that contains an array of two-byte LANGID codes supported by the device" - - if (index == 0) { - /* language ids */ - dest[0] = 4; - dest[1] = USB_DT_STRING; - dest[2] = 0x09; - dest[3] = 0x04; // we only support English (United States) - return 4; - } - - str = USBDesc_GetString(dev, index); - if (str == nullptr) { - return 0; - } - - // From the standard: "The UNICODE string descriptor is not NULL-terminated. The string length is - // computed by subtracting two from the value of the first byte of the descriptor" - - bLength = strlen(str) * 2 + 2; - dest[0] = bLength; - dest[1] = USB_DT_STRING; - i = 0; pos = 2; - while (pos + 1 < bLength && pos + 1 < len) { - dest[pos++] = str[i++]; - dest[pos++] = 0; - } - return pos; -} - -void USBPCIDevice::USBDesc_SetString(XboxDeviceState* dev, int index, std::string&& str) { - USBDescString* s; - - QLIST_FOREACH(s, &dev->Strings, next) { - if (s->index == index) { - break; - } - } - - if (s == nullptr) { - s = new USBDescString(); - s->index = index; - QLIST_INSERT_HEAD(&dev->Strings, s, next); - } - - s->str = str; -} - -const char* USBPCIDevice::USBDesc_GetString(XboxDeviceState* dev, int index) { - USBDescString* s; - - QLIST_FOREACH(s, &dev->Strings, next) { - if (s->index == index) { - return s->str.c_str(); - } - } - - return nullptr; + log_spew("USBPCIDevice::PCIMMIOWrite: Unimplemented write! bar = %d, address = 0x%x, value = 0x%x, size = %u\n", barIndex, addr, value, size); } } diff --git a/modules/core/src/common/strikebox/hw/xid/xid_gamepad.cpp b/modules/core/src/common/strikebox/hw/xid/xid_gamepad.cpp deleted file mode 100644 index 869276c..0000000 --- a/modules/core/src/common/strikebox/hw/xid/xid_gamepad.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// This is an open source non-commercial project. Dear PVS-Studio, please check it. -// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->devices->usb->XidGamepad.cpp -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2018 ergo720 -// * -// * All rights reserved -// * -// ****************************************************************** - -#include "strikebox/hw/xid/xid_gamepad.h" - -#include "strikebox/hw/ohci/ohci.h" -#include "strikebox/hw/pci/usb_pci.h" - -#include - -namespace strikebox { - -XidGamepad* g_XidControllerObjArray[4]; - -#define USB_CLASS_XID 0x58 -#define USB_DT_XID 0x42 - -#define HID_GET_REPORT 0x01 -#define HID_SET_REPORT 0x09 -#define XID_GET_CAPABILITIES 0x01 - - -#pragma pack(1) - -/* Class-specific xid descriptor */ -struct XIDDesc { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdXid; - uint8_t bType; - uint8_t bSubType; - uint8_t bMaxInputReportSize; - uint8_t bMaxOutputReportSize; - uint16_t wAlternateProductIds[4]; -}; - -/* Struct used by the Get_Report request -> state of the buttons */ -struct XIDGamepadReport { - uint8_t bReportId; - uint8_t bLength; - uint16_t wButtons; // all non-analog buttons - uint8_t bAnalogButtons[8]; // X, Y, A, B, white, black, left/right trigger - int16_t sThumbLX; // analog stick, left X - int16_t sThumbLY; // analog stick, left Y - int16_t sThumbRX; // analog stick, right X - int16_t sThumbRY; // analog stick, right Y -}; - -/* Struct used by the Set_Report request -> vibration strenght */ -struct XIDGamepadOutputReport { - uint8_t report_id; // From XQEMU: FIXME: is this correct? - uint8_t length; - uint16_t left_actuator_strength; // strenght of left vibration motor - uint16_t right_actuator_strength; // strenght of right vibration motor -}; - -#pragma pack() - -struct USBXIDState { - XboxDeviceState dev; // gamepad device status - USBEndpoint* intr; // interrupt endpoint of the gamepad - - const XIDDesc* xid_desc; // xid-specific descriptor - - XIDGamepadReport in_state; // Get_Report struct - XIDGamepadReport in_state_capabilities; // Get_Capabilities struct (in) - XIDGamepadOutputReport out_state; // Set_Report struct - XIDGamepadOutputReport out_state_capabilities; // Get_Capabilities struct (out) -}; - -static const USBDescEndpoint desc_endp_xbox_gamepad[2] = { - { - USB_DIR_IN | 0x02, // bEndpointAddress; - USB_ENDPOINT_XFER_INT, // bmAttributes; - 0x20, // wMaxPacketSize; - 4, // bInterval; - 0, // bRefresh; - 0, // bSynchAddress - 0, // is_audio - nullptr // extra - }, - { - USB_DIR_OUT | 0x02, - USB_ENDPOINT_XFER_INT, - 0x20, - 4, - 0, - 0, - 0, - nullptr - } -}; - -static const USBDescIface desc_iface_xbox_gamepad = { - 0, // bInterfaceNumber; - 0, // bAlternateSetting; - 2, // bNumEndpoints; - USB_CLASS_XID, // bInterfaceClass; - 0x42, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0, // iInterface - 0, // ndesc - nullptr, // descs - desc_endp_xbox_gamepad -}; - -static const USBDescConfig desc_config_xbox_gamepad = { - 1, // bNumInterfaces - 1, // bConfigurationValue - 0, // iConfiguration - 0x80, // bmAttributes - 50, // bMaxPower - 1, // nif - &desc_iface_xbox_gamepad -}; - -static const USBDescDevice desc_device_xbox_gamepad = { - 0x0110, // bcdUSB - 0, // bDeviceClass - 0, // bDeviceSubClass - 0, // bDeviceProtocol - 0x40, // bMaxPacketSize0 - 1, // bNumConfigurations - &desc_config_xbox_gamepad -}; - -static const USBDesc desc_xbox_gamepad = { - { - 0x045E, // idVendor - 0x0202, // idProduct - 0x0100, // bcdDevice - STR_MANUFACTURER, // iManufacturer - STR_PRODUCT, // iProduct - STR_SERIALNUMBER // iSerialNumber - }, - &desc_device_xbox_gamepad -}; - -static const XIDDesc desc_xid_xbox_gamepad = { - 0x10, // bLength - USB_DT_XID, // bDescriptorType - 0x100, // bcdXid - 1, // bType - 1, // bSubType - 20, // bMaxInputReportSize - 6, // bMaxOutputReportSize - { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF } // wAlternateProductIds -}; - -int XidGamepad::Init(int port) { - if (port > 4 || port < 1) { return -1; } - - XboxDeviceState* dev = ClassInitFn(); - int rc = UsbXidClaimPort(dev, port); - if (rc != 0) { - m_UsbDev->m_HostController->m_bFrameTime = false; - return rc; - } - m_UsbDev->USB_EpInit(dev); - m_UsbDev->USB_DeviceInit(dev); - m_UsbDev->USB_DeviceAttach(dev); - m_UsbDev->m_HostController->m_bFrameTime = false; - - return 0; -} - -XboxDeviceState* XidGamepad::ClassInitFn() { - m_pPeripheralFuncStruct = new USBDeviceClass(); - m_XidState = new USBXIDState(); - XboxDeviceState* dev = &m_XidState->dev; - - dev->ProductDesc = "Microsoft Xbox Controller"; - QLIST_INIT(&dev->Strings); - dev->klass = m_pPeripheralFuncStruct; - - { - using namespace std::placeholders; - - m_pPeripheralFuncStruct->init = std::bind(&XidGamepad::UsbXid_Initfn, this, _1); - m_pPeripheralFuncStruct->handle_reset = std::bind(&XidGamepad::UsbXid_HandleReset, this); - m_pPeripheralFuncStruct->handle_control = std::bind(&XidGamepad::UsbXid_HandleControl, this, _1, _2, _3, _4, _5, _6, _7); - m_pPeripheralFuncStruct->handle_data = std::bind(&XidGamepad::UsbXid_HandleData, this, _1, _2); - m_pPeripheralFuncStruct->handle_destroy = std::bind(&XidGamepad::UsbXid_HandleDestroy, this); - m_pPeripheralFuncStruct->handle_attach = std::bind(&XidGamepad::UsbXid_Attach, this, _1); - m_pPeripheralFuncStruct->product_desc = dev->ProductDesc.c_str(); - m_pPeripheralFuncStruct->usb_desc = &desc_xbox_gamepad; - } - - return dev; -} - -int XidGamepad::UsbXidClaimPort(XboxDeviceState* dev, int port) { - int i; - std::vector::iterator it; - - assert(dev->Port == nullptr); - - for (int j = 0; j < 4; j++) { - if (g_HubObjArray[j]) { - i = 0; - for (auto usb_port : g_HubObjArray[j]->m_UsbDev->m_FreePorts) { - if (usb_port->Path == (std::to_string(port) + ".2")) { - m_UsbDev = g_HubObjArray[j]->m_UsbDev; - break; - } - i++; - } - } - } - if (m_UsbDev == nullptr) { - log_warning("XID: Port requested %d.2 not found (in use?)", port); - return -1; - } - - while (m_UsbDev->m_HostController->m_bFrameTime) {} - m_UsbDev->m_HostController->m_bFrameTime = true; - - m_Port = port; - it = m_UsbDev->m_FreePorts.begin() + i; - dev->Port = *it; - (*it)->Dev = dev; - m_UsbDev->m_FreePorts.erase(it); - - return 0; -} - -void XidGamepad::UsbXidReleasePort(XboxDeviceState* dev) { - USBPort* port = dev->Port; - - assert(port != nullptr); - - port->Dev = nullptr; - dev->Port = nullptr; -} - -int XidGamepad::UsbXid_Initfn(XboxDeviceState* dev) { - m_UsbDev->USB_CreateSerial(dev, std::string("1")); - m_UsbDev->USBDesc_SetString(dev, STR_MANUFACTURER, std::string("Cxbx-Reloaded")); - m_UsbDev->USBDesc_SetString(dev, STR_PRODUCT, std::string("Microsoft Gamepad")); - m_UsbDev->USBDesc_Init(dev); - m_XidState->intr = m_UsbDev->USB_GetEP(dev, USB_TOKEN_IN, 2); - - m_XidState->in_state.bLength = sizeof(m_XidState->in_state); - m_XidState->in_state.bReportId = 0; - m_XidState->out_state.length = sizeof(m_XidState->out_state); - m_XidState->out_state.report_id = 0; - - memset(&m_XidState->in_state_capabilities, 0xFF, sizeof(m_XidState->in_state_capabilities)); - m_XidState->in_state_capabilities.bLength = sizeof(m_XidState->in_state_capabilities); - m_XidState->in_state_capabilities.bReportId = 0; - memset(&m_XidState->out_state_capabilities, 0xFF, sizeof(m_XidState->out_state_capabilities)); - m_XidState->out_state_capabilities.length = sizeof(m_XidState->out_state_capabilities); - m_XidState->out_state_capabilities.report_id = 0; - - m_XidState->xid_desc = &desc_xid_xbox_gamepad; - - return 0; -} - -void XidGamepad::UsbXid_HandleDestroy() { - UsbXidReleasePort(&m_XidState->dev); - XidCleanUp(); -} - -void XidGamepad::UsbXid_Attach(XboxDeviceState* dev) { - if ((dev->Port->SpeedMask & USB_SPEED_MASK_FULL)) { - dev->Speed = USB_SPEED_FULL; - } - else { - return; - } - m_UsbDev->USBDesc_SetDefaults(dev); -} - -void XidGamepad::UsbXid_HandleReset() { - log_debug("XID: Gamepad reset event"); -} - -void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p, - int request, int value, int index, int length, uint8_t* data) { - int ret = m_UsbDev->USBDesc_HandleControl(dev, p, request, value, index, length, data); - if (ret >= 0) { - log_debug("XID: Gamepad handled by USBDesc_HandleControl, ret is %d", ret); - return; - } - - switch (request) { - // HID-specific requests - case ClassInterfaceRequest | HID_GET_REPORT: - { - // From the HID standard: "The Get_Report request allows the host to receive a report via the Control pipe. - // The wValue field specifies the Report Type in the high byte and the Report ID in the low byte. Set Report ID - // to 0 (zero) if Report IDs are not used. 01 = input, 02 = output, 03 = feature, 04-FF = reserved" - log_debug("XID: Gamepad GET_REPORT 0x%X", value); - // JayFoxRox's analysis: "This 0x0100 case is for input. - // This is the case where the Xbox wants to read input data from the controller. - // Confirmed with a real Duke controller : - // If the buffer provided by the Xbox is too small, the controller will cut the transfer when the buffer is full (actual_length is patched). - // If the buffer is too large the controller will STALL instead. - // If the buffer has the correct length the full input data is transferred." - if (value == 0x0100) { - if (length <= m_XidState->in_state.bLength) { - // TODO: implement input devices - //SDL2Devices* controller = g_InputDeviceManager->FindDeviceFromXboxPort(m_Port); - //if (controller != nullptr) { - // controller->ReadButtonState(&m_XidState->in_state.wButtons, m_XidState->in_state.bAnalogButtons, - // &m_XidState->in_state.sThumbLX, &m_XidState->in_state.sThumbLY, &m_XidState->in_state.sThumbRX, - // &m_XidState->in_state.sThumbRY); - //} - //else - //{ - // // ergo720: this shouldn't really happen. If it does, it either means that m_Port is wrong or there's a bug - // // in the InputDeviceManager - // p->Status = USB_RET_STALL; - // assert(0); - //} - memcpy(data, &m_XidState->in_state, m_XidState->in_state.bLength); - p->ActualLength = length; - } - else { - p->Status = USB_RET_STALL; - } - } - else { - p->Status = USB_RET_STALL; - } - break; - } - - case ClassInterfaceOutRequest | HID_SET_REPORT: - { - // From the HID standard: "The Set_Report request allows the host to send a report to the device, possibly - // setting the state of input, output, or feature controls. The meaning of the request fields for the Set_Report - // request is the same as for the Get_Report request, however the data direction is reversed and the Report - // Data is sent from host to device." - log_debug("XID: Gamepad SET_REPORT 0x%X", value); - // JayFoxRox's analysis: "The 0x0200 case below is for output. - // This is the case where the Xbox wants to write rumble data to the controller. - // To my knowledge : - // If the buffer provided by the Xbox is too small the transfer will STALL. - // If the buffer is too large the transfer will STALL. - // If the buffer has the correct length the full output data is transferred." - if (value == 0x0200) { - if (length == m_XidState->out_state.length) { - // Read length, then the entire packet - memcpy(&m_XidState->out_state, data, sizeof(m_XidState->out_state)); - /* FIXME: This should also be a STALL */ - assert(m_XidState->out_state.length == sizeof(m_XidState->out_state)); - p->ActualLength = length; - } - else { - p->Status = USB_RET_STALL; - } - UpdateForceFeedback(); - } - else { - p->Status = USB_RET_STALL; - assert(0); - } - break; - } - - // XID-specific requests - case VendorInterfaceRequest | USB_REQ_GET_DESCRIPTOR: - { - log_debug("XID: Gamepad GET_DESCRIPTOR 0x%x", value); - if (value == 0x4200) { - assert(m_XidState->xid_desc->bLength <= length); - memcpy(data, m_XidState->xid_desc, m_XidState->xid_desc->bLength); - p->ActualLength = m_XidState->xid_desc->bLength; - } - else { - p->Status = USB_RET_STALL; - assert(0); - } - break; - } - - case VendorInterfaceRequest | XID_GET_CAPABILITIES: - { - log_debug("XID: Gamepad XID_GET_CAPABILITIES 0x%x", value); - if (value == 0x0100) { - if (length > m_XidState->in_state_capabilities.bLength) { - length = m_XidState->in_state_capabilities.bLength; - } - memcpy(data, &m_XidState->in_state_capabilities, length); - p->ActualLength = length; - } - else if (value == 0x0200) { - if (length > m_XidState->out_state_capabilities.length) { - length = m_XidState->out_state_capabilities.length; - } - memcpy(data, &m_XidState->out_state_capabilities, length); - p->ActualLength = length; - } - else { - p->Status = USB_RET_STALL; - assert(0); - } - break; - } - - case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8) | USB_REQ_GET_DESCRIPTOR: - { - /* FIXME: ! */ - log_debug("XID: Gamepad unknown xpad request 0x%X: value = 0x%X", request, value); - memset(data, 0x00, length); - //FIXME: Intended for the hub: usbd_get_hub_descriptor, UT_READ_CLASS?! - p->Status = USB_RET_STALL; - //assert(false); - break; - } - - case ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_ENDPOINT) << 8) | USB_REQ_CLEAR_FEATURE: - { - /* FIXME: ! */ - log_debug("XID: Gamepad unknown xpad request 0x%X: value = 0x%X", request, value); - memset(data, 0x00, length); - p->Status = USB_RET_STALL; - break; - } - - default: - log_debug("XID: Gamepad USB stalled on request 0x%X value 0x%X", request, value); - p->Status = USB_RET_STALL; - assert(0); - break; - } -} - -void XidGamepad::UsbXid_HandleData(XboxDeviceState* dev, USBPacket* p) { - switch (p->Pid) { - case USB_TOKEN_IN: - { - if (p->Endpoint->Num == 2) { - //SDL2Devices* controller = g_InputDeviceManager->FindDeviceFromXboxPort(m_Port); - //if (controller != nullptr) { - // bool ret; - // ret = controller->ReadButtonState(&m_XidState->in_state.wButtons, m_XidState->in_state.bAnalogButtons, - // &m_XidState->in_state.sThumbLX, &m_XidState->in_state.sThumbLY, &m_XidState->in_state.sThumbRX, - // &m_XidState->in_state.sThumbRY); - // if (ret) { - // m_UsbDev->USB_PacketCopy(p, &m_XidState->in_state, m_XidState->in_state.bLength); - // } - // else { - p->Status = USB_RET_NAK; - // } - //} - //else - //{ - // p->Status = USB_RET_STALL; - // assert(0); - //} - } - else { - assert(0); - } - break; - } - - case USB_TOKEN_OUT: - { - if (p->Endpoint->Num == 2) { - m_UsbDev->USB_PacketCopy(p, &m_XidState->out_state, m_XidState->out_state.length); - UpdateForceFeedback(); - } - else { - assert(0); - } - break; - } - - default: - p->Status = USB_RET_STALL; - assert(0); - break; - } -} - -void XidGamepad::XidCleanUp() { - delete m_pPeripheralFuncStruct; - delete m_XidState; - m_pPeripheralFuncStruct = nullptr; - m_XidState = nullptr; -} - -void XidGamepad::UpdateForceFeedback() { - // JayFoxRox's remarks: "Xbox -> XID packets were not tested - // The handling of output packets / force feedback was not checked." - // For the above reason we don't implement vibration support for now since the current - // implementation is untested and could potentially contain errors - /* FIXME: Check actuator endianess */ - log_debug("XID: Set rumble power to left: 0x%X and right: 0x%X\n", - m_XidState->out_state.left_actuator_strength, - m_XidState->out_state.right_actuator_strength); -} - -} diff --git a/modules/core/src/common/strikebox/iovec.cpp b/modules/core/src/common/strikebox/iovec.cpp deleted file mode 100644 index 03eee85..0000000 --- a/modules/core/src/common/strikebox/iovec.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Portions of the code are based on Cxbx-Reloaded's OHCI LLE implementation. - * The original copyright header is included below. - */ -// ****************************************************************** -// * -// * .,-::::: .,:: .::::::::. .,:: .: -// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; -// * [[[ '[[,,[[' [[[__[[\. '[[,,[[' -// * $$$ Y$$$P $$""""Y$$ Y$$$P -// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, -// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, -// * -// * Cxbx->Cxbx.h -// * -// * This file is part of the Cxbx project. -// * -// * Cxbx and Cxbe are free software; you can redistribute them -// * and/or modify them under the terms of the GNU General Public -// * License as published by the Free Software Foundation; either -// * version 2 of the license, or (at your option) any later version. -// * -// * This program is distributed in the hope that it will be useful, -// * but WITHOUT ANY WARRANTY; without even the implied warranty of -// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// * GNU General Public License for more details. -// * -// * You should have recieved a copy of the GNU General Public License -// * along with this program; see the file COPYING. -// * If not, write to the Free Software Foundation, Inc., -// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. -// * -// * (c) 2002-2003 Aaron Robinson -// * -// * All rights reserved -// * -// ****************************************************************** -#include "strikebox/iovec.h" - -#include -#include -#include - -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -namespace strikebox { - -void IoVecReset(IOVector* qiov) { - assert(qiov->AllocNumber != -1); - - qiov->IoVecNumber = 0; - qiov->Size = 0; -} - -void IoVecAdd(IOVector* qiov, void* base, size_t len) { - assert(qiov->AllocNumber != -1); - - if (qiov->IoVecNumber == qiov->AllocNumber) { - qiov->AllocNumber = 2 * qiov->AllocNumber + 1; - qiov->IoVecStruct = static_cast(std::realloc(qiov->IoVecStruct, qiov->AllocNumber * sizeof(IOVector))); - } - qiov->IoVecStruct[qiov->IoVecNumber].Iov_Base = base; - qiov->IoVecStruct[qiov->IoVecNumber].Iov_Len = len; - qiov->Size += len; - ++qiov->IoVecNumber; -} - -// This takes "iov_cnt" of "iov" buffers as input and copies sequentially their contents to the "buf" output buffer. -// "offset" indicates the offset inside "bytes" (total lenght of "iov" buffers) where the copy is going to start. -// "offset" must be less than "bytes" or else the assertion will fail. "done" is the number of bytes actually copied -size_t IoVecTobuffer(const IoVec* iov, const unsigned int iov_cnt, size_t offset, void* buf, size_t bytes) { - size_t done; - unsigned int i; - for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { - if (offset < iov[i].Iov_Len) { - size_t len = MIN(iov[i].Iov_Len - offset, bytes - done); - std::memcpy(static_cast(buf) + done, static_cast(iov[i].Iov_Base) + offset, len); - done += len; - offset = 0; - } - else { - offset -= iov[i].Iov_Len; - } - } - assert(offset == 0); - return done; -} - -// This does the opposite of IoVecTobuffer: it takes "buf" as input and copies sequentially its contents to the -// "iov" output buffers. -size_t IoVecFromBuffer(const IoVec* iov, unsigned int iov_cnt, size_t offset, void* buf, size_t bytes) { - size_t done; - unsigned int i; - for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) { - if (offset < iov[i].Iov_Len) { - size_t len = MIN(iov[i].Iov_Len - offset, bytes - done); - memcpy(static_cast(iov[i].Iov_Base) + offset, static_cast(buf) + done, len); - done += len; - offset = 0; - } - else { - offset -= iov[i].Iov_Len; - } - } - assert(offset == 0); - return done; -} - -} diff --git a/modules/core/src/common/strikebox/xbox.cpp b/modules/core/src/common/strikebox/xbox.cpp index 7c32a45..065cb30 100644 --- a/modules/core/src/common/strikebox/xbox.cpp +++ b/modules/core/src/common/strikebox/xbox.cpp @@ -570,28 +570,7 @@ EmulatorStatus Xbox::InitHardware() { } EmulatorStatus Xbox::InitDebugger() { - // GDB Server - if (m_settings.gdb_enable) { - m_gdb = new GdbServer(m_vm->get().GetVirtualProcessor(0)->get(), "127.0.0.1", 9269); - // TODO: handle result properly - int result = m_gdb->Initialize(); - if (result) { - return EMUS_INIT_DEBUGGER_FAILED; - } - - // Allow debugging before running so client can setup breakpoints, etc - log_debug("Starting GDB Server\n"); - m_gdb->WaitForConnection(); - m_gdb->Debug(1); - } - - /*HardwareBreakpoints bps = { 0 }; - bps.bp[0].globalEnable = true; - bps.bp[0].address = 0x80016756; - bps.bp[0].length = HWBP_LENGTH_1_BYTE; - bps.bp[0].trigger = HWBP_TRIGGER_EXECUTION; - vp.SetHardwareBreakpoints(bps);*/ - + // TODO: Start GDB server return EMUS_OK; } @@ -925,7 +904,7 @@ void Xbox::Cleanup() { } if (m_settings.gdb_enable) { - m_gdb->Shutdown(); + // TODO: Stop GDB server } }