1 // license:BSD-3-Clause
2 // copyright-holders:Ted Green
3 #include "emu.h"
4 #include "voodoo_pci.h"
5
6 #include "screen.h"
7
8
device_add_mconfig(machine_config & config)9 void voodoo_1_pci_device::device_add_mconfig(machine_config &config)
10 {
11 VOODOO_1(config, m_voodoo, STD_VOODOO_1_CLOCK);
12 m_voodoo->set_fbmem(4);
13 m_voodoo->set_tmumem(1, 0);
14 }
15
device_add_mconfig(machine_config & config)16 void voodoo_2_pci_device::device_add_mconfig(machine_config &config)
17 {
18 VOODOO_2(config, m_voodoo, STD_VOODOO_2_CLOCK);
19 m_voodoo->set_fbmem(4);
20 m_voodoo->set_tmumem(1, 0);
21 }
22
device_add_mconfig(machine_config & config)23 void voodoo_banshee_pci_device::device_add_mconfig(machine_config &config)
24 {
25 VOODOO_BANSHEE(config, m_voodoo, STD_VOODOO_BANSHEE_CLOCK);
26 m_voodoo->set_fbmem(16);
27 }
28
device_add_mconfig(machine_config & config)29 void voodoo_3_pci_device::device_add_mconfig(machine_config &config)
30 {
31 VOODOO_3(config, m_voodoo, STD_VOODOO_3_CLOCK);
32 m_voodoo->set_fbmem(16);
33 }
34
35 DEFINE_DEVICE_TYPE(VOODOO_1_PCI, voodoo_1_pci_device, "voodoo_1_pci", "Voodoo 1 PCI")
36 DEFINE_DEVICE_TYPE(VOODOO_2_PCI, voodoo_2_pci_device, "voodoo_2_pci", "Voodoo 2 PCI")
37 DEFINE_DEVICE_TYPE(VOODOO_BANSHEE_PCI, voodoo_banshee_pci_device, "voodoo_banshee_pci", "Voodoo Banshee PCI")
38 DEFINE_DEVICE_TYPE(VOODOO_3_PCI, voodoo_3_pci_device, "voodoo_3_pci", "Voodoo 3 PCI")
39
config_map(address_map & map)40 void voodoo_pci_device::config_map(address_map &map)
41 {
42 pci_device::config_map(map);
43 map(0x40, 0x5f).rw(FUNC(voodoo_pci_device::pcictrl_r), FUNC(voodoo_pci_device::pcictrl_w));
44 }
45
46 // VOODOO_1 & VOODOO_2 map
voodoo_reg_map(address_map & map)47 void voodoo_pci_device::voodoo_reg_map(address_map &map)
48 {
49 map(0x0, 0x00ffffff).rw(m_voodoo, FUNC(voodoo_device::voodoo_r), FUNC(voodoo_device::voodoo_w));
50 }
51 // VOODOO_BANSHEE and VOODOO_3 maps
banshee_reg_map(address_map & map)52 void voodoo_pci_device::banshee_reg_map(address_map &map)
53 {
54 map(0x0, 0x01ffffff).rw(m_voodoo, FUNC(voodoo_banshee_device::banshee_r), FUNC(voodoo_banshee_device::banshee_w));
55 }
56
lfb_map(address_map & map)57 void voodoo_pci_device::lfb_map(address_map &map)
58 {
59 map(0x0, 0x01ffffff).rw(m_voodoo, FUNC(voodoo_banshee_device::banshee_fb_r), FUNC(voodoo_banshee_device::banshee_fb_w));
60 }
61
io_map(address_map & map)62 void voodoo_pci_device::io_map(address_map &map)
63 {
64 map(0x000, 0x0ff).rw(m_voodoo, FUNC(voodoo_banshee_device::banshee_io_r), FUNC(voodoo_banshee_device::banshee_io_w));
65 }
66
voodoo_pci_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)67 voodoo_pci_device::voodoo_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
68 : pci_device(mconfig, type, tag, owner, clock),
69 m_voodoo(*this, "voodoo"), m_cpu(*this, finder_base::DUMMY_TAG), m_screen(*this, finder_base::DUMMY_TAG), m_fbmem(2), m_tmumem0(0), m_tmumem1(0)
70 {
71 }
72
voodoo_1_pci_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)73 voodoo_1_pci_device::voodoo_1_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
74 : voodoo_pci_device(mconfig, VOODOO_1_PCI, tag, owner, clock)
75 {
76 }
77
voodoo_2_pci_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)78 voodoo_2_pci_device::voodoo_2_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
79 : voodoo_pci_device(mconfig, VOODOO_2_PCI, tag, owner, clock)
80 {
81 }
82
voodoo_banshee_pci_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)83 voodoo_banshee_pci_device::voodoo_banshee_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
84 : voodoo_pci_device(mconfig, VOODOO_BANSHEE_PCI, tag, owner, clock)
85 {
86 }
87
voodoo_3_pci_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)88 voodoo_3_pci_device::voodoo_3_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
89 : voodoo_pci_device(mconfig, VOODOO_3_PCI, tag, owner, clock)
90 {
91 }
92
device_start()93 void voodoo_pci_device::device_start()
94 {
95 if (m_cpu)
96 m_voodoo->set_cpu(*m_cpu);
97 if (m_screen)
98 m_voodoo->set_screen(*m_screen);
99 m_voodoo->set_fbmem(m_fbmem);
100 m_voodoo->set_tmumem(m_tmumem0, m_tmumem1);
101 pci_device::device_start();
102 save_item(NAME(m_pcictrl_reg));
103 machine().save().register_postload(save_prepost_delegate(FUNC(voodoo_pci_device::postload), this));
104 }
105
106 //void set_ids(uint32_t main_id, uint8_t revision, uint32_t pclass, uint32_t subsystem_id);
device_start()107 void voodoo_1_pci_device::device_start()
108 {
109 set_ids(0x121a0001, 0x02, 0x030000, 0x000000);
110
111 voodoo_pci_device::device_start();
112
113 add_map(16 * 1024 * 1024, M_MEM | M_PREF, FUNC(voodoo_pci_device::voodoo_reg_map));
114 bank_infos[0].adr = 0xff000000;
115 }
116
device_start()117 void voodoo_2_pci_device::device_start()
118 {
119 set_ids(0x121a0002, 0x02, 0x038000, 0x000000);
120
121 voodoo_pci_device::device_start();
122
123 add_map(16 * 1024 * 1024, M_MEM | M_PREF, FUNC(voodoo_pci_device::voodoo_reg_map));
124 bank_infos[0].adr = 0xff000000;
125 }
126
device_start()127 void voodoo_banshee_pci_device::device_start()
128 {
129 set_ids(0x121a0003, 0x02, 0x030000, 0x000000);
130
131 voodoo_pci_device::device_start();
132
133 add_map(32 * 1024 * 1024, M_MEM, FUNC(voodoo_pci_device::banshee_reg_map));
134 add_map(32 * 1024 * 1024, M_MEM, FUNC(voodoo_pci_device::lfb_map));
135 add_map(256, M_IO, FUNC(voodoo_pci_device::io_map));
136 bank_infos[0].adr = 0xf8000000;
137 bank_infos[1].adr = 0xf8000008;
138 bank_infos[2].adr = 0xfffffff0;
139 }
140
device_start()141 void voodoo_3_pci_device::device_start()
142 {
143 set_ids(0x121a0005, 0x02, 0x030000, 0x000000);
144
145 voodoo_pci_device::device_start();
146
147 add_map(32 * 1024 * 1024, M_MEM, FUNC(voodoo_pci_device::banshee_reg_map));
148 add_map(32 * 1024 * 1024, M_MEM, FUNC(voodoo_pci_device::lfb_map));
149 add_map(256, M_IO, FUNC(voodoo_pci_device::io_map));
150 bank_infos[0].adr = 0xf8000000;
151 bank_infos[1].adr = 0xf8000008;
152 bank_infos[2].adr = 0xfffffff0;
153 }
154
postload()155 void voodoo_pci_device::postload()
156 {
157 remap_cb();
158 }
159
device_reset()160 void voodoo_pci_device::device_reset()
161 {
162 memset(m_pcictrl_reg, 0, sizeof(m_pcictrl_reg));
163 pci_device::device_reset();
164 }
165
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)166 void voodoo_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
167 uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
168 {
169 logerror("%s: map_extra\n", this->tag());
170 }
171
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)172 void voodoo_banshee_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
173 uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
174 {
175 logerror("%s: map_extra\n", this->tag());
176
177 // Map VGA legacy access
178 // Should really be dependent on voodoo VGAINIT0 bit 8 and IO base + 0xc3 bit 0
179 uint64_t start = io_offset + 0x3b0;
180 uint64_t end = io_offset + 0x3df;
181 io_space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(voodoo_pci_device::vga_r)), write32s_delegate(*this, FUNC(voodoo_pci_device::vga_w)));
182 logerror("%s: map %s at %0*x-%0*x\n", this->tag(), "vga_r/w", 4, uint32_t(start), 4, uint32_t(end));
183 }
184
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)185 void voodoo_3_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
186 uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
187 {
188 logerror("%s: map_extra\n", this->tag());
189
190 // Map VGA legacy access
191 // Should really be dependent on voodoo VGAINIT0 bit 8 and IO base + 0xc3 bit 0
192 uint64_t start = io_offset + 0x3b0;
193 uint64_t end = io_offset + 0x3df;
194 io_space->install_readwrite_handler(start, end, read32s_delegate(*this, FUNC(voodoo_pci_device::vga_r)), write32s_delegate(*this, FUNC(voodoo_pci_device::vga_w)));
195 logerror("%s: map %s at %0*x-%0*x\n", this->tag(), "vga_r/w", 4, uint32_t(start), 4, uint32_t(end));
196 }
197
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)198 uint32_t voodoo_pci_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
199 {
200 return m_voodoo->voodoo_update(bitmap, cliprect) ? 0 : UPDATE_HAS_NOT_CHANGED;
201 }
202
203 // PCI bus control
pcictrl_r(offs_t offset,uint32_t mem_mask)204 uint32_t voodoo_pci_device::pcictrl_r(offs_t offset, uint32_t mem_mask)
205 {
206 uint32_t result = m_pcictrl_reg[offset];
207 // The address map starts at 0x40
208 switch (offset + 0x40 / 4) {
209 case 0x40/4:
210 // V1: initEnable: 11:0
211 // V2: initEnable: Fab ID=19:16, Graphics Rev=15:12
212 // Banshee/V3: fabID: ScratchPad=31:4 fabID=3:0
213 if (m_voodoo->vd_type== TYPE_VOODOO_2)
214 result = (result & ~0xff000) | 0x00044000; // Vegas driver needs this value
215 else if (m_voodoo->vd_type >= TYPE_VOODOO_BANSHEE)
216 result = (result & ~0xf) | 0x1;
217 break;
218 case 0x54/4:
219 // V2: SiProcess Register: Osc Force On, Osc Ring Sel, Osc Count Reset, 12 bit PCI Counter, 16 bit Oscillator Counter
220 // V3: AGP Capability Register: 8 bit 0, 4 bit AGP Major, 4 bit AGP Minor, 8 bit Next Ptr, 8 bit Capability ID
221 // Tenthdeg (vegas) checks this
222 result = 0x00006002;
223 break;
224 }
225
226 if (1)
227 logerror("%s:voodoo_pci_device pcictrl_r from offset %02X = %08X & %08X\n", machine().describe_context(), offset*4 + 0x40, result, mem_mask);
228 return result;
229 }
pcictrl_w(offs_t offset,uint32_t data,uint32_t mem_mask)230 void voodoo_pci_device::pcictrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
231 {
232 COMBINE_DATA(&m_pcictrl_reg[offset]);
233 // The address map starts at 0x40
234 switch (offset + 0x40 / 4) {
235 case 0x40/4:
236 // HW initEnable
237 m_voodoo->voodoo_set_init_enable(data);
238 logerror("%s:voodoo_pci_device pcictrl_w (initEnable) offset %02X = %08X & %08X\n", machine().describe_context(), offset * 4 + 0x40, data, mem_mask);
239 break;
240 default:
241 logerror("%s:voodoo_pci_device pcictrl_w to offset %02X = %08X & %08X\n", machine().describe_context(), offset*4 + 0x40, data, mem_mask);
242 break;
243 }
244 }
245
246 // VGA legacy accesses
vga_r(offs_t offset,uint32_t mem_mask)247 uint32_t voodoo_pci_device::vga_r(offs_t offset, uint32_t mem_mask)
248 {
249 uint32_t result = 0;
250 if (ACCESSING_BITS_0_7)
251 result |= downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_r(offset * 4 + 0 + 0xb0) << 0;
252 if (ACCESSING_BITS_8_15)
253 result |= downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_r(offset * 4 + 1 + 0xb0) << 8;
254 if (ACCESSING_BITS_16_23)
255 result |= downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_r(offset * 4 + 2 + 0xb0) << 16;
256 if (ACCESSING_BITS_24_31)
257 result |= downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_r(offset * 4 + 3 + 0xb0) << 24;
258 if (0)
259 logerror("%s voodoo_pci_device vga_r from offset %02X = %08X & %08X\n", machine().describe_context(), offset * 4, result, mem_mask);
260 return result;
261 }
vga_w(offs_t offset,uint32_t data,uint32_t mem_mask)262 void voodoo_pci_device::vga_w(offs_t offset, uint32_t data, uint32_t mem_mask)
263 {
264 if (ACCESSING_BITS_0_7)
265 downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_w(offset * 4 + 0 + 0xb0, data >> 0);
266 if (ACCESSING_BITS_8_15)
267 downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_w(offset * 4 + 1 + 0xb0, data >> 8);
268 if (ACCESSING_BITS_16_23)
269 downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_w(offset * 4 + 2 + 0xb0, data >> 16);
270 if (ACCESSING_BITS_24_31)
271 downcast<voodoo_banshee_device *>(m_voodoo.target())->banshee_vga_w(offset * 4 + 3 + 0xb0, data >> 24);
272
273 if (0)
274 logerror("%s voodoo_pci_device vga_w to offset %04X = %08X & %08X\n", machine().describe_context(), offset * 4, data, mem_mask);
275 }
276