1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
// license: BSD-3-Clause
// copyright-holders: Angelo Salese
/**************************************************************************************************
SiS 7018 Audio device (AC'97 compliant)
TODO:
- Derive from Trident 4DWave-DX/-NX (very similar interface);
- shutms11 uses an AD1881 as AC'97 engine;
**************************************************************************************************/
#include "emu.h"
#include "sis7018_audio.h"
#define LOG_IO (1U << 1) // log PCI register accesses
#define LOG_TODO (1U << 2) // log unimplemented registers
#define LOG_MAP (1U << 3) // log full remaps
#define LOG_PMC (1U << 4) // log PMC access
#define VERBOSE (LOG_GENERAL | LOG_IO | LOG_TODO | LOG_MAP | LOG_PMC)
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
#define LOGIO(...) LOGMASKED(LOG_IO, __VA_ARGS__)
#define LOGMAP(...) LOGMASKED(LOG_MAP, __VA_ARGS__)
#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
#define LOGPMC(...) LOGMASKED(LOG_PMC, __VA_ARGS__)
DEFINE_DEVICE_TYPE(SIS7018_AUDIO, sis7018_audio_device, "sis7018_audio", "SiS 7018 Audio AC97")
sis7018_audio_device::sis7018_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: pci_device(mconfig, SIS7018_AUDIO, tag, owner, clock)
, m_joy(*this, "pc_joy")
{
// 0x040100 - Multimedia device, audio device (no specific vendor interface)
// 0x01 - Rev 1
set_ids(0x10397018, 0x01, 0x040100, 0x00);
}
void sis7018_audio_device::device_add_mconfig(machine_config &config)
{
PC_JOY(config, m_joy);
// ...
}
// NOTE: prefer using Trident naming if a register is there too.
void sis7018_audio_device::config_map(address_map &map)
{
pci_device::config_map(map);
map(0x48, 0xe3).rw(FUNC(sis7018_audio_device::unmap_log_r), FUNC(sis7018_audio_device::unmap_log_w));
map(0x44, 0x44).lrw8(
NAME([this] (offs_t offset) {
return m_legacy_io_base;
}),
NAME([this] (offs_t offset, u8 data) {
LOGIO("PCI $44: Legacy I/O base %02x\n", data);
m_legacy_io_base = data;
remap_cb();
})
);
// 0x45 Legacy DMA Decoding
// 0x46 PM_CFG Power Management Config (Legacy Control on Trident)
// 0x47 Inactivity Timer Expiration Control
// 0x48-0x49 Int Acknowledge Snoop
// PMC capability identifier
map(0xdc, 0xdf).r(FUNC(sis7018_audio_device::pmc_id_r));
// map(0xe0, 0xe3).r(FUNC(sis7018_audio_device::pmc_status_r), FUNC(sis7018_audio_device::pmc_control_w));
}
u8 sis7018_audio_device::capptr_r()
{
LOGIO("AUDIO Read capptr_r [$34]\n");
return 0xdc;
}
// TODO: move to specific interface
u32 sis7018_audio_device::pmc_id_r()
{
LOGPMC("Read PMC ID [$dc]\n");
// bits 31-16 PPMI v1.0, D1 / D2 supported, no PCI clock for PME#
// bits 15-8 0x00 no NEXT_PTR (NULL terminates here)
// bits 7-0 PM_CAP_ID (0x01 for PMC)
return 0xe6110001;
}
void sis7018_audio_device::memory_map(address_map &map)
{
}
void sis7018_audio_device::io_map(address_map &map)
{
}
void sis7018_audio_device::device_start()
{
pci_device::device_start();
add_map(256, M_IO, FUNC(sis7018_audio_device::io_map));
// not explicitly stated, assume 4096 size from the MEM decoding
add_map(4096, M_MEM, FUNC(sis7018_audio_device::memory_map));
// min_gnt = 500 nsec, max_lat = 6 usec (way more than Trident)
minimum_grant = 0x02;
maximum_latency = 0x18;
}
void sis7018_audio_device::device_reset()
{
pci_device::device_reset();
command = 0x0000;
command_mask = 7;
// NOTE: claims fast back-to-back capable vs. Trident
status = 0x0290;
// INTA#
intr_pin = 1;
intr_line = 0x05;
// TODO: can be written to with $46=1
subsystem_id = 0x10397018;
m_legacy_io_base = 0xe2; // 0xf0 on Trident
remap_cb();
}
void sis7018_audio_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)
{
// if(BIT(m_legacy_io_base, 7))
// const u16 mpu401base_io_addr = 0x300 | (BIT(m_legacy_io_base, 6) ? 0x00 : 0x30);
if (BIT(m_legacy_io_base, 5))
{
const u16 gamebase_io_addr = 0x200 | (BIT(m_legacy_io_base, 4) << 3);
io_space->install_device(gamebase_io_addr, gamebase_io_addr | 0x7, *this, &sis7018_audio_device::gameport_map);
}
// if(BIT(m_legacy_io_base, 3))
// const u16 adlibbase_io_addr = 0x388 | (BIT(m_legacy_io_base, 2) << 2);
// if(BIT(m_legacy_io_base, 1))
// const u16 sbbase_io_addr = 0x200 | (BIT(m_legacy_io_base, 0) ? 0x20 : 0x40);
}
// 200h / 208h
void sis7018_audio_device::gameport_map(address_map &map)
{
map(0x00, 0x07).rw(m_joy, FUNC(pc_joy_device::joy_port_r), FUNC(pc_joy_device::joy_port_w));
}
/*
* Debugging
*/
u8 sis7018_audio_device::unmap_log_r(offs_t offset)
{
LOGTODO("AUDIO Unemulated [%02x] R\n", offset + 0x48);
return 0;
}
void sis7018_audio_device::unmap_log_w(offs_t offset, u8 data)
{
LOGTODO("AUDIO Unemulated [%02x] %02x W\n", offset + 0x48, data);
}
|