1 // license:BSD-3-Clause
2 // copyright-holders:Samuele Zannoli
3 
4 #include "emu.h"
5 #include "machine/pci.h"
6 #include "machine/idectrl.h"
7 #include "includes/xbox_pci.h"
8 #include "includes/xbox.h"
9 #include "machine/ds128x.h"
10 
11 #include <functional>
12 
13 //#define LOG_AUDIO
14 
15 /*
16  * Host
17  */
18 
19 DEFINE_DEVICE_TYPE(NV2A_HOST, nv2a_host_device, "nv2a_host", "NV2A PCI Bridge Device - Host Bridge")
20 
nv2a_host_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)21 nv2a_host_device::nv2a_host_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
22 	pci_host_device(mconfig, NV2A_HOST, tag, owner, clock),
23 	cpu(*this, finder_base::DUMMY_TAG)
24 {
25 	set_ids_host(0x10de02a5, 0, 0);
26 }
27 
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)28 void nv2a_host_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
29 	uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
30 {
31 	io_space->install_device(0, 0xffff, *static_cast<pci_host_device *>(this), &pci_host_device::io_configuration_access_map);
32 }
33 
device_start()34 void nv2a_host_device::device_start()
35 {
36 	pci_host_device::device_start();
37 	memory_space = &cpu->space(AS_PROGRAM);
38 	io_space = &cpu->space(AS_IO);
39 
40 	// do not change the next two
41 	memory_window_start = 0x10000000;
42 	memory_window_end = 0xfeefffff;
43 	memory_offset = 0;
44 	// do not change the next two
45 	io_window_start = 0x5000;
46 	io_window_end = 0xefff;
47 	io_offset = 0;
48 }
49 
device_reset()50 void nv2a_host_device::device_reset()
51 {
52 	pci_host_device::device_reset();
53 }
54 
55 /*
56  * Ram
57  */
58 
59 DEFINE_DEVICE_TYPE(NV2A_RAM, nv2a_ram_device, "nv2a_ram", "NV2A Memory Controller - SDRAM")
60 
config_map(address_map & map)61 void nv2a_ram_device::config_map(address_map &map)
62 {
63 	pci_device::config_map(map);
64 	map(0x6c, 0x6f).rw(FUNC(nv2a_ram_device::config_register_r), FUNC(nv2a_ram_device::config_register_w));
65 }
66 
nv2a_ram_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)67 nv2a_ram_device::nv2a_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
68 	: pci_device(mconfig, NV2A_RAM, tag, owner, clock)
69 {
70 	set_ids(0x10de02a6, 0, 0, 0);
71 }
72 
device_start()73 void nv2a_ram_device::device_start()
74 {
75 	pci_device::device_start();
76 	ram.resize(ram_size * 1024 * 1024 / 4);
77 }
78 
config_register_r()79 uint32_t nv2a_ram_device::config_register_r()
80 {
81 	return 0x08800044;
82 }
83 
config_register_w(uint32_t data)84 void nv2a_ram_device::config_register_w(uint32_t data)
85 {
86 }
87 
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)88 void nv2a_ram_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
89 	uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
90 {
91 	memory_space->install_ram(0x00000000, ram_size * 1024 * 1024 - 1, &ram[0]);
92 }
93 
94 /*
95  * LPC Bus
96  */
97 
98 DEFINE_DEVICE_TYPE(MCPX_ISALPC, mcpx_isalpc_device, "mcpx_isalpc", "MCPX HUB Interface - ISA Bridge")
99 
lpc_io(address_map & map)100 void mcpx_isalpc_device::lpc_io(address_map &map)
101 {
102 	map(0x00000000, 0x000000ff).rw(FUNC(mcpx_isalpc_device::acpi_r), FUNC(mcpx_isalpc_device::acpi_w));
103 }
104 
internal_io_map(address_map & map)105 void mcpx_isalpc_device::internal_io_map(address_map &map)
106 {
107 	map(0x0020, 0x0023).rw("pic8259_1", FUNC(pic8259_device::read), FUNC(pic8259_device::write));
108 	map(0x0040, 0x0043).rw("pit8254", FUNC(pit8254_device::read), FUNC(pit8254_device::write));
109 	map(0x0061, 0x0061).rw(FUNC(mcpx_isalpc_device::portb_r), FUNC(mcpx_isalpc_device::portb_w));
110 	map(0x0070, 0x0073).rw("rtc", FUNC(ds12885ext_device::read_extended), FUNC(ds12885ext_device::write_extended));
111 	map(0x0080, 0x0080).w(FUNC(mcpx_isalpc_device::boot_state_w));
112 	map(0x00a0, 0x00a3).rw("pic8259_2", FUNC(pic8259_device::read), FUNC(pic8259_device::write));
113 	map(0x00e0, 0x00e3).nopw();
114 }
115 
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)116 void mcpx_isalpc_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
117 	uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
118 {
119 	io_space->install_device(0, 0xffff, *this, &mcpx_isalpc_device::internal_io_map);
120 	for (int a = 0; a < 16; a++)
121 		if (lpcdevices[a] != nullptr)
122 			lpcdevices[a]->map_extra(memory_space, io_space);
123 }
124 
mcpx_isalpc_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t subsystem_id)125 mcpx_isalpc_device::mcpx_isalpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t subsystem_id)
126 	: mcpx_isalpc_device(mconfig, tag, owner, clock)
127 {
128 	// revision id must be at least 0xb4 in the xbox, otherwise usb will require a hub
129 	// in the a7n266-c motherboard it has revision 0xc3
130 	set_ids(0x10de01b2, 0xb4, 0x060100, subsystem_id);
131 }
132 
mcpx_isalpc_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)133 mcpx_isalpc_device::mcpx_isalpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
134 	: pci_device(mconfig, MCPX_ISALPC, tag, owner, clock),
135 	m_smi_callback(*this),
136 	m_interrupt_output(*this),
137 	m_boot_state_hook(*this),
138 	pic8259_1(*this, "pic8259_1"),
139 	pic8259_2(*this, "pic8259_2"),
140 	pit8254(*this, "pit8254"),
141 	m_pm1_status(0),
142 	m_pm1_enable(0),
143 	m_pm1_control(0),
144 	m_pm1_timer(0),
145 	m_gpe0_status(0),
146 	m_gpe0_enable(0),
147 	m_global_smi_control(0),
148 	m_smi_command_port(0),
149 	m_speaker(0),
150 	m_refresh(false),
151 	m_pit_out2(0),
152 	m_spkrdata(0),
153 	m_channel_check(0)
154 {
155 }
156 
device_start()157 void mcpx_isalpc_device::device_start()
158 {
159 	pci_device::device_start();
160 	set_multifunction_device(true);
161 	m_smi_callback.resolve_safe();
162 	m_interrupt_output.resolve_safe();
163 	m_boot_state_hook.resolve_safe();
164 	add_map(0x00000100, M_IO, FUNC(mcpx_isalpc_device::lpc_io));
165 	bank_infos[0].adr = 0x8000;
166 	status = 0x00b0;
167 	command = 0x0001;
168 	command_mask = 0x01be;
169 	for (int a = 0; a < 16; a++)
170 		lpcdevices[a] = nullptr;
171 	for (device_t &d : subdevices())
172 	{
173 		const char *t = d.basetag();
174 		int l = strlen(t);
175 
176 		if (l == 1)
177 		{
178 			int address = strtol(t + l, nullptr, 16);
179 
180 			address = address & 15;
181 			if (lpcdevices[address] == nullptr)
182 			{
183 				lpcbus_device_interface *i = dynamic_cast<lpcbus_device_interface *>(&d);
184 				lpcdevices[address] = i;
185 				if (i)
186 					i->set_host(address, this);
187 			}
188 			else
189 				logerror("Duplicate address for LPC bus device with tag %s\n", t);
190 			break;
191 		}
192 	}
193 }
194 
device_reset()195 void mcpx_isalpc_device::device_reset()
196 {
197 	pci_device::device_reset();
198 	memset(m_gpio_mode, 0, sizeof(m_gpio_mode));
199 	m_refresh = false;
200 	m_pit_out2 = 1;
201 	m_spkrdata = 0;
202 }
203 
device_add_mconfig(machine_config & config)204 void mcpx_isalpc_device::device_add_mconfig(machine_config &config)
205 {
206 	pic8259_device &pic8259_1(PIC8259(config, "pic8259_1", 0));
207 	pic8259_1.out_int_callback().set(FUNC(mcpx_isalpc_device::interrupt_ouptut_changed));
208 	pic8259_1.in_sp_callback().set_constant(1);
209 	pic8259_1.read_slave_ack_callback().set(FUNC(mcpx_isalpc_device::get_slave_ack));
210 
211 	pic8259_device &pic8259_2(PIC8259(config, "pic8259_2", 0));
212 	pic8259_2.out_int_callback().set(pic8259_1, FUNC(pic8259_device::ir2_w));
213 	pic8259_2.in_sp_callback().set_constant(0);
214 
215 	pit8254_device &pit8254(PIT8254(config, "pit8254", 0));
216 	pit8254.set_clk<0>(1125000); /* heartbeat IRQ */
217 	pit8254.out_handler<0>().set(FUNC(mcpx_isalpc_device::pit8254_out0_changed));
218 	pit8254.set_clk<1>(1125000); /* originally dram refresh, now only legacy support */
219 	pit8254.out_handler<1>().set(FUNC(mcpx_isalpc_device::pit8254_out1_changed));
220 	pit8254.set_clk<2>(1125000); /* (unused) pio port c pin 4, and speaker polling enough */
221 	pit8254.out_handler<2>().set(FUNC(mcpx_isalpc_device::pit8254_out2_changed));
222 
223 	ds12885ext_device &ds12885(DS12885EXT(config, "rtc", 0));
224 	ds12885.irq().set(pic8259_2, FUNC(pic8259_device::ir0_w));
225 
226 	/*
227 	More devices are needed:
228 	    82093 compatible I/O APIC
229 	    dual 8237 DMA controllers
230 	*/
231 }
232 
update_smi_line()233 void mcpx_isalpc_device::update_smi_line()
234 {
235 	if (m_global_smi_control)
236 		m_smi_callback(1);
237 	else
238 		m_smi_callback(0);
239 }
240 
acpi_r(offs_t offset,uint32_t mem_mask)241 uint32_t mcpx_isalpc_device::acpi_r(offs_t offset, uint32_t mem_mask)
242 {
243 	logerror("Acpi read from %04X mask %08X\n", (bank_infos[0].adr & 0xfffffffe) + offset * 4, mem_mask);
244 	if ((offset == 0xa) && ACCESSING_BITS_0_15)
245 		return m_global_smi_control;
246 	if ((offset == 0xb) && ACCESSING_BITS_16_23)
247 		return m_smi_command_port << 16;
248 	return 0;
249 }
250 
acpi_w(offs_t offset,uint32_t data,uint32_t mem_mask)251 void mcpx_isalpc_device::acpi_w(offs_t offset, uint32_t data, uint32_t mem_mask)
252 {
253 	logerror("Acpi write %08X to %04X mask %08X\n", data, (bank_infos[0].adr & 0xfffffffe) + offset * 4, mem_mask);
254 	// Seen using word registers at offsets
255 	// 0x00 0x02 0x04 0x08 0x20 0x22 0x28 0xa0 0xa2 0xc0-0xd8
256 	// Byte access at 0x2e
257 	if ((offset == 0) && ACCESSING_BITS_0_15)
258 		// pm1 status register
259 		m_pm1_status = data & 0xffff;
260 	else if ((offset == 0) && ACCESSING_BITS_16_31)
261 		// pm1 enable register
262 		m_pm1_enable = data >> 16;
263 	else if ((offset == 1) && ACCESSING_BITS_0_15)
264 		// pm1 control register
265 		m_pm1_control = data & 0xffff;
266 	else if ((offset == 2) && ACCESSING_BITS_0_15)
267 		// pm1 timer register
268 		m_pm1_timer = data & 0xffff;
269 	else if ((offset == 8) && ACCESSING_BITS_0_15)
270 		// gpe0 status register
271 		m_gpe0_status = data & 0xffff;
272 	else if ((offset == 8) && ACCESSING_BITS_16_31)
273 		// gpe0 enable register
274 		m_gpe0_enable = data >> 16;
275 	else if ((offset == 0xa) && ACCESSING_BITS_0_15)
276 	{
277 		// Global SMI Control
278 		m_global_smi_control = m_global_smi_control & (~data & 0xffff);
279 		update_smi_line();
280 	}
281 	else if ((offset == 0xb) && ACCESSING_BITS_16_23)
282 	{
283 		// SMI Command Port
284 		// write to byte 0x2e must generate a SMI interrupt
285 		m_smi_command_port = (data >> 16) & 0xff;
286 		m_global_smi_control |= 0x200;
287 		update_smi_line();
288 		logerror("Generate software SMI with value %02X\n", m_smi_command_port);
289 	}
290 	else if (((offset >= 0x30) && (offset < 0x36)) || ((offset == 0x36) && ACCESSING_BITS_0_15))
291 	{
292 		int m = offset != 0x36 ? 4 : 2;
293 		int p = (offset - 0x30) * 4;
294 
295 		for (int a = 0; a < m; a++)
296 		{
297 			m_gpio_mode[p] = (m_gpio_mode[p] & (~mem_mask & 0xff)) | (data & 0xff);
298 			p++;
299 			data = data >> 8;
300 			mem_mask = mem_mask >> 8;
301 		}
302 	}
303 	else
304 		logerror("Acpi write not recognized\n");
305 }
306 
boot_state_w(uint8_t data)307 void mcpx_isalpc_device::boot_state_w(uint8_t data)
308 {
309 	if (m_boot_state_hook)
310 		m_boot_state_hook((offs_t)0, data);
311 }
312 
WRITE_LINE_MEMBER(mcpx_isalpc_device::interrupt_ouptut_changed)313 WRITE_LINE_MEMBER(mcpx_isalpc_device::interrupt_ouptut_changed)
314 {
315 	m_interrupt_output(state);
316 }
317 
get_slave_ack(offs_t offset)318 uint8_t mcpx_isalpc_device::get_slave_ack(offs_t offset)
319 {
320 	if (offset == 2) // IRQ = 2
321 		return pic8259_2->acknowledge();
322 	return 0x00;
323 }
324 
WRITE_LINE_MEMBER(mcpx_isalpc_device::pit8254_out0_changed)325 WRITE_LINE_MEMBER(mcpx_isalpc_device::pit8254_out0_changed)
326 {
327 	pic8259_1->ir0_w(state);
328 }
329 
WRITE_LINE_MEMBER(mcpx_isalpc_device::pit8254_out1_changed)330 WRITE_LINE_MEMBER(mcpx_isalpc_device::pit8254_out1_changed)
331 {
332 	if (state)
333 		m_refresh = !m_refresh;
334 }
335 
WRITE_LINE_MEMBER(mcpx_isalpc_device::pit8254_out2_changed)336 WRITE_LINE_MEMBER(mcpx_isalpc_device::pit8254_out2_changed)
337 {
338 	m_pit_out2 = state ? 1 : 0;
339 	//xbox_speaker_set_input(m_at_spkrdata & m_pit_out2);
340 }
341 
WRITE_LINE_MEMBER(mcpx_isalpc_device::irq1)342 WRITE_LINE_MEMBER(mcpx_isalpc_device::irq1)
343 {
344 	pic8259_1->ir1_w(state);
345 }
346 
WRITE_LINE_MEMBER(mcpx_isalpc_device::irq3)347 WRITE_LINE_MEMBER(mcpx_isalpc_device::irq3)
348 {
349 	pic8259_1->ir3_w(state);
350 }
351 
WRITE_LINE_MEMBER(mcpx_isalpc_device::irq10)352 WRITE_LINE_MEMBER(mcpx_isalpc_device::irq10)
353 {
354 	pic8259_2->ir2_w(state);
355 }
356 
WRITE_LINE_MEMBER(mcpx_isalpc_device::irq11)357 WRITE_LINE_MEMBER(mcpx_isalpc_device::irq11)
358 {
359 	pic8259_2->ir3_w(state);
360 }
361 
WRITE_LINE_MEMBER(mcpx_isalpc_device::irq14)362 WRITE_LINE_MEMBER(mcpx_isalpc_device::irq14)
363 {
364 	pic8259_2->ir6_w(state);
365 }
366 
WRITE_LINE_MEMBER(mcpx_isalpc_device::irq15)367 WRITE_LINE_MEMBER(mcpx_isalpc_device::irq15)
368 {
369 	pic8259_2->ir7_w(state);
370 }
371 
portb_r()372 uint8_t mcpx_isalpc_device::portb_r()
373 {
374 	uint8_t data = m_speaker;
375 
376 	data &= ~0xd0; /* AT BIOS don't likes this being set */
377 	/* 0x10 is the dram refresh line bit on the 5170, just a timer here, 15.085us. */
378 	data |= m_refresh ? 0x10 : 0;
379 	if (m_pit_out2)
380 		data |= 0x20;
381 	else
382 		data &= ~0x20; /* ps2m30 wants this */
383 
384 	return data;
385 }
386 
portb_w(uint8_t data)387 void mcpx_isalpc_device::portb_w(uint8_t data)
388 {
389 	m_speaker = data;
390 	pit8254->write_gate2(BIT(data, 0));
391 	speaker_set_spkrdata(BIT(data, 1));
392 	m_channel_check = BIT(data, 3);
393 	//if (m_channel_check) m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
394 }
395 
acknowledge()396 uint32_t mcpx_isalpc_device::acknowledge()
397 {
398 	return pic8259_1->acknowledge();
399 }
400 
speaker_set_spkrdata(uint8_t data)401 void mcpx_isalpc_device::speaker_set_spkrdata(uint8_t data)
402 {
403 	m_spkrdata = data ? 1 : 0;
404 	//xbox_speaker_set_input(m_at_spkrdata & m_pit_out2);
405 }
406 
debug_generate_irq(int irq,int state)407 void mcpx_isalpc_device::debug_generate_irq(int irq, int state)
408 {
409 	set_virtual_line(irq, state);
410 }
411 
set_virtual_line(int line,int state)412 void mcpx_isalpc_device::set_virtual_line(int line, int state)
413 {
414 	if (line < 16)
415 	{
416 		switch (line)
417 		{
418 		case 0:
419 			pic8259_1->ir0_w(state);
420 			break;
421 		case 1:
422 			pic8259_1->ir1_w(state);
423 			break;
424 		case 3:
425 			pic8259_1->ir3_w(state);
426 			break;
427 		case 4:
428 			pic8259_1->ir4_w(state);
429 			break;
430 		case 5:
431 			pic8259_1->ir5_w(state);
432 			break;
433 		case 6:
434 			pic8259_1->ir6_w(state);
435 			break;
436 		case 7:
437 			pic8259_1->ir7_w(state);
438 			break;
439 		case 8:
440 			pic8259_2->ir0_w(state);
441 			break;
442 		case 9:
443 			pic8259_2->ir1_w(state);
444 			break;
445 		case 10:
446 			pic8259_2->ir2_w(state);
447 			break;
448 		case 11:
449 			pic8259_2->ir3_w(state);
450 			break;
451 		case 12:
452 			pic8259_2->ir4_w(state);
453 			break;
454 		case 13:
455 			pic8259_2->ir5_w(state);
456 			break;
457 		case 14:
458 			pic8259_2->ir6_w(state);
459 			break;
460 		case 15:
461 			pic8259_2->ir7_w(state);
462 			break;
463 		}
464 		return;
465 	}
466 /* Will be updated to support dma
467     line = line - 16;
468     if (line < 4)
469     {
470         switch (line)
471         {
472         case 0:
473             break;
474         case 1:
475             break;
476         case 2:
477             break;
478         case 3:
479             break;
480         }
481     }
482 */
483 }
484 
remap()485 void mcpx_isalpc_device::remap()
486 {
487 	remap_cb();
488 }
489 
490 /*
491  * SMBus
492  */
493 
494 DEFINE_DEVICE_TYPE(MCPX_SMBUS, mcpx_smbus_device, "mcpx_smbus", "MCPX SMBus Controller")
495 
config_map(address_map & map)496 void mcpx_smbus_device::config_map(address_map &map)
497 {
498 	pci_device::config_map(map);
499 	map(0x3e, 0x3e).r(FUNC(mcpx_smbus_device::minimum_grant_r));
500 	map(0x3f, 0x3f).r(FUNC(mcpx_smbus_device::maximum_latency_r));
501 }
502 
smbus_io0(address_map & map)503 void mcpx_smbus_device::smbus_io0(address_map &map)
504 {
505 	map(0x00000000, 0x0000000f).rw(FUNC(mcpx_smbus_device::smbus0_r), FUNC(mcpx_smbus_device::smbus0_w));
506 }
507 
smbus_io1(address_map & map)508 void mcpx_smbus_device::smbus_io1(address_map &map)
509 {
510 	map(0x00000000, 0x0000000f).rw(FUNC(mcpx_smbus_device::smbus1_r), FUNC(mcpx_smbus_device::smbus1_w));
511 }
512 
smbus_io2(address_map & map)513 void mcpx_smbus_device::smbus_io2(address_map &map)
514 {
515 	map(0x00000000, 0x0000001f).noprw();
516 }
517 
mcpx_smbus_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t subsystem_id)518 mcpx_smbus_device::mcpx_smbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t subsystem_id)
519 	: mcpx_smbus_device(mconfig, tag, owner, clock)
520 {
521 	set_ids(0x10de01b4, 0xc1, 0x0c0500, subsystem_id);
522 }
523 
mcpx_smbus_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)524 mcpx_smbus_device::mcpx_smbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
525 	: pci_device(mconfig, MCPX_SMBUS, tag, owner, clock),
526 	m_interrupt_handler(*this)
527 {
528 }
529 
device_start()530 void mcpx_smbus_device::device_start()
531 {
532 	pci_device::device_start();
533 	set_multifunction_device(true);
534 	m_interrupt_handler.resolve_safe();
535 	add_map(0x00000010, M_IO, FUNC(mcpx_smbus_device::smbus_io0));
536 	bank_infos[0].adr = 0x1000;
537 	add_map(0x00000010, M_IO, FUNC(mcpx_smbus_device::smbus_io1));
538 	bank_infos[1].adr = 0xc000;
539 	add_map(0x00000020, M_IO, FUNC(mcpx_smbus_device::smbus_io2));
540 	bank_infos[2].adr = 0xc200;
541 	status = 0x00b0;
542 	command = 0x0001;
543 	// Min Grant 3
544 	// Max Latency 1
545 	intr_pin = 1;
546 	memset(&smbusst, 0, sizeof(smbusst));
547 	for (int b = 0; b < 2; b++)
548 		for (int a = 0; a < 128; a++)
549 			smbusst[b].devices[a] = nullptr;
550 	for (device_t &d : subdevices())
551 	{
552 		const char *t = d.tag();
553 		int l = strlen(t);
554 
555 		while (l > 0)
556 		{
557 			l--;
558 			if (t[l] == ':')
559 			{
560 				l++;
561 				int address = strtol(t + l, nullptr, 16);
562 				int bus;
563 
564 				bus = address >> 8;
565 				address = address & 0xff;
566 				if ((address > 0) && (address < 128) && (bus >= 0) && (bus <= 1))
567 				{
568 					if (smbusst[bus].devices[address] == nullptr)
569 					{
570 						smbus_interface *i = dynamic_cast<smbus_interface *>(&d);
571 						smbusst[bus].devices[address] = i;
572 					}
573 					else
574 						logerror("Duplicate address for SMBus device with tag %s\n", t);
575 				}
576 				else
577 					logerror("Invalid address for SMBus device with tag %s\n", t);
578 				break;
579 			}
580 		}
581 	}
582 }
583 
device_reset()584 void mcpx_smbus_device::device_reset()
585 {
586 	pci_device::device_reset();
587 }
588 
smbus_read(int bus,offs_t offset,uint32_t mem_mask)589 uint32_t mcpx_smbus_device::smbus_read(int bus, offs_t offset, uint32_t mem_mask)
590 {
591 	if (offset == 0) // 0 smbus status
592 		smbusst[bus].words[offset] = (smbusst[bus].words[offset] & ~0xffff) | ((smbusst[bus].status & 0xffff) << 0);
593 	if (offset == 1) // 6 smbus data
594 		smbusst[bus].words[offset] = (smbusst[bus].words[offset] & ~(0xffff << 16)) | ((smbusst[bus].data & 0xffff) << 16);
595 	return smbusst[bus].words[offset];
596 }
597 
smbus_write(int bus,offs_t offset,uint32_t data,uint32_t mem_mask)598 void mcpx_smbus_device::smbus_write(int bus, offs_t offset, uint32_t data, uint32_t mem_mask)
599 {
600 	COMBINE_DATA(smbusst[bus].words);
601 	if ((offset == 0) && (ACCESSING_BITS_0_7 || ACCESSING_BITS_8_15)) // 0 smbus status
602 	{
603 		if (!((smbusst[bus].status ^ data) & 0x10)) // clearing interrupt
604 		{
605 			if (m_interrupt_handler)
606 				m_interrupt_handler(0);
607 		}
608 		smbusst[bus].status &= ~data;
609 	}
610 	if ((offset == 0) && ACCESSING_BITS_16_23) // 2 smbus control
611 	{
612 		data = data >> 16;
613 		smbusst[bus].control = data;
614 		int cycletype = smbusst[bus].control & 7;
615 		if (smbusst[bus].control & 8) { // start
616 			if ((cycletype & 6) == 2)
617 			{
618 				if (smbusst[bus].devices[smbusst[bus].address])
619 					if (smbusst[bus].rw == 0)
620 						smbusst[bus].devices[smbusst[bus].address]->execute_command(smbusst[bus].command, smbusst[bus].rw, smbusst[bus].data);
621 					else
622 						smbusst[bus].data = smbusst[bus].devices[smbusst[bus].address]->execute_command(smbusst[bus].command, smbusst[bus].rw, smbusst[bus].data);
623 				else
624 					logerror("SMBUS: access to missing device at bus %d address %d\n", bus, smbusst[bus].address);
625 				smbusst[bus].status |= 0x10;
626 				if (smbusst[bus].control & 0x10)
627 				{
628 					if (m_interrupt_handler)
629 						m_interrupt_handler(1);
630 				}
631 			}
632 		}
633 	}
634 	if ((offset == 1) && ACCESSING_BITS_0_7) // 4 smbus address
635 	{
636 		smbusst[bus].address = data >> 1;
637 		smbusst[bus].rw = data & 1;
638 	}
639 	if ((offset == 1) && (ACCESSING_BITS_16_23 || ACCESSING_BITS_16_31)) // 6 smbus data
640 	{
641 		data = data >> 16;
642 		smbusst[bus].data = data;
643 	}
644 	if ((offset == 2) && ACCESSING_BITS_0_7) // 8 smbus command
645 		smbusst[bus].command = data;
646 }
647 
smbus0_r(offs_t offset,uint32_t mem_mask)648 uint32_t mcpx_smbus_device::smbus0_r(offs_t offset, uint32_t mem_mask)
649 {
650 	return smbus_read(0, offset, mem_mask);
651 }
652 
smbus0_w(offs_t offset,uint32_t data,uint32_t mem_mask)653 void mcpx_smbus_device::smbus0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
654 {
655 	smbus_write(0, offset, data, mem_mask);
656 }
657 
smbus1_r(offs_t offset,uint32_t mem_mask)658 uint32_t mcpx_smbus_device::smbus1_r(offs_t offset, uint32_t mem_mask)
659 {
660 	return smbus_read(1, offset, mem_mask);
661 }
662 
smbus1_w(offs_t offset,uint32_t data,uint32_t mem_mask)663 void mcpx_smbus_device::smbus1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
664 {
665 	smbus_write(1, offset, data, mem_mask);
666 }
667 
668 /*
669  * OHCI USB Controller
670  */
671 
672 DEFINE_DEVICE_TYPE(MCPX_OHCI, mcpx_ohci_device, "mcpx_ohci", "MCPX OHCI USB Controller")
673 
config_map(address_map & map)674 void mcpx_ohci_device::config_map(address_map &map)
675 {
676 	pci_device::config_map(map);
677 	map(0x3e, 0x3e).r(FUNC(mcpx_ohci_device::minimum_grant_r));
678 	map(0x3f, 0x3f).r(FUNC(mcpx_ohci_device::maximum_latency_r));
679 }
680 
ohci_mmio(address_map & map)681 void mcpx_ohci_device::ohci_mmio(address_map &map)
682 {
683 	map(0x00000000, 0x00000fff).rw(FUNC(mcpx_ohci_device::ohci_r), FUNC(mcpx_ohci_device::ohci_w));
684 }
685 
mcpx_ohci_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t subsystem_id)686 mcpx_ohci_device::mcpx_ohci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t subsystem_id)
687 	: mcpx_ohci_device(mconfig, tag, owner, clock)
688 {
689 	set_ids(0x10de01c2, 0xc3, 0x0c0310, subsystem_id);
690 }
691 
mcpx_ohci_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)692 mcpx_ohci_device::mcpx_ohci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
693 	: pci_device(mconfig, MCPX_OHCI, tag, owner, clock),
694 	ohci_usb(nullptr),
695 	m_interrupt_handler(*this),
696 	timer(nullptr),
697 	maincpu(*this, ":maincpu"),
698 	connecteds_count(0)
699 {
700 }
701 
plug_usb_device(int port,device_usb_ohci_function_interface * function)702 void mcpx_ohci_device::plug_usb_device(int port, device_usb_ohci_function_interface *function)
703 {
704 	function->set_bus_manager(ohci_usb);
705 	ohci_usb->usb_ohci_plug(port, function);
706 }
707 
device_start()708 void mcpx_ohci_device::device_start()
709 {
710 	pci_device::device_start();
711 	m_interrupt_handler.resolve_safe();
712 	add_map(0x00001000, M_MEM, FUNC(mcpx_ohci_device::ohci_mmio));
713 	bank_infos[0].adr = 0xfed00000;
714 	status = 0x00b0;
715 	command = 0x0002;
716 	intr_pin = 1;
717 	ohci_usb = new ohci_usb_controller();
718 	ohci_usb->set_cpu(maincpu.target());
719 	ohci_usb->set_irq_callback(
720 		[&](int state)
721 		{
722 			m_interrupt_handler(state);
723 		}
724 	);
725 	timer = timer_alloc(0);
726 	ohci_usb->set_timer(timer);
727 	ohci_usb->start();
728 	for (int i=0;i < connecteds_count;i++)
729 		plug_usb_device(connecteds[i].port, connecteds[i].dev);
730 }
731 
device_reset()732 void mcpx_ohci_device::device_reset()
733 {
734 	pci_device::device_reset();
735 	if (ohci_usb)
736 		ohci_usb->reset();
737 }
738 
device_config_complete()739 void mcpx_ohci_device::device_config_complete()
740 {
741 	char id[8];
742 
743 	for (int i = 1; i<=4; i++)
744 	{
745 		sprintf(id, "port%d", i);
746 		ohci_usb_connector *conn = downcast<ohci_usb_connector *>(subdevice(id));
747 		if (conn)
748 		{
749 			device_usb_ohci_function_interface *func = conn->get_card_device();
750 			if (func)
751 			{
752 				connecteds[connecteds_count].dev = func;
753 				connecteds[connecteds_count].port = i;
754 				connecteds_count++;
755 			}
756 		}
757 	}
758 }
759 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)760 void mcpx_ohci_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
761 {
762 	if (ohci_usb)
763 		ohci_usb->timer(timer, id, param, ptr);
764 }
765 
ohci_r(offs_t offset)766 uint32_t mcpx_ohci_device::ohci_r(offs_t offset)
767 {
768 	if (!ohci_usb)
769 		return 0;
770 	if (offset == 0) // hacks needed until usb (and jvs) is implemented
771 	{
772 		hack_callback();
773 	}
774 	return ohci_usb->read(offset);
775 }
776 
ohci_w(offs_t offset,uint32_t data)777 void mcpx_ohci_device::ohci_w(offs_t offset, uint32_t data)
778 {
779 	if (ohci_usb)
780 		ohci_usb->write(offset, data);
781 }
782 
783 /*
784  * Ethernet
785  */
786 
787 DEFINE_DEVICE_TYPE(MCPX_ETH, mcpx_eth_device, "mcpx_eth", "MCP Networking Adapter")
788 
eth_mmio(address_map & map)789 void mcpx_eth_device::eth_mmio(address_map &map)
790 {
791 	map(0x00000000, 0x0000003ff).rw(FUNC(mcpx_eth_device::eth_r), FUNC(mcpx_eth_device::eth_w));
792 }
793 
eth_io(address_map & map)794 void mcpx_eth_device::eth_io(address_map &map)
795 {
796 	map(0x00000000, 0x000000007).rw(FUNC(mcpx_eth_device::eth_io_r), FUNC(mcpx_eth_device::eth_io_w));
797 }
798 
mcpx_eth_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)799 mcpx_eth_device::mcpx_eth_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
800 	: pci_device(mconfig, MCPX_ETH, tag, owner, clock)
801 {
802 	set_ids(0x10de01c3, 0, 0, 0);
803 }
804 
device_start()805 void mcpx_eth_device::device_start()
806 {
807 	pci_device::device_start();
808 	add_map(0x00001000, M_MEM, FUNC(mcpx_eth_device::eth_mmio));
809 	bank_infos[0].adr = 0xfef00000;
810 	add_map(0x00000100, M_IO, FUNC(mcpx_eth_device::eth_io));
811 	bank_infos[1].adr = 0xe000;
812 }
813 
device_reset()814 void mcpx_eth_device::device_reset()
815 {
816 	pci_device::device_reset();
817 }
818 
eth_r()819 uint32_t mcpx_eth_device::eth_r()
820 {
821 	return 0;
822 }
823 
eth_w(uint32_t data)824 void mcpx_eth_device::eth_w(uint32_t data)
825 {
826 }
827 
eth_io_r()828 uint32_t mcpx_eth_device::eth_io_r()
829 {
830 	return 0;
831 }
832 
eth_io_w(uint32_t data)833 void mcpx_eth_device::eth_io_w(uint32_t data)
834 {
835 }
836 
837 /*
838  * Audio Processing Unit
839  */
840 
841 DEFINE_DEVICE_TYPE(MCPX_APU, mcpx_apu_device, "mcpx_apu", "MCP APU")
842 
config_map(address_map & map)843 void mcpx_apu_device::config_map(address_map &map)
844 {
845 	pci_device::config_map(map);
846 	map(0x3e, 0x3e).r(FUNC(mcpx_apu_device::minimum_grant_r));
847 	map(0x3f, 0x3f).r(FUNC(mcpx_apu_device::maximum_latency_r));
848 }
849 
apu_mmio(address_map & map)850 void mcpx_apu_device::apu_mmio(address_map &map)
851 {
852 	map(0x00000000, 0x00007ffff).rw(FUNC(mcpx_apu_device::apu_r), FUNC(mcpx_apu_device::apu_w));
853 }
854 
mcpx_apu_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)855 mcpx_apu_device::mcpx_apu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
856 	pci_device(mconfig, MCPX_APU, tag, owner, clock),
857 	cpu(*this, finder_base::DUMMY_TAG)
858 {
859 }
860 
device_start()861 void mcpx_apu_device::device_start()
862 {
863 	pci_device::device_start();
864 	add_map(0x00080000, M_MEM, FUNC(mcpx_apu_device::apu_mmio));
865 	bank_infos[0].adr = 0xfe800000;
866 	status = 0x00b0;
867 	command = 0x0002;
868 	intr_pin = 1;
869 	memset(apust.memory, 0, sizeof(apust.memory));
870 	memset(apust.voices_heap_blockaddr, 0, sizeof(apust.voices_heap_blockaddr));
871 	memset(apust.voices_active, 0, sizeof(apust.voices_active));
872 	memset(apust.voices_position, 0, sizeof(apust.voices_position));
873 	memset(apust.voices_position_start, 0, sizeof(apust.voices_position_start));
874 	memset(apust.voices_position_end, 0, sizeof(apust.voices_position_end));
875 	memset(apust.voices_position_increment, 0, sizeof(apust.voices_position_increment));
876 	apust.space = &cpu->space();
877 	apust.timer = timer_alloc(0);
878 	apust.timer->enable(false);
879 }
880 
device_reset()881 void mcpx_apu_device::device_reset()
882 {
883 	pci_device::device_reset();
884 }
885 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)886 void mcpx_apu_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
887 {
888 	int cmd;
889 	int bb, b, v;
890 	uint64_t bv;
891 	uint32_t phys;
892 
893 	// this works only for outr2
894 	// value at 0x810 is modified by the firmware that has been loaded on the gp dsp
895 	cmd = apust.space->read_dword(apust.gpdsp_address + 0x800 + 0x10);
896 	if (cmd == 3)
897 		apust.space->write_dword(apust.gpdsp_address + 0x800 + 0x10, 0);
898 	/*else
899 	logerror("Audio_APU: unexpected value at address %d\n",apust.gpdsp_address+0x800+0x10);*/
900 	// check all the 256 possible voices
901 	for (b = 0; b < 4; b++) {
902 		bv = 1;
903 		for (bb = 0; bb < 64; bb++) {
904 			if (apust.voices_active[b] & bv) {
905 				v = bb + (b << 6);
906 				apust.voices_position[v] += apust.voices_position_increment[v];
907 				while (apust.voices_position[v] >= apust.voices_position_end[v])
908 					apust.voices_position[v] = apust.voices_position_start[v] + apust.voices_position[v] - apust.voices_position_end[v] - 1000;
909 				phys = apust.voicedata_address + 0x80 * v;
910 				apust.space->write_dword(phys + 0x58, apust.voices_position[v] / 1000);
911 			}
912 			bv = bv << 1;
913 		}
914 	}
915 }
916 
apu_r(offs_t offset,uint32_t mem_mask)917 uint32_t mcpx_apu_device::apu_r(offs_t offset, uint32_t mem_mask)
918 {
919 #ifdef LOG_AUDIO
920 	logerror("Audio_APU: read from %08X mask %08X\n", 0xfe800000 + offset * 4, mem_mask);
921 #endif
922 	if (offset == 0x20010 / 4) // some kind of internal counter or state value
923 		return 0x20 + 4 + 8 + 0x48 + 0x80;
924 	return apust.memory[offset];
925 }
926 
apu_w(offs_t offset,uint32_t data,uint32_t mem_mask)927 void mcpx_apu_device::apu_w(offs_t offset, uint32_t data, uint32_t mem_mask)
928 {
929 	uint32_t v;
930 
931 #ifdef LOG_AUDIO
932 	logerror("Audio_APU: write at %08X mask %08X value %08X\n", 0xfe800000 + offset * 4, mem_mask, data);
933 #endif
934 	apust.memory[offset] = data;
935 	if (offset == 0x02040 / 4) // address of memory area with scatter-gather info (gpdsp scratch dma)
936 		apust.gpdsp_sgaddress = data;
937 	if (offset == 0x020d4 / 4) { // block count (gpdsp)
938 		apust.gpdsp_sgblocks = data;
939 		apust.gpdsp_address = apust.space->read_dword(apust.gpdsp_sgaddress); // memory address of first block
940 		apust.timer->enable();
941 		apust.timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1));
942 	}
943 	if (offset == 0x02048 / 4) // (epdsp scratch dma)
944 		apust.epdsp_sgaddress = data;
945 	if (offset == 0x020dc / 4) // (epdsp)
946 		apust.epdsp_sgblocks = data;
947 	if (offset == 0x0204c / 4) // address of memory area with information about blocks
948 		apust.epdsp_sgaddress2 = data;
949 	if (offset == 0x020e0 / 4) // block count - 1
950 		apust.epdsp_sgblocks2 = data;
951 	if (offset == 0x0202c / 4) { // address of memory area with 0x80 bytes for each voice
952 		apust.voicedata_address = data;
953 		return;
954 	}
955 	if (offset == 0x04024 / 4) // offset in memory area indicated by 0x204c (analog output ?)
956 		return;
957 	if (offset == 0x04034 / 4) // size
958 		return;
959 	if (offset == 0x04028 / 4) // offset in memory area indicated by 0x204c (digital output ?)
960 		return;
961 	if (offset == 0x04038 / 4) // size
962 		return;
963 	if (offset == 0x20804 / 4) { // block number for scatter-gather heap that stores sampled audio to be played
964 		if (data >= 1024) {
965 			logerror("Audio_APU: sg block number too high, increase size of voices_heap_blockaddr\n");
966 			apust.memory[offset] = 1023;
967 		}
968 		return;
969 	}
970 	if (offset == 0x20808 / 4) { // block address for scatter-gather heap that stores sampled audio to be played
971 		apust.voices_heap_blockaddr[apust.memory[0x20804 / 4]] = data;
972 		return;
973 	}
974 	if (offset == 0x202f8 / 4) { // voice number for parameters ?
975 		apust.voice_number = data;
976 		return;
977 	}
978 	if (offset == 0x202fc / 4) // 1 when accessing voice parameters 0 otherwise
979 		return;
980 	if (offset == 0x20304 / 4) { // format
981 		 /*
982 		 bits 28-31 sample format:
983 		 0  8-bit pcm
984 		 5  16-bit pcm
985 		 10 adpcm ?
986 		 14 24-bit pcm
987 		 15 32-bit pcm
988 		 bits 16-20 number of channels - 1:
989 		 0  mono
990 		 1  stereo
991 		 */
992 		return;
993 	}
994 	if (offset == 0x2037c / 4) { // value related to sample rate
995 		int16_t v0 = (int16_t)(data >> 16); // upper 16 bits as a signed 16 bit value
996 		float vv = ((float)v0) / 4096.0f; // divide by 4096
997 		float vvv = powf(2, vv); // two to the vv
998 		int f = vvv*48000.0f; // sample rate
999 		apust.voices_frequency[apust.voice_number] = f;
1000 		return;
1001 	}
1002 	if (offset == 0x203a0 / 4) // start offset of data in scatter-gather heap
1003 		return;
1004 	if (offset == 0x203a4 / 4) { // first sample to play
1005 		apust.voices_position_start[apust.voice_number] = data * 1000;
1006 		return;
1007 	}
1008 	if (offset == 0x203dc / 4) { // last sample to play
1009 		apust.voices_position_end[apust.voice_number] = data * 1000;
1010 		return;
1011 	}
1012 	if (offset == 0x2010c / 4) // voice processor 0 idle 1 not idle ?
1013 		return;
1014 	if (offset == 0x20124 / 4) { // voice number to activate ?
1015 		v = apust.voice_number;
1016 		apust.voices_active[v >> 6] |= ((uint64_t)1 << (v & 63));
1017 		apust.voices_position[v] = apust.voices_position_start[apust.voice_number];
1018 		apust.voices_position_increment[apust.voice_number] = apust.voices_frequency[apust.voice_number];
1019 		return;
1020 	}
1021 	if (offset == 0x20128 / 4) { // voice number to deactivate ?
1022 		v = apust.voice_number;
1023 		apust.voices_active[v >> 6] &= ~(1 << (v & 63));
1024 		return;
1025 	}
1026 	if (offset == 0x20140 / 4) // voice number to ?
1027 		return;
1028 	if ((offset >= 0x20200 / 4) && (offset < 0x20280 / 4)) // headroom for each of the 32 mixbins
1029 		return;
1030 	if (offset == 0x20280 / 4) // hrtf headroom ?
1031 		return;
1032 }
1033 
1034 /*
1035  * AC97 Audio Controller
1036  */
1037 
1038 DEFINE_DEVICE_TYPE(MCPX_AC97_AUDIO, mcpx_ac97_audio_device, "mcpx_ac97_audio", "MCPX AC'97 Audio Codec Interface")
1039 
config_map(address_map & map)1040 void mcpx_ac97_audio_device::config_map(address_map &map)
1041 {
1042 	pci_device::config_map(map);
1043 	map(0x3e, 0x3e).r(FUNC(mcpx_ac97_audio_device::minimum_grant_r));
1044 	map(0x3f, 0x3f).r(FUNC(mcpx_ac97_audio_device::maximum_latency_r));
1045 }
1046 
ac97_mmio(address_map & map)1047 void mcpx_ac97_audio_device::ac97_mmio(address_map &map)
1048 {
1049 	map(0x00000000, 0x000000fff).rw(FUNC(mcpx_ac97_audio_device::ac97_audio_r), FUNC(mcpx_ac97_audio_device::ac97_audio_w));
1050 }
1051 
ac97_io0(address_map & map)1052 void mcpx_ac97_audio_device::ac97_io0(address_map &map)
1053 {
1054 	map(0x00000000, 0x0000000ff).rw(FUNC(mcpx_ac97_audio_device::ac97_audio_io0_r), FUNC(mcpx_ac97_audio_device::ac97_audio_io0_w));
1055 }
1056 
ac97_io1(address_map & map)1057 void mcpx_ac97_audio_device::ac97_io1(address_map &map)
1058 {
1059 	map(0x00000000, 0x00000007f).rw(FUNC(mcpx_ac97_audio_device::ac97_audio_io1_r), FUNC(mcpx_ac97_audio_device::ac97_audio_io1_w));
1060 }
1061 
mcpx_ac97_audio_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t subsystem_id)1062 mcpx_ac97_audio_device::mcpx_ac97_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t subsystem_id)
1063 	: mcpx_ac97_audio_device(mconfig, tag, owner, clock)
1064 {
1065 	set_ids(0x10de01b1, 0xc2, 0x040100, subsystem_id);
1066 }
1067 
mcpx_ac97_audio_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1068 mcpx_ac97_audio_device::mcpx_ac97_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1069 	: pci_device(mconfig, MCPX_AC97_AUDIO, tag, owner, clock)
1070 {
1071 }
1072 
device_start()1073 void mcpx_ac97_audio_device::device_start()
1074 {
1075 	pci_device::device_start();
1076 	set_multifunction_device(true);
1077 	add_map(0x00000100, M_IO, FUNC(mcpx_ac97_audio_device::ac97_io0));
1078 	bank_infos[0].adr = 0xd000;
1079 	add_map(0x00000080, M_IO, FUNC(mcpx_ac97_audio_device::ac97_io1));
1080 	bank_infos[1].adr = 0xd200;
1081 	add_map(0x00001000, M_MEM, FUNC(mcpx_ac97_audio_device::ac97_mmio));
1082 	bank_infos[2].adr = 0xfec00000;
1083 	status = 0x00b0;
1084 	command = 0x0003;
1085 	intr_pin = 1;
1086 	memset(&ac97st, 0, sizeof(ac97st));
1087 }
1088 
device_reset()1089 void mcpx_ac97_audio_device::device_reset()
1090 {
1091 	pci_device::device_reset();
1092 }
1093 
ac97_audio_r(offs_t offset,uint32_t mem_mask)1094 uint32_t mcpx_ac97_audio_device::ac97_audio_r(offs_t offset, uint32_t mem_mask)
1095 {
1096 	uint32_t ret = 0;
1097 
1098 #ifdef LOG_AUDIO
1099 	logerror("Audio_AC3: read from %08X mask %08X\n", 0xfec00000 + offset * 4, mem_mask);
1100 #endif
1101 	if (offset < 0x80 / 4)
1102 	{
1103 		ret = ac97st.mixer_regs[offset];
1104 	}
1105 	if ((offset >= 0x100 / 4) && (offset <= 0x138 / 4))
1106 	{
1107 		offset = offset - 0x100 / 4;
1108 		if (offset == 0x18 / 4)
1109 		{
1110 			ac97st.controller_regs[offset] &= ~0x02000000; // REGRST: register reset
1111 		}
1112 		if (offset == 0x30 / 4)
1113 		{
1114 			ac97st.controller_regs[offset] |= 0x100; // PCRDY: primary codec ready
1115 		}
1116 		if (offset == 0x34 / 4)
1117 		{
1118 			ac97st.controller_regs[offset] &= ~1; // CAS: codec access semaphore
1119 		}
1120 		ret = ac97st.controller_regs[offset];
1121 	}
1122 	return ret;
1123 }
1124 
ac97_audio_w(offs_t offset,uint32_t data,uint32_t mem_mask)1125 void mcpx_ac97_audio_device::ac97_audio_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1126 {
1127 #ifdef LOG_AUDIO
1128 	logerror("Audio_AC3: write at %08X mask %08X value %08X\n", 0xfec00000 + offset * 4, mem_mask, data);
1129 #endif
1130 	if (offset < 0x80 / 4)
1131 	{
1132 		COMBINE_DATA(ac97st.mixer_regs + offset);
1133 	}
1134 	if ((offset >= 0x100 / 4) && (offset < 0x13c / 4))
1135 	{
1136 		offset = offset - 0x100 / 4;
1137 		COMBINE_DATA(ac97st.controller_regs + offset);
1138 	}
1139 }
1140 
ac97_audio_io0_r()1141 uint32_t mcpx_ac97_audio_device::ac97_audio_io0_r()
1142 {
1143 	return 0;
1144 }
1145 
ac97_audio_io0_w(uint32_t data)1146 void mcpx_ac97_audio_device::ac97_audio_io0_w(uint32_t data)
1147 {
1148 }
1149 
ac97_audio_io1_r()1150 uint32_t mcpx_ac97_audio_device::ac97_audio_io1_r()
1151 {
1152 	return 0;
1153 }
1154 
ac97_audio_io1_w(uint32_t data)1155 void mcpx_ac97_audio_device::ac97_audio_io1_w(uint32_t data)
1156 {
1157 }
1158 
1159 /*
1160  * AC97 Modem Controller
1161  */
1162 
1163 DEFINE_DEVICE_TYPE(MCPX_AC97_MODEM, mcpx_ac97_modem_device, "mcpx_ac97_modem", "MCPX AC'97 Modem Controller")
1164 
mcpx_ac97_modem_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1165 mcpx_ac97_modem_device::mcpx_ac97_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1166 	: pci_device(mconfig, MCPX_AC97_MODEM, tag, owner, clock)
1167 {
1168 	set_ids(0x10de01c1, 0, 0, 0);
1169 }
1170 
1171 /*
1172  * IDE Controller
1173  */
1174 
1175 DEFINE_DEVICE_TYPE(MCPX_IDE, mcpx_ide_device, "mcpx_ide", "MCPX IDE Controller")
1176 
config_map(address_map & map)1177 void mcpx_ide_device::config_map(address_map &map)
1178 {
1179 	pci_device::config_map(map);
1180 	map(0x08, 0x0b).rw(FUNC(pci_device::class_rev_r), FUNC(mcpx_ide_device::class_rev_w));
1181 	map(0x3e, 0x3e).r(FUNC(mcpx_ide_device::minimum_grant_r));
1182 	map(0x3f, 0x3f).r(FUNC(mcpx_ide_device::maximum_latency_r));
1183 }
1184 
ide_pri_command(address_map & map)1185 void mcpx_ide_device::ide_pri_command(address_map &map)
1186 {
1187 	map(0, 7).rw("ide1", FUNC(bus_master_ide_controller_device::cs0_r), FUNC(bus_master_ide_controller_device::cs0_w));
1188 }
1189 
ide_pri_control(address_map & map)1190 void mcpx_ide_device::ide_pri_control(address_map &map)
1191 {
1192 	// 3f6
1193 	map(2, 2).rw(FUNC(mcpx_ide_device::pri_read_cs1_r), FUNC(mcpx_ide_device::pri_write_cs1_w));
1194 }
1195 
ide_sec_command(address_map & map)1196 void mcpx_ide_device::ide_sec_command(address_map &map)
1197 {
1198 	map(0, 7).rw("ide2", FUNC(bus_master_ide_controller_device::cs0_r), FUNC(bus_master_ide_controller_device::cs0_w));
1199 }
1200 
ide_sec_control(address_map & map)1201 void mcpx_ide_device::ide_sec_control(address_map &map)
1202 {
1203 	// 376
1204 	map(2, 2).rw(FUNC(mcpx_ide_device::sec_read_cs1_r), FUNC(mcpx_ide_device::sec_write_cs1_w));
1205 }
1206 
ide_io(address_map & map)1207 void mcpx_ide_device::ide_io(address_map &map)
1208 {
1209 	map(0x0000, 0x0007).rw("ide1", FUNC(bus_master_ide_controller_device::bmdma_r), FUNC(bus_master_ide_controller_device::bmdma_w));
1210 	map(0x0008, 0x000f).rw("ide2", FUNC(bus_master_ide_controller_device::bmdma_r), FUNC(bus_master_ide_controller_device::bmdma_w));
1211 }
1212 
mcpx_ide_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,uint32_t subsystem_id)1213 mcpx_ide_device::mcpx_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t subsystem_id)
1214 	: mcpx_ide_device(mconfig, tag, owner, clock)
1215 {
1216 	set_ids(0x10de01bc, 0xc3, 0x01018a, subsystem_id);
1217 }
1218 
mcpx_ide_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1219 mcpx_ide_device::mcpx_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1220 	: pci_device(mconfig, MCPX_IDE, tag, owner, clock),
1221 	m_pri(*this, "ide1"),
1222 	m_sec(*this, "ide2"),
1223 	m_pri_interrupt_handler(*this),
1224 	m_sec_interrupt_handler(*this)
1225 {
1226 }
1227 
device_start()1228 void mcpx_ide_device::device_start()
1229 {
1230 	pci_device::device_start();
1231 	add_map(0x00000008, M_IO | M_DISABLED, FUNC(mcpx_ide_device::ide_pri_command)); // primary command block
1232 	add_map(0x00000004, M_IO | M_DISABLED, FUNC(mcpx_ide_device::ide_pri_control)); // primary control block
1233 	add_map(0x00000008, M_IO | M_DISABLED, FUNC(mcpx_ide_device::ide_sec_command)); // secondary command block
1234 	add_map(0x00000004, M_IO | M_DISABLED, FUNC(mcpx_ide_device::ide_sec_control)); // secondary control block
1235 	add_map(0x00000010, M_IO, FUNC(mcpx_ide_device::ide_io));
1236 	bank_infos[4].adr = 0xff60;
1237 	status = 0x00b0;
1238 	command = 0x0001;
1239 	m_pri_interrupt_handler.resolve_safe();
1240 	m_sec_interrupt_handler.resolve_safe();
1241 }
1242 
device_reset()1243 void mcpx_ide_device::device_reset()
1244 {
1245 	pci_device::device_reset();
1246 }
1247 
device_add_mconfig(machine_config & config)1248 void mcpx_ide_device::device_add_mconfig(machine_config &config)
1249 {
1250 	bus_master_ide_controller_device &ide1(BUS_MASTER_IDE_CONTROLLER(config, "ide1", 0));
1251 	ide1.irq_handler().set(FUNC(mcpx_ide_device::ide_pri_interrupt));
1252 	ide1.set_bus_master_space(":maincpu", AS_PROGRAM);
1253 
1254 	bus_master_ide_controller_device &ide2(BUS_MASTER_IDE_CONTROLLER(config, "ide2", 0));
1255 	ide2.irq_handler().set(FUNC(mcpx_ide_device::ide_sec_interrupt));
1256 	ide2.set_bus_master_space(":maincpu", AS_PROGRAM);
1257 }
1258 
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)1259 void mcpx_ide_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
1260 	uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
1261 {
1262 	// in compatibility mode the addresses are fixed, but the io enable bit in the command register is still used
1263 	if (~pclass & 1) // compatibility mode
1264 	{
1265 		if (command & 1)
1266 		{
1267 			io_space->install_device(0x1f0, 0x1f7, *this, &mcpx_ide_device::ide_pri_command);
1268 			io_space->install_device(0x3f4, 0x3f7, *this, &mcpx_ide_device::ide_pri_control);
1269 		}
1270 	}
1271 	if (~pclass & 4)
1272 	{
1273 		if (command & 1)
1274 		{
1275 			io_space->install_device(0x170, 0x177, *this, &mcpx_ide_device::ide_sec_command);
1276 			io_space->install_device(0x374, 0x377, *this, &mcpx_ide_device::ide_sec_control);
1277 		}
1278 	}
1279 }
1280 
class_rev_w(offs_t offset,uint32_t data,uint32_t mem_mask)1281 void mcpx_ide_device::class_rev_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1282 {
1283 	if (ACCESSING_BITS_8_15)
1284 	{
1285 		uint32_t old = pclass;
1286 		// bit 0 specifies if the primary channel is in compatibility or native-pci mode
1287 		// bit 2 specifies if the secondary channel is in compatibility or native-pci mode
1288 		pclass = (pclass & 0xfffffffa) | ((data >> 8) & 5);
1289 		if (old ^ pclass)
1290 		{
1291 			if (~pclass & 1) // compatibility mode
1292 			{
1293 				bank_infos[0].flags |= M_DISABLED;
1294 				bank_infos[1].flags |= M_DISABLED;
1295 			}
1296 			else
1297 			{
1298 				bank_infos[0].flags &= ~M_DISABLED;
1299 				bank_infos[1].flags &= ~M_DISABLED;
1300 			}
1301 			if (~pclass & 4) // compatibility mode
1302 			{
1303 				bank_infos[2].flags |= M_DISABLED;
1304 				bank_infos[3].flags |= M_DISABLED;
1305 			}
1306 			else
1307 			{
1308 				bank_infos[2].flags &= ~M_DISABLED;
1309 				bank_infos[3].flags &= ~M_DISABLED;
1310 			}
1311 			remap_cb();
1312 		}
1313 	}
1314 }
1315 
pri_read_cs1_r()1316 uint8_t mcpx_ide_device::pri_read_cs1_r()
1317 {
1318 	return m_pri->read_cs1(1, 0xff0000) >> 16;
1319 }
1320 
pri_write_cs1_w(uint8_t data)1321 void mcpx_ide_device::pri_write_cs1_w(uint8_t data)
1322 {
1323 	m_pri->write_cs1(1, data << 16, 0xff0000);
1324 }
1325 
sec_read_cs1_r()1326 uint8_t mcpx_ide_device::sec_read_cs1_r()
1327 {
1328 	return m_sec->read_cs1(1, 0xff0000) >> 16;
1329 }
1330 
sec_write_cs1_w(uint8_t data)1331 void mcpx_ide_device::sec_write_cs1_w(uint8_t data)
1332 {
1333 	m_sec->write_cs1(1, data << 16, 0xff0000);
1334 }
1335 
WRITE_LINE_MEMBER(mcpx_ide_device::ide_pri_interrupt)1336 WRITE_LINE_MEMBER(mcpx_ide_device::ide_pri_interrupt)
1337 {
1338 	m_pri_interrupt_handler(state);
1339 }
1340 
WRITE_LINE_MEMBER(mcpx_ide_device::ide_sec_interrupt)1341 WRITE_LINE_MEMBER(mcpx_ide_device::ide_sec_interrupt)
1342 {
1343 	m_sec_interrupt_handler(state);
1344 }
1345 
1346 /*
1347  * AGP Bridge
1348  */
1349 
1350 DEFINE_DEVICE_TYPE(NV2A_AGP, nv2a_agp_device, "nv2a_agp", "NV2A AGP Host to PCI Bridge")
1351 
config_map(address_map & map)1352 void nv2a_agp_device::config_map(address_map& map)
1353 {
1354 	agp_bridge_device::config_map(map);
1355 	map(0x40, 0xff).rw(FUNC(nv2a_agp_device::unknown_r), FUNC(nv2a_agp_device::unknown_w));
1356 }
1357 
nv2a_agp_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1358 nv2a_agp_device::nv2a_agp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
1359 	: agp_bridge_device(mconfig, NV2A_AGP, tag, owner, clock)
1360 {
1361 }
1362 
device_start()1363 void nv2a_agp_device::device_start()
1364 {
1365 	agp_bridge_device::device_start();
1366 }
1367 
device_reset()1368 void nv2a_agp_device::device_reset()
1369 {
1370 	agp_bridge_device::device_reset();
1371 }
1372 
unknown_r(offs_t offset,uint32_t mem_mask)1373 uint32_t nv2a_agp_device::unknown_r(offs_t offset, uint32_t mem_mask)
1374 {
1375 	// 4c 8 or 32
1376 	// 44 8
1377 	// 45 8
1378 	// 46 8
1379 	// 47 8
1380 	//printf("R %08X %08X\n",0x40+offset*4,mem_mask);
1381 	if (offset == 3)
1382 		return 1;
1383 	return 0;
1384 }
1385 
unknown_w(offs_t offset,uint32_t data,uint32_t mem_mask)1386 void nv2a_agp_device::unknown_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1387 {
1388 	//printf("W %08X %08X %08X\n", 0x40+offset*4, mem_mask, data);
1389 }
1390 
1391 /*
1392  * NV2A 3D Accelerator
1393  */
1394 
1395 DEFINE_DEVICE_TYPE(NV2A_GPU, nv2a_gpu_device, "nv2a_gpu", "NVIDIA NV2A GPU")
1396 
nv2a_mmio(address_map & map)1397 void nv2a_gpu_device::nv2a_mmio(address_map &map)
1398 {
1399 	map(0x00000000, 0x00ffffff).ram().rw(FUNC(nv2a_gpu_device::geforce_r), FUNC(nv2a_gpu_device::geforce_w));
1400 }
1401 
nv2a_mirror(address_map & map)1402 void nv2a_gpu_device::nv2a_mirror(address_map &map)
1403 {
1404 	map(0x00000000, 0x07ffffff).ram().rw(FUNC(nv2a_gpu_device::nv2a_mirror_r), FUNC(nv2a_gpu_device::nv2a_mirror_w));
1405 }
1406 
nv2a_gpu_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1407 nv2a_gpu_device::nv2a_gpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
1408 	agp_device(mconfig, NV2A_GPU, tag, owner, clock),
1409 	nvidia_nv2a(nullptr),
1410 	cpu(*this, finder_base::DUMMY_TAG),
1411 	m_interrupt_handler(*this),
1412 	m_program(nullptr)
1413 {
1414 	set_ids(0x10de02a0, 0, 0, 0);
1415 }
1416 
device_start()1417 void nv2a_gpu_device::device_start()
1418 {
1419 	agp_device::device_start();
1420 	m_interrupt_handler.resolve_safe();
1421 	add_map(0x01000000, M_MEM, FUNC(nv2a_gpu_device::nv2a_mmio));
1422 	bank_infos[0].adr = 0xfd000000;
1423 	add_map(0x08000000, M_MEM, FUNC(nv2a_gpu_device::nv2a_mirror));
1424 	bank_infos[1].adr = 0xf0000000;
1425 	m_program = &cpu->space(AS_PROGRAM); // FIXME: isn't there a proper way to map stuff or do DMA via the PCI device interface?
1426 	nvidia_nv2a = new nv2a_renderer(machine());
1427 	nvidia_nv2a->set_irq_callbaclk(
1428 		[&](int state)
1429 		{
1430 			m_interrupt_handler(state);
1431 		}
1432 	);
1433 	nvidia_nv2a->start(m_program);
1434 	nvidia_nv2a->savestate_items();
1435 }
1436 
device_reset()1437 void nv2a_gpu_device::device_reset()
1438 {
1439 	agp_device::device_reset();
1440 	nvidia_nv2a->set_ram_base(m_program->get_read_ptr(0));
1441 }
1442 
geforce_r(offs_t offset,uint32_t mem_mask)1443 uint32_t nv2a_gpu_device::geforce_r(offs_t offset, uint32_t mem_mask)
1444 {
1445 	return nvidia_nv2a->geforce_r(offset, mem_mask);
1446 }
1447 
geforce_w(address_space & space,offs_t offset,uint32_t data,uint32_t mem_mask)1448 void nv2a_gpu_device::geforce_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask)
1449 {
1450 	nvidia_nv2a->geforce_w(space, offset, data, mem_mask);
1451 }
1452 
nv2a_mirror_r(offs_t offset,uint32_t mem_mask)1453 uint32_t nv2a_gpu_device::nv2a_mirror_r(offs_t offset, uint32_t mem_mask)
1454 {
1455 	return m_program->read_dword(offset << 2);
1456 }
1457 
nv2a_mirror_w(offs_t offset,uint32_t data,uint32_t mem_mask)1458 void nv2a_gpu_device::nv2a_mirror_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1459 {
1460 	m_program->write_dword(offset << 2, data, mem_mask);
1461 }
1462