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