video/atirage.cpp: Extremely preliminary emulation of PCI ATI 3D Rage family SVGA chips. [R. Belmont]

apple/powermacg3.cpp: Hooked up ATI Rage II video, you can now enter and interact with Open Firmware. [R. Belmont]
This commit is contained in:
arbee 2023-05-18 19:57:03 -04:00
parent 915cf99f06
commit 9de67ba595
6 changed files with 710 additions and 10 deletions

View File

@ -55,6 +55,18 @@ if (VIDEOS["AM8052"]~=null) then
}
end
--------------------------------------------------
--
--@src/devices/video/atirage.h,VIDEOS["ATIRAGE"] = true
--------------------------------------------------
if (VIDEOS["ATIRAGE"]~=null) then
files {
MAME_DIR .. "src/devices/video/atirage.cpp",
MAME_DIR .. "src/devices/video/atirage.h",
}
end
--------------------------------------------------
--
--@src/devices/video/bufsprite.h,VIDEOS["BUFSPRITE"] = true

View File

@ -169,7 +169,14 @@ uint16_t mach32_device::offset()
uint32_t mach32_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
ati_vga_device::screen_update(screen,bitmap,cliprect);
ati_vga_device::screen_update(screen, bitmap, cliprect);
draw_hw_cursor(screen, bitmap, cliprect);
return 0;
}
uint32_t mach32_device::draw_hw_cursor(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint8_t depth = get_video_depth();
if(!m_cursor_enable)
@ -356,3 +363,33 @@ void mach64_device::device_reset()
{
mach32_device::device_reset();
}
void mach64_device::set_color(u8 index, u32 color)
{
// update the palette device so we can see in the F4 viewer what the Rage is doing
set_pen_color(index, (color>>16) & 0xff, (color>>8) & 0xff, color & 0xff);
}
u32 mach64_device::framebuffer_r(offs_t offset, u32 mem_mask)
{
const u32 *target = (u32 *)&vga.memory[offset<<2];
return *target;
}
void mach64_device::framebuffer_w(offs_t offset, u32 data, u32 mem_mask)
{
COMBINE_DATA((u32*)&vga.memory[offset<<2]);
}
u32 mach64_device::framebuffer_be_r(offs_t offset, u32 mem_mask)
{
const u32 *target = (u32 *)&vga.memory[offset<<2];
return swapendian_int32(*target);
}
void mach64_device::framebuffer_be_w(offs_t offset, u32 data, u32 mem_mask)
{
data = swapendian_int32(data);
mem_mask = swapendian_int32(mem_mask);
COMBINE_DATA((u32*)&vga.memory[offset<<2]);
}

View File

@ -53,6 +53,7 @@ public:
// construction/destruction
mach32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
uint32_t draw_hw_cursor(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
required_device<mach32_8514a_device> m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device
@ -213,6 +214,13 @@ public:
void mach64_config1_w(uint16_t data) { } // why does the mach64 BIOS write to these, they are read only on the mach32 and earlier
void mach64_config2_w(uint16_t data) { }
void set_color(u8 index, u32 color);
u32 framebuffer_r(offs_t offset, u32 mem_mask);
void framebuffer_w(offs_t offset, u32 data, u32 mem_mask);
u32 framebuffer_be_r(offs_t offset, u32 mem_mask);
void framebuffer_be_w(offs_t offset, u32 data, u32 mem_mask);
u8 *get_framebuffer_addr() { return &vga.memory[0]; }
protected:
mach64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@ -222,6 +230,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
required_device<mach64_8514a_device> m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device
private:
};
// device type definition

View File

@ -0,0 +1,524 @@
// license:BSD-3-Clause
// copyright-holders: R. Belmont
/*
ATI Rage PCI/AGP SVGA
This implementation targets the mach64 VT and 3D Rage chips. Rage 128 has similar registers
but they're mapped differently.
mach64 VT = mach64 with video decoding. Uses a Rage-compatible register layout, as opposed to earlier mach64.
mach64 GT = Rage I (mach64 acceleration and VGA with 3D polygons and MPEG-1 decode)
mach64 GT-B = Rage II (Rage I with faster 2D & 3D and MPEG-2 decode)
Rage II+ = Rage II with full DVD acceleration
Rage IIc = Rage II+ with optional AGP support
Rage Pro = new triangle setup engine, improved perspective correction, fog + specular lighting,
and improved video decode
Rage Pro Turbo = Rage Pro with AGP 2X support and improved performance drivers for Win9X
Rage LT = lower-power Rage II with DVD support
Rage Mobility C, EC, L, and M2 = lower-power Rage Pro with DVD motion compensation
Rage Mobility P, M, and M1 = lower-power Rage Pro with DVD motion compensation and IDCT accleration
Rage XL = cost-reduced Rage Pro with improved 3D image quality, used in many servers until 2006
Most PCI IDs are a 2-letter ATI product code in ASCII. For instance, Rage I & II aka mach64 GT are 0x4754 'GT'.
Reference: rrg-g02700_mach64_register_reference_guide_jul96.pdf, aka "mach64 Register Reference Guide: ATI VT-264 and 3D RAGE"
http://hackipedia.org/browse.cgi/Computer/Platform/PC%2C%20IBM%20compatible/Video/VGA/SVGA/ATI%2C%20Array%20Technology%20Inc
*/
#include "emu.h"
#include "screen.h"
#include "atirage.h"
#define LOG_GENERAL (1U << 0)
#define LOG_REGISTERS (1U << 1)
#define LOG_CRTC (1U << 2)
#define LOG_DAC (1U << 3)
#define VERBOSE (0)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(ATI_RAGEII, atirageii_device, "rageii", "ATI Rage II PCI")
DEFINE_DEVICE_TYPE(ATI_RAGEIIC, atirageiic_device, "rageiic", "ATI Rage IIC PCI")
DEFINE_DEVICE_TYPE(ATI_RAGEPRO, atiragepro_device, "ragepro", "ATI Rage Pro PCI")
// register offsets
static constexpr u32 CRTC_H_TOTAL_DISP = 0x00;
static constexpr u32 CRTC_V_TOTAL_DISP = 0x08;
static constexpr u32 CRTC_OFF_PITCH = 0x14;
static constexpr u32 CRTC_GEN_CNTL = 0x1c;
static constexpr u32 GP_IO = 0x78;
static constexpr u32 CLOCK_CNTL = 0x90;
static constexpr u32 CRTC_DAC_BASE = 0xc0;
static constexpr u32 CONFIG_CHIP_ID = 0xe0;
// PLL register offsets
static constexpr u32 PLL_MACRO_CNTL = 1;
static constexpr u32 PLL_REF_DIV = 2;
static constexpr u32 PLL_GEN_CNTL = 3;
static constexpr u32 MCLK_FB_DIV = 4;
static constexpr u32 PLL_VCLK_CNTL = 5;
static constexpr u32 VCLK_POST_DIV = 6;
static constexpr u32 VCLK0_FB_DIV = 7;
static constexpr u32 VCLK1_FB_DIV = 8;
static constexpr u32 VCLK2_FB_DIV = 9;
static constexpr u32 VCLK3_FB_DIV = 10;
static constexpr u32 PLL_XCLK_CNTL = 11;
static constexpr u32 PLL_FCP_CNTL = 12;
// mach64 & 3D Rage post-dividers for PLL
static const int pll_post_dividers[8] =
{
1, 2, 4, 8, 3, 5, 6, 12
};
void atirage_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
screen.set_screen_update(FUNC(atirage_device::screen_update));
ATIMACH64(config, m_mach64, 0);
m_mach64->set_screen("screen");
m_mach64->set_vram_size(0x600000);
}
atirage_device::atirage_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: pci_device(mconfig, type, tag, owner, clock),
m_mach64(*this, "vga"),
m_screen(*this, "screen"),
read_gpio(*this),
write_gpio(*this)
{
m_hres = m_vres = m_htotal = m_vtotal = m_format = 0;
m_dac_windex = m_dac_rindex = m_dac_state = 0;
m_dac_mask = 0xff;
}
atirageii_device::atirageii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: atirage_device(mconfig, ATI_RAGEII, tag, owner, clock)
{
}
atirageiic_device::atirageiic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: atirage_device(mconfig, ATI_RAGEIIC, tag, owner, clock)
{
}
atiragepro_device::atiragepro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: atirage_device(mconfig, ATI_RAGEPRO, tag, owner, clock)
{
}
void atirage_device::io_map(address_map& map)
{
map(0x00000000, 0x000003ff).rw(FUNC(atirage_device::regs_0_read), FUNC(atirage_device::regs_0_write));
}
void atirage_device::mem_map(address_map& map)
{
map(0x00000000, 0x005fffff).rw(m_mach64, FUNC(mach64_device::framebuffer_r), FUNC(mach64_device::framebuffer_w));
map(0x007ff800, 0x007ffbff).rw(FUNC(atirage_device::regs_1_read), FUNC(atirage_device::regs_1_write));
map(0x007ffc00, 0x007fffff).rw(FUNC(atirage_device::regs_0_read), FUNC(atirage_device::regs_0_write));
map(0x00800000, 0x00dfffff).rw(m_mach64, FUNC(mach64_device::framebuffer_be_r), FUNC(mach64_device::framebuffer_be_w));
}
void atirage_device::reg_map(address_map& map)
{
}
void atirage_device::config_map(address_map &map)
{
pci_device::config_map(map);
map(0x0040, 0x0043).rw(FUNC(atirage_device::user_cfg_r), FUNC(atirage_device::user_cfg_w));
}
void atirage_device::device_start()
{
read_gpio.resolve_safe(0);
write_gpio.resolve_safe();
pci_device::device_start();
add_map(0x1000000, M_MEM, FUNC(atirage_device::mem_map)); // 16 MB memory map
add_map(0x100, M_IO, FUNC(atirage_device::io_map)); // 256 byte I/O map
add_map(0x01000, M_MEM, FUNC(atirage_device::reg_map)); // 4K register map
command = 3;
intr_pin = 1;
intr_line = 0;
// clear the registers
std::fill(std::begin(m_regs0), std::end(m_regs0), 0);
std::fill(std::begin(m_regs1), std::end(m_regs1), 0);
std::fill(std::begin(m_pll_regs), std::end(m_pll_regs), 0);
std::fill(std::begin(m_dac_colors), std::end(m_dac_colors), 0);
// set PLL defaults from the manual
m_pll_regs[PLL_MACRO_CNTL] = 0xd4;
m_pll_regs[PLL_REF_DIV] = 0x36;
m_pll_regs[PLL_GEN_CNTL] = 0x4f;
m_pll_regs[MCLK_FB_DIV] = 0x97;
m_pll_regs[PLL_VCLK_CNTL] = 0x04;
m_pll_regs[VCLK_POST_DIV] = 0x6a;
m_pll_regs[VCLK0_FB_DIV] = 0xbe;
m_pll_regs[VCLK1_FB_DIV] = 0xd6;
m_pll_regs[VCLK2_FB_DIV] = 0xee;
m_pll_regs[VCLK3_FB_DIV] = 0x88;
m_pll_regs[PLL_XCLK_CNTL] = 0x00;
m_pll_regs[PLL_FCP_CNTL] = 0x41;
m_user_cfg = 8;
save_item(NAME(m_user_cfg));
save_item(NAME(m_regs0));
save_item(NAME(m_regs1));
save_item(NAME(m_pll_regs));
save_item(NAME(m_hres));
save_item(NAME(m_vres));
save_item(NAME(m_htotal));
save_item(NAME(m_vtotal));
save_item(NAME(m_format));
save_item(NAME(m_pixel_clock));
save_item(NAME(m_dac_windex));
save_item(NAME(m_dac_rindex));
save_item(NAME(m_dac_state));
save_item(NAME(m_dac_mask));
save_item(NAME(m_dac_colors));
}
void atirageii_device::device_start()
{
// mach64 GT-B / 3D Rage II (ATI documentation uses both names)
set_ids(0x10024754, 0x00, 0x030000, 0x10026987);
atirage_device::device_start();
revision = 0x9a;
m_regs0[CONFIG_CHIP_ID] = 0x54;
m_regs0[CONFIG_CHIP_ID+1] = 0x47;
m_regs0[CONFIG_CHIP_ID+3] = 0x9a;
}
void atirageiic_device::device_start()
{
// Rage IIc PCI
set_ids(0x10024756, 0x00, 0x030000, 0x10026987);
atirage_device::device_start();
revision = 0x3a;
m_regs0[CONFIG_CHIP_ID] = 0x56;
m_regs0[CONFIG_CHIP_ID+1] = 0x47;
m_regs0[CONFIG_CHIP_ID+3] = 0x3a;
}
void atiragepro_device::device_start()
{
// Rage Pro PCI
set_ids(0x10024750, 0x00, 0x030000, 0x10026987);
atirage_device::device_start();
revision = 0x5c;
m_regs0[CONFIG_CHIP_ID] = 0x50;
m_regs0[CONFIG_CHIP_ID+1] = 0x47;
m_regs0[CONFIG_CHIP_ID+3] = 0x5c;
}
void atirage_device::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)
{
}
u8 atirage_device::regs_0_read(offs_t offset)
{
switch (offset)
{
case CRTC_DAC_BASE: // DAC write index
return m_dac_windex;
case CRTC_DAC_BASE + 1:
{
u8 result;
switch (m_dac_state)
{
case 0: // red
result = ((m_dac_colors[m_dac_rindex] >> 16) & 0xff);
break;
case 1: // blue
result = ((m_dac_colors[m_dac_rindex] >> 8) & 0xff);
break;
case 2: // green
result = (m_dac_colors[m_dac_rindex] & 0xff);
break;
}
m_dac_state++;
if (m_dac_state >= 3)
{
m_dac_state = 0;
m_dac_rindex++;
}
return result;
}
break;
case CRTC_DAC_BASE + 2:
return m_dac_mask;
case CRTC_DAC_BASE + 3:
return m_dac_rindex;
case CLOCK_CNTL + 2:
return m_pll_regs[(m_regs0[CLOCK_CNTL+1] >> 2) & 0xf] << 16;
case GP_IO: // monitor sense - either 3-line Apple or EDID
return read_gpio() & 0xff;
case GP_IO + 1:
return (read_gpio() & 0xff00) >> 8;
case GP_IO + 2:
return (read_gpio() & 0xff0000) >> 16;
case GP_IO + 3:
return read_gpio() >> 24;
}
return m_regs0[offset];
}
void atirage_device::regs_0_write(offs_t offset, u8 data)
{
// the FCode drivers try to write to the chip ID, no idea why
if ((offset >= CONFIG_CHIP_ID) && (offset <= (CONFIG_CHIP_ID + 3)))
{
return;
}
LOGMASKED(LOG_REGISTERS, "regs_0_write: %02x to %x\n", data, offset);
m_regs0[offset] = data;
switch (offset)
{
case CRTC_DAC_BASE: // DAC write index
m_dac_state = 0;
m_dac_windex = data;
break;
case CRTC_DAC_BASE + 1:
switch (m_dac_state)
{
case 0: // red
m_dac_colors[m_dac_windex] &= 0x00ffff;
m_dac_colors[m_dac_windex] |= ((data & 0xff) << 16);
break;
case 1: // green
m_dac_colors[m_dac_windex] &= 0xff00ff;
m_dac_colors[m_dac_windex] |= ((data & 0xff) << 8);
break;
case 2: // blue
m_dac_colors[m_dac_windex] &= 0xffff00;
m_dac_colors[m_dac_windex] |= (data & 0xff);
break;
}
m_dac_state++;
if (m_dac_state == 3)
{
m_dac_state = 0;
m_mach64->set_color(m_dac_windex, m_dac_colors[m_dac_windex]);
m_dac_windex++;
}
break;
case CRTC_DAC_BASE + 2:
m_dac_mask = data;
break;
case CRTC_DAC_BASE + 3:
m_dac_state = 0;
m_dac_rindex = data >> 24;
break;
case CRTC_OFF_PITCH:
case CRTC_GEN_CNTL:
update_mode();
break;
case CLOCK_CNTL + 2:
if (BIT(m_regs0[CLOCK_CNTL+1], 1))
{
u8 regnum = (m_regs0[CLOCK_CNTL+1] >> 2) & 0xf;
m_pll_regs[regnum] = data & 0xff;
}
break;
case GP_IO:
case GP_IO + 1:
case GP_IO + 2:
case GP_IO + 3:
write_gpio(*(u32 *)&m_regs0[GP_IO]);
break;
}
}
u8 atirage_device::regs_1_read(offs_t offset)
{
LOGMASKED(LOG_REGISTERS, "regs 1 read @ %x\n", offset);
return m_regs1[offset];
}
void atirage_device::regs_1_write(offs_t offset, u8 data)
{
m_regs1[offset] = data;
}
u32 atirage_device::user_cfg_r()
{
return m_user_cfg;
}
void atirage_device::user_cfg_w(u32 data)
{
m_user_cfg = data;
}
void atirage_device::update_mode()
{
// first prereq: must be in native mode and the CRTC must be enabled
if (!(m_regs0[CRTC_GEN_CNTL+3] & 3))
{
LOGMASKED(LOG_CRTC, "VGA mode must be OFF and CRTC must be ON\n");
return;
}
m_htotal = (m_regs0[CRTC_H_TOTAL_DISP] | (m_regs0[CRTC_H_TOTAL_DISP+1] & 1) << 8) + 1;
m_htotal <<= 3; // in units of 8 pixels
m_hres = m_regs0[CRTC_H_TOTAL_DISP+2] + 1;
m_hres <<= 3;
m_vres = (m_regs0[CRTC_V_TOTAL_DISP+2] | (m_regs0[CRTC_V_TOTAL_DISP+3] & 7) << 8) + 1;
m_vtotal = (m_regs0[CRTC_V_TOTAL_DISP] | (m_regs0[CRTC_V_TOTAL_DISP+1] & 7) << 8) + 1;
m_format = m_regs0[CRTC_GEN_CNTL+1] & 7;
LOGMASKED(LOG_CRTC, "Setting mode (%d x %d), total (%d x %d) format %d\n", m_hres, m_vres, m_htotal, m_vtotal, m_format);
int vclk_source = (m_pll_regs[PLL_VCLK_CNTL] & 3);
if ((vclk_source != 0) && (vclk_source != 3))
{
LOGMASKED(LOG_CRTC, "VCLK source (%d) is not VPLL, can't calculate dot clock\n", m_pll_regs[PLL_VCLK_CNTL] & 3);
return;
}
double vpll_frequency;
int clk_source = m_regs0[CLOCK_CNTL] & 3;
switch (vclk_source)
{
case 0: // CPUCLK (the PCI bus clock, not to exceed 33 MHz)
vpll_frequency = (33000000.0 * m_pll_regs[VCLK0_FB_DIV + clk_source]) / m_pll_regs[PLL_REF_DIV];
break;
case 3: // PLLVCLK
vpll_frequency = ((clock() * 2.0) * m_pll_regs[VCLK0_FB_DIV + clk_source]) / m_pll_regs[PLL_REF_DIV];
break;
}
LOGMASKED(LOG_CRTC, "VPLL freq %f\n", vpll_frequency);
int vpll_post_divider = (m_pll_regs[VCLK_POST_DIV] >> (clk_source << 1)) & 3;
// Rage Pro adds one more bit to the divider from bits 4/5/6/7 of XCLK_CNTL depending on the clock source.
// This should always be zero on mach64/Rage/Rage II.
vpll_post_divider |= ((m_pll_regs[PLL_XCLK_CNTL] >> (clk_source + 2)) & 4);
m_pixel_clock = u32(vpll_frequency / pll_post_dividers[vpll_post_divider]);
LOGMASKED(LOG_CRTC, "Pixel clock = %d, refresh = %f\n", m_pixel_clock, (double)m_pixel_clock / (double)m_htotal / (double)m_vtotal);
rectangle visarea(0, m_hres - 1, 0, m_vres - 1);
m_screen->configure(m_htotal, m_vtotal, visarea, attotime::from_ticks(m_htotal * m_vtotal, m_pixel_clock).as_attoseconds());
}
u32 atirage_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
// are we in VGA mode rather than native? if so, let the legacy VGA stuff draw.
if (!(m_regs0[CRTC_GEN_CNTL+3] & 1))
{
return m_mach64->screen_update(screen, bitmap, cliprect);
}
// is the CRTC not enabled or the display disable bit set?
if ((!(m_regs0[CRTC_GEN_CNTL+3] & 2)) || (m_regs0[CRTC_GEN_CNTL] & 0x40))
{
bitmap.fill(0, cliprect);
return 0;
}
const int offset = ((m_regs0[CRTC_OFF_PITCH+2] & 0xf) << 16) | (m_regs0[CRTC_OFF_PITCH+1] << 8) | (m_regs0[CRTC_OFF_PITCH]);
u8 *vram = m_mach64->get_framebuffer_addr() + (offset * 8);
int stride = (m_regs0[CRTC_OFF_PITCH+2] >> 6) | (m_regs0[CRTC_OFF_PITCH+3] << 2);
stride *= 4;
switch (m_format)
{
case 2: // 8 bpp (also can be a weird 2/2/3 direct color mode)
for (u32 y = 0; y < m_vres; y++)
{
const u8 *src = &vram[stride*y];
u32 *dst = &bitmap.pix(y, 0);
for (u32 x = 0; x < m_hres; x++)
{
*dst++ = m_dac_colors[src[x]];
}
vram += stride;
}
break;
default:
LOGMASKED(LOG_GENERAL, "Unknown pixel format %d\n", m_format);
break;
}
return 0;
}
/*
02 to CLOCK_CTNL + 1
PLL: cd to 0
06 to CLOCK_CTNL + 1
PLL: d5 to 1
2a to CLOCK_CTNL + 1
PLL: 17 to 10
1a to CLOCK_CTNL + 1
PLL: c0 to 6
0a to CLOCK_CTNL + 1
PLL: 21 to 2
16 to CLOCK_CTNL + 1
PLL: 03 to 5
12 to CLOCK_CTNL + 1
PLL: 91 to 4
0e to CLOCK_CTNL + 1
PLL: 14 to 3
2e to CLOCK_CTNL + 1
PLL: 01 to 11
32 to CLOCK_CTNL + 1
PLL: a6 to 12
32 to CLOCK_CTNL + 1
PLL: e6 to 12
32 to CLOCK_CTNL + 1
PLL: a6 to 12
2a to CLOCK_CTNL + 1
PLL: 98 to 10
2e to CLOCK_CTNL + 1
PLL: 01 to 11
18 to CLOCK_CTNL + 1
Read PLL 6
1a to CLOCK_CTNL + 1
PLL: 80 to 6
0a to CLOCK_CTNL + 1
PLL: 24 to 2
12 to CLOCK_CTNL + 1
PLL: 9e to 4
32 to CLOCK_CTNL + 1
PLL: a6 to 12
32 to CLOCK_CTNL + 1
PLL: e6 to 12
32 to CLOCK_CTNL + 1
PLL: a6 to 12
*/

View File

@ -0,0 +1,92 @@
// license:BSD-3-Clause
// copyright-holders: R. Belmont
#ifndef MAME_VIDEO_ATIRAGE_H
#define MAME_VIDEO_ATIRAGE_H
#pragma once
#include "machine/pci.h"
#include "bus/isa/mach32.h"
class atirage_device : public pci_device
{
public:
atirage_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void mem_map(address_map &map);
void io_map(address_map &map);
void reg_map(address_map &map);
auto gpio_get_cb() { return read_gpio.bind(); }
auto gpio_set_cb() { return write_gpio.bind(); }
protected:
virtual void device_start() 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;
virtual void config_map(address_map &map) override;
required_device<mach64_device> m_mach64;
required_device<screen_device> m_screen;
u8 m_regs0[0x400];
u8 m_regs1[0x400];
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
private:
devcb_read32 read_gpio;
devcb_write32 write_gpio;
u32 m_user_cfg;
u32 m_hres, m_vres, m_htotal, m_vtotal, m_format, m_pixel_clock;
u8 m_dac_windex, m_dac_rindex, m_dac_state, m_dac_mask;
u32 m_dac_colors[256];
u8 m_pll_regs[16];
u8 regs_0_read(offs_t offset);
void regs_0_write(offs_t offset, u8 data);
u8 regs_1_read(offs_t offset);
void regs_1_write(offs_t offset, u8 data);
u32 user_cfg_r();
void user_cfg_w(u32 data);
void update_mode();
};
class atirageii_device : public atirage_device
{
public:
atirageii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual void device_start() override;
};
class atirageiic_device : public atirage_device
{
public:
atirageiic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual void device_start() override;
};
class atiragepro_device : public atirage_device
{
public:
atiragepro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
virtual void device_start() override;
};
DECLARE_DEVICE_TYPE(ATI_RAGEII, atirageii_device)
DECLARE_DEVICE_TYPE(ATI_RAGEIIC, atirageiic_device)
DECLARE_DEVICE_TYPE(ATI_RAGEPRO, atiragepro_device)
#endif

View File

@ -11,7 +11,7 @@
CPU: PowerPC 750 "G3" @ 233 MHz
Memory controller/PCI bridge: Motorola MPC106 "Grackle"
Video: ATI Rage II+, ATI Rage Pro on rev. B, ATI Rage Pro Turbo on rev. C
Video: ATI Rage II, ATI Rage Pro on rev. B, ATI Rage Pro Turbo on rev. C
I/O: Heathrow PCI I/O ASIC (see heathrow.cpp for details)
****************************************************************************/
@ -24,6 +24,7 @@
#include "machine/pci.h"
#include "machine/pci-ide.h"
#include "machine/ram.h"
#include "video/atirage.h"
#include "awacs_macrisc.h"
#include "cuda.h"
#include "heathrow.h"
@ -42,13 +43,19 @@ public:
required_device<macadb_device> m_macadb;
required_device<dimm_spd_device> m_dimm0, m_dimm1, m_dimm2;
required_device<ram_device> m_ram;
required_device<atirage_device> m_atirage;
private:
u32 m_sense;
void pwrmacg3_map(address_map &map);
virtual void machine_start() override;
virtual void machine_reset() override;
u32 read_sense();
void write_sense(u32 data);
WRITE_LINE_MEMBER(cuda_reset_w)
{
m_maincpu->set_input_line(INPUT_LINE_HALT, state);
@ -70,12 +77,15 @@ pwrmacg3_state::pwrmacg3_state(const machine_config &mconfig, device_type type,
m_dimm0(*this, "dimm0"),
m_dimm1(*this, "dimm1"),
m_dimm2(*this, "dimm2"),
m_ram(*this, RAM_TAG)
m_ram(*this, RAM_TAG),
m_atirage(*this, "pci:12.0")
{
}
void pwrmacg3_state::machine_start()
{
m_sense = 0;
m_mpc106->set_ram_info((u8 *)m_ram->pointer(), m_ram->size());
// start off disabling all of the DIMMs
@ -85,10 +95,6 @@ void pwrmacg3_state::machine_start()
switch (m_ram->size())
{
case 32*1024*1024:
m_dimm0->set_dimm_size(dimm_spd_device::SIZE_32_MIB);
break;
case 64*1024*1024:
m_dimm0->set_dimm_size(dimm_spd_device::SIZE_64_MIB);
break;
@ -106,6 +112,8 @@ void pwrmacg3_state::machine_start()
m_dimm0->set_dimm_size(dimm_spd_device::SIZE_256_MIB);
break;
}
save_item(NAME(m_sense));
}
void pwrmacg3_state::machine_reset()
@ -119,9 +127,20 @@ void pwrmacg3_state::pwrmacg3_map(address_map &map)
map.unmap_value_high();
}
u32 pwrmacg3_state::read_sense()
{
// ID as a 640x480 13" for now
return (m_sense & 0xffff00ff) | (6 << 8);
}
void pwrmacg3_state::write_sense(u32 data)
{
m_sense = data;
}
void pwrmacg3_state::pwrmacg3(machine_config &config)
{
PPC740(config, m_maincpu, 66000000); // actually 233 MHz
PPC750(config, m_maincpu, 66000000); // actually 233 MHz
m_maincpu->ppcdrc_set_options(PPCDRC_COMPATIBLE_OPTIONS);
m_maincpu->set_addrmap(AS_PROGRAM, &pwrmacg3_state::pwrmacg3_map);
@ -132,6 +151,12 @@ void pwrmacg3_state::pwrmacg3(machine_config &config)
heathrow.set_maincpu_tag("maincpu");
heathrow.set_pci_root_tag(":pci:00.0", AS_DATA);
// Apple's documentation says systems with the 4.0f2 ROM use a Rage II+, but
// the 4.0f2 ROM won't init the Rage if the PCI ID is 4755 (II+), only 4754 (Rage II).
atirage_device &ati(ATI_RAGEII(config, m_atirage, 14.318181_MHz_XTAL));
ati.gpio_get_cb().set(FUNC(pwrmacg3_state::read_sense));
ati.gpio_set_cb().set(FUNC(pwrmacg3_state::write_sense));
MACADB(config, m_macadb, 15.6672_MHz_XTAL);
CUDA(config, m_cuda, CUDA_341S0060);
@ -170,8 +195,8 @@ void pwrmacg3_state::pwrmacg3(machine_config &config)
m_dimm2->sda_callback().set(sda_merger, FUNC(input_merger_device::in_w<3>));
RAM(config, m_ram);
m_ram->set_default_size("32M");
m_ram->set_extra_options("32M,64M,96M,128M,256M");
m_ram->set_default_size("64M");
m_ram->set_extra_options("64M,96M,128M,256M");
screamer_device &screamer(SCREAMER(config, "codec", 45.1584_MHz_XTAL / 2));
screamer.dma_output().set(heathrow, FUNC(heathrow_device::codec_dma_read));