5
* Marco van den Heuvel <blackystardust68@yahoo.com>
10
* This file is part of VICE, the Versatile Commodore Emulator.
11
* See README for copyright notice.
13
* This program is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License as published by
15
* the Free Software Foundation; either version 2 of the License, or
16
* (at your option) any later version.
18
* This program is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
23
* You should have received a copy of the GNU General Public License
24
* along with this program; if not, write to the Free Software
25
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
37
typedef unsigned short uint16;
38
typedef unsigned long uint32;
40
static int sid_NTSC = 0; // TRUE for 60Hz oscillator, FALSE for 50
44
/* buffer containing current register state of SIDs */
45
static BYTE sidbuf[0x20];
47
static int sidfh = -1;
49
#define CW_SID_DAT 0xd8
50
#define CW_SID_CMD 0xdc
52
static int pci_install_check(void)
56
memset(&r, 0, sizeof(r));
61
if (__dpmi_int(0x1a, &r) != 0) {
65
if (r.h.ah != 0 || r.d.edx != 0x20494350) {
73
static int pci_find(int vendorID, int deviceID, int index, int *bus, int *device, int *func)
77
memset(&r, 0, sizeof(r));
84
if (__dpmi_int(0x1a, &r) != 0) {
90
*device = (r.h.bl >> 3) & 0x1f;
91
*func = r.h.bl & 0x03;
98
static int pci_read_config_dword(int bus, int device, int func, int reg, uint32 *value)
102
memset(&r, 0, sizeof(r));
106
r.h.bl = (device << 3) + func;
109
if (__dpmi_int(0x1a, &r) != 0) {
121
static int pci_find_catweasel(int index)
123
int i = 0, j = 0, res;
124
int bus, device, func;
125
uint32 subsysID, baseAddr;
127
if (pci_install_check() != 0) {
133
/* Find the next card that uses the Tiger Jet Networks Tiger320 PCI chip */
134
res = pci_find(0xe159, 0x0001, j++, &bus, &device, &func);
139
/* Read the subsystem vendor ID + subsystem ID */
140
res = pci_read_config_dword(bus, device, func, 0x2c, &subsysID);
145
/* Check if they match the Catweasel */
147
case 0x00021212: /* Catweasel MK3 */
148
case 0x00031212: /* Catweasel MK3 alternate */
149
case 0x00025213: /* Catweasel MK4 */
150
case 0x00035213: /* Catweasel MK4 alternate */
158
for (i = 0x10; i <= 0x24; i += 4) {
160
/* Read a base address */
161
res = pci_read_config_dword(bus, device, func, i, &baseAddr);
166
/* Check for I/O space */
168
return baseAddr & ~3;
175
static unsigned char read_sid(unsigned char reg)
179
cmd = (reg & 0x1f) | 0x20; // Read command & address
181
cmd |= 0x40; // Make sure its correct frequency
184
// Write command to the SID
185
outportb(base + CW_SID_CMD, cmd);
188
inportb(base + CW_SID_DAT);
189
inportb(base + CW_SID_DAT);
191
return inportb(base + CW_SID_DAT);
194
static void write_sid(unsigned char reg, unsigned char data)
200
cmd |= 0x40; // Make sure its correct frequency
203
// Write data to the SID
204
outportb(base + CW_SID_DAT, data);
205
outportb(base + CW_SID_CMD, cmd);
208
inportb(base + CW_SID_DAT);
209
inportb(base + CW_SID_DAT);
212
int catweaselmkiii_open(void)
216
base = pci_find_catweasel(0);
219
log_message(LOG_DEFAULT, "Unable to find a Catweasel Mk3 PCI card\n");
223
// Reset the catweasel PCI interface (as per the CW programming docs)
224
outportb(base + 0x00, 0xf1);
225
outportb(base + 0x01, 0x00);
226
outportb(base + 0x02, 0x00);
227
outportb(base + 0x04, 0x00);
228
outportb(base + 0x05, 0x00);
229
outportb(base + 0x29, 0x00);
230
outportb(base + 0x2b, 0x00);
233
memset(sidbuf, 0, sizeof(sidbuf));
234
for (i = 0; i < sizeof(sidbuf); i++) {
238
log_message(LOG_DEFAULT, "CatWeasel MK3 PCI SID: opened");
245
int catweaselmkiii_close(void)
250
memset(sidbuf, 0, sizeof(sidbuf));
251
for (i = 0; i < sizeof(sidbuf); i++) {
255
log_message(LOG_DEFAULT, "CatWeasel MK3 PCI SID: closed");
260
/* read value from SIDs */
261
int catweaselmkiii_read(WORD addr, int chipno)
263
/* check if chipno and addr is valid */
264
if (chipno < 1 && addr < 0x20) {
265
/* if addr is from read-only register, perform a read read */
266
if (addr >= 0x19 && addr <= 0x1C && sidfh >= 0) {
267
addr += chipno * 0x20;
268
sidbuf[addr] = read_sid(addr);
270
addr += chipno * 0x20;
273
/* take value from sidbuf[] */
280
/* write value into SID */
281
void catweaselmkiii_store(WORD addr, BYTE val, int chipno)
283
/* check if chipno and addr is valid */
284
if (chipno < 1 && addr <= 0x18) {
285
/* correct addr, so it becomes an index into sidbuf[] and the unix device */
286
addr += chipno * 0x20;
287
/* write into sidbuf[] */
289
/* if the device is opened, write to device */
291
write_sid(addr, val);
296
/* set current main clock frequency, which gives us the possibilty to
297
choose between pal and ntsc frequencies */
298
void catweaselmkiii_set_machine_parameter(long cycles_per_sec)
300
sid_NTSC = (cycles_per_sec <= 1000000) ? 0 : 1;