// license:BSD-3-Clause // copyright-holders:Samuele Zannoli #ifndef MAME_INCLUDES_XBOX_PCI_H #define MAME_INCLUDES_XBOX_PCI_H #pragma once #include "machine/pit8253.h" #include "xbox_nv2a.h" #include "xbox_usb.h" /* * Host */ class nv2a_host_device : public pci_host_device { public: template nv2a_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag) : nv2a_host_device(mconfig, tag, owner, clock) { set_ids_host(0x10de02a5, 0, 0); set_cpu_tag(std::forward(cpu_tag)); } nv2a_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override; template void set_cpu_tag(T &&cpu_tag) { cpu.set_tag(std::forward(cpu_tag)); } protected: virtual void device_start() override; virtual void device_reset() override; private: required_device cpu; }; DECLARE_DEVICE_TYPE(NV2A_HOST, nv2a_host_device) /* * Ram */ class nv2a_ram_device : public pci_device { public: nv2a_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, int memory_size) : nv2a_ram_device(mconfig, tag, owner, clock) { ram_size = memory_size; } nv2a_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual void config_map(address_map &map) override; virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override; protected: virtual void device_start() override; DECLARE_READ32_MEMBER(config_register_r); DECLARE_WRITE32_MEMBER(config_register_w); private: int ram_size; std::vector ram; }; DECLARE_DEVICE_TYPE(NV2A_RAM, nv2a_ram_device) /* * LPC Bus */ class lpcbus_host_interface { public: virtual void set_virtual_line(int line, int state) = 0; }; class lpcbus_device_interface { public: virtual void map_extra(address_space *memory_space, address_space *io_space) = 0; virtual void set_host(int index, lpcbus_host_interface *host) = 0; }; class mcpx_isalpc_device : public pci_device, public lpcbus_host_interface { public: mcpx_isalpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t subsystem_id); mcpx_isalpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto smi() { return m_smi_callback.bind(); } auto interrupt_output() { return m_interrupt_output.bind(); } auto boot_state_hook() { return m_boot_state_hook.bind(); } uint32_t acknowledge(); void debug_generate_irq(int irq, int state); virtual void set_virtual_line(int line, int state) override; DECLARE_READ32_MEMBER(acpi_r); DECLARE_WRITE32_MEMBER(acpi_w); DECLARE_WRITE8_MEMBER(boot_state_w); DECLARE_WRITE_LINE_MEMBER(irq1); DECLARE_WRITE_LINE_MEMBER(irq3); DECLARE_WRITE_LINE_MEMBER(irq11); DECLARE_WRITE_LINE_MEMBER(irq10); DECLARE_WRITE_LINE_MEMBER(irq14); DECLARE_WRITE_LINE_MEMBER(irq15); protected: virtual void device_start() override; virtual void device_reset() override; virtual void device_add_mconfig(machine_config &config) override; virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override; DECLARE_WRITE_LINE_MEMBER(interrupt_ouptut_changed); DECLARE_READ8_MEMBER(get_slave_ack); DECLARE_WRITE_LINE_MEMBER(pit8254_out0_changed); DECLARE_WRITE_LINE_MEMBER(pit8254_out2_changed); private: void internal_io_map(address_map &map); void lpc_io(address_map &map); void update_smi_line(); devcb_write_line m_smi_callback; devcb_write_line m_interrupt_output; devcb_write8 m_boot_state_hook; required_device pic8259_1; required_device pic8259_2; required_device pit8254; uint16_t m_pm1_status; uint16_t m_pm1_enable; uint16_t m_pm1_control; uint16_t m_pm1_timer; uint16_t m_gpe0_status; uint16_t m_gpe0_enable; uint16_t m_global_smi_control; uint8_t m_smi_command_port; lpcbus_device_interface *lpcdevices[16]; }; DECLARE_DEVICE_TYPE(MCPX_ISALPC, mcpx_isalpc_device) /* * SMBus */ class smbus_interface { public: virtual int execute_command(int command, int rw, int data) = 0; }; class mcpx_smbus_device : public pci_device { public: mcpx_smbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto interrupt_handler() { return m_interrupt_handler.bind(); } DECLARE_READ32_MEMBER(smbus0_r); DECLARE_WRITE32_MEMBER(smbus0_w); DECLARE_READ32_MEMBER(smbus1_r); DECLARE_WRITE32_MEMBER(smbus1_w); protected: virtual void device_start() override; virtual void device_reset() override; private: devcb_write_line m_interrupt_handler; struct smbus_state { int status; int control; int address; int data; int command; int rw; smbus_interface *devices[128]; uint32_t words[256 / 4]; } smbusst[2]; void smbus_io0(address_map &map); void smbus_io1(address_map &map); void smbus_io2(address_map &map); uint32_t smbus_read(int bus, offs_t offset, uint32_t mem_mask); void smbus_write(int bus, offs_t offset, uint32_t data, uint32_t mem_mask); }; DECLARE_DEVICE_TYPE(MCPX_SMBUS, mcpx_smbus_device) /* * OHCI USB Controller */ class usb_function_device; class mcpx_ohci_device : public pci_device { public: mcpx_ohci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); void set_hack_callback(std::function hack) { hack_callback = hack; } void plug_usb_device(int port, device_usb_ohci_function_interface *function); auto interrupt_handler() { return m_interrupt_handler.bind(); } DECLARE_READ32_MEMBER(ohci_r); DECLARE_WRITE32_MEMBER(ohci_w); protected: virtual void device_start() override; virtual void device_reset() override; virtual void device_config_complete() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; private: ohci_usb_controller *ohci_usb; devcb_write_line m_interrupt_handler; emu_timer *timer; required_device maincpu; std::function hack_callback; void ohci_mmio(address_map &map); struct dev_t { device_usb_ohci_function_interface *dev; int port; } connecteds[4]; int connecteds_count; }; DECLARE_DEVICE_TYPE(MCPX_OHCI, mcpx_ohci_device) /* * Ethernet */ class mcpx_eth_device : public pci_device { public: mcpx_eth_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); DECLARE_READ32_MEMBER(eth_r); DECLARE_WRITE32_MEMBER(eth_w); DECLARE_READ32_MEMBER(eth_io_r); DECLARE_WRITE32_MEMBER(eth_io_w); protected: virtual void device_start() override; virtual void device_reset() override; private: void eth_mmio(address_map &map); void eth_io(address_map &map); }; DECLARE_DEVICE_TYPE(MCPX_ETH, mcpx_eth_device) /* * Audio Processing Unit */ class mcpx_apu_device : public pci_device { public: template mcpx_apu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag) : mcpx_apu_device(mconfig, tag, owner, clock) { set_cpu_tag(std::forward(cpu_tag)); } mcpx_apu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); template void set_cpu_tag(T &&cpu_tag) { cpu.set_tag(std::forward(cpu_tag)); } DECLARE_READ32_MEMBER(apu_r); DECLARE_WRITE32_MEMBER(apu_w); protected: virtual void device_start() override; virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; private: required_device cpu; // APU contains 3 dsps: voice processor (VP) global processor (GP) encode processor (EP) struct apu_state { uint32_t memory[0x60000 / 4]; uint32_t gpdsp_sgaddress; // global processor scatter-gather uint32_t gpdsp_sgblocks; uint32_t gpdsp_address; uint32_t epdsp_sgaddress; // encoder processor scatter-gather uint32_t epdsp_sgblocks; uint32_t epdsp_sgaddress2; uint32_t epdsp_sgblocks2; int voice_number; uint32_t voices_heap_blockaddr[1024]; uint64_t voices_active[4]; //one bit for each voice: 1 playing 0 not uint32_t voicedata_address; int voices_frequency[256]; // sample rate int voices_position[256]; // position in samples * 1000 int voices_position_start[256]; // position in samples * 1000 int voices_position_end[256]; // position in samples * 1000 int voices_position_increment[256]; // position increment every 1ms * 1000 emu_timer *timer; address_space *space; } apust; void apu_mmio(address_map &map); }; DECLARE_DEVICE_TYPE(MCPX_APU, mcpx_apu_device) /* * AC97 Audio Controller */ class mcpx_ac97_audio_device : public pci_device { public: mcpx_ac97_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); DECLARE_READ32_MEMBER(ac97_audio_r); DECLARE_WRITE32_MEMBER(ac97_audio_w); DECLARE_READ32_MEMBER(ac97_audio_io0_r); DECLARE_WRITE32_MEMBER(ac97_audio_io0_w); DECLARE_READ32_MEMBER(ac97_audio_io1_r); DECLARE_WRITE32_MEMBER(ac97_audio_io1_w); protected: virtual void device_start() override; virtual void device_reset() override; private: struct ac97_state { uint32_t mixer_regs[0x84 / 4]; uint32_t controller_regs[0x40 / 4]; } ac97st; void ac97_mmio(address_map &map); void ac97_io0(address_map &map); void ac97_io1(address_map &map); }; DECLARE_DEVICE_TYPE(MCPX_AC97_AUDIO, mcpx_ac97_audio_device) /* * AC97 Modem Controller */ class mcpx_ac97_modem_device : public pci_device { public: mcpx_ac97_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; DECLARE_DEVICE_TYPE(MCPX_AC97_MODEM, mcpx_ac97_modem_device) /* * IDE Controller */ class mcpx_ide_device : public pci_device { public: mcpx_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto pri_interrupt_handler() { return m_pri_interrupt_handler.bind(); } auto sec_interrupt_handler() { return m_sec_interrupt_handler.bind(); } virtual void config_map(address_map &map) override; DECLARE_WRITE32_MEMBER(class_rev_w); DECLARE_READ8_MEMBER(pri_read_cs1_r); DECLARE_WRITE8_MEMBER(pri_write_cs1_w); DECLARE_READ8_MEMBER(sec_read_cs1_r); DECLARE_WRITE8_MEMBER(sec_write_cs1_w); protected: virtual void device_start() override; virtual void device_reset() override; virtual void device_add_mconfig(machine_config &config) override; virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override; private: required_device m_pri; required_device m_sec; devcb_write_line m_pri_interrupt_handler; devcb_write_line m_sec_interrupt_handler; void ide_pri_command(address_map &map); void ide_pri_control(address_map &map); void ide_sec_command(address_map &map); void ide_sec_control(address_map &map); void ide_io(address_map &map); DECLARE_WRITE_LINE_MEMBER(ide_pri_interrupt); DECLARE_WRITE_LINE_MEMBER(ide_sec_interrupt); }; DECLARE_DEVICE_TYPE(MCPX_IDE, mcpx_ide_device) /* * AGP Bridge */ class nv2a_agp_device : public agp_bridge_device { public: nv2a_agp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t main_id, uint32_t revision) : nv2a_agp_device(mconfig, tag, owner, clock) { set_ids_bridge(main_id, revision); } nv2a_agp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); void config_map(address_map& map) override; DECLARE_READ32_MEMBER(unknown_r); DECLARE_WRITE32_MEMBER(unknown_w); protected: virtual void device_start() override; virtual void device_reset() override; }; DECLARE_DEVICE_TYPE(NV2A_AGP, nv2a_agp_device) /* * NV2A 3D Accelerator */ class nv2a_gpu_device : public agp_device { public: template nv2a_gpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag) : nv2a_gpu_device(mconfig, tag, owner, clock) { set_cpu_tag(std::forward(cpu_tag)); } nv2a_gpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); template void set_cpu_tag(T &&cpu_tag) { cpu.set_tag(std::forward(cpu_tag)); } nv2a_renderer *debug_get_renderer() { return nvidia_nv2a; } auto interrupt_handler() { return m_interrupt_handler.bind(); } DECLARE_READ32_MEMBER(geforce_r); DECLARE_WRITE32_MEMBER(geforce_w); DECLARE_READ32_MEMBER(nv2a_mirror_r); DECLARE_WRITE32_MEMBER(nv2a_mirror_w); protected: virtual void device_start() override; virtual void device_reset() override; private: nv2a_renderer *nvidia_nv2a; required_device cpu; devcb_write_line m_interrupt_handler; address_space *m_program; void nv2a_mmio(address_map &map); void nv2a_mirror(address_map &map); }; DECLARE_DEVICE_TYPE(NV2A_GPU, nv2a_gpu_device) #endif // MAME_INCLUDES_XBOX_PCI_H