~ubuntu-branches/ubuntu/trusty/vice/trusty

« back to all changes in this revision

Viewing changes to src/arch/msdos/catweaselmkiii.c

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2013-07-28 20:38:23 UTC
  • mfrom: (1.2.5)
  • mto: This revision was merged to the branch mainline in revision 27.
  • Revision ID: package-import@ubuntu.com-20130728203823-w495rps5wuykespp
Tags: upstream-2.4.dfsg
ImportĀ upstreamĀ versionĀ 2.4.dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * catweaselmkiii.c
 
3
 *
 
4
 * Written by
 
5
 *  Marco van den Heuvel <blackystardust68@yahoo.com>
 
6
 *
 
7
 * Based on code by
 
8
 *  Timothy Mann
 
9
 *
 
10
 * This file is part of VICE, the Versatile Commodore Emulator.
 
11
 * See README for copyright notice.
 
12
 *
 
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.
 
17
 *
 
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.
 
22
 *
 
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
 
26
 *  02111-1307  USA.
 
27
 *
 
28
 */
 
29
 
 
30
#include <stdio.h>
 
31
#include <dpmi.h>
 
32
#include <string.h>
 
33
 
 
34
#include "log.h"
 
35
#include "types.h"
 
36
 
 
37
typedef unsigned short uint16;
 
38
typedef unsigned long uint32;
 
39
 
 
40
static int sid_NTSC = 0; // TRUE for 60Hz oscillator, FALSE for 50
 
41
 
 
42
static int base;
 
43
 
 
44
/* buffer containing current register state of SIDs */
 
45
static BYTE sidbuf[0x20];
 
46
 
 
47
static int sidfh = -1;
 
48
 
 
49
#define CW_SID_DAT 0xd8
 
50
#define CW_SID_CMD 0xdc
 
51
 
 
52
static int pci_install_check(void)
 
53
{
 
54
    __dpmi_regs r;
 
55
 
 
56
    memset(&r, 0, sizeof(r));
 
57
 
 
58
    r.x.ax = 0xb101;
 
59
    r.d.edi = 0x0;
 
60
 
 
61
    if (__dpmi_int(0x1a, &r) != 0) {
 
62
        return -1;
 
63
    }
 
64
        
 
65
    if (r.h.ah != 0 || r.d.edx != 0x20494350) {
 
66
        return -1;
 
67
    }
 
68
 
 
69
    return 0;
 
70
}
 
71
 
 
72
 
 
73
static int pci_find(int vendorID, int deviceID, int index, int *bus, int *device, int *func)
 
74
{
 
75
    __dpmi_regs r;
 
76
 
 
77
    memset(&r, 0, sizeof(r));
 
78
 
 
79
    r.x.ax = 0xb102;
 
80
    r.x.cx = deviceID;
 
81
    r.x.dx = vendorID;
 
82
    r.x.si = index;
 
83
 
 
84
    if (__dpmi_int(0x1a, &r) != 0) {
 
85
        return -1;
 
86
    }
 
87
 
 
88
    if (r.h.ah == 0) {
 
89
        *bus = r.h.bh;
 
90
        *device = (r.h.bl >> 3) & 0x1f;
 
91
        *func = r.h.bl & 0x03;
 
92
    }
 
93
 
 
94
    return r.h.ah;
 
95
}
 
96
 
 
97
 
 
98
static int pci_read_config_dword(int bus, int device, int func, int reg, uint32 *value)
 
99
{
 
100
    __dpmi_regs r;
 
101
 
 
102
    memset(&r, 0, sizeof(r));
 
103
 
 
104
    r.x.ax = 0xb10a;
 
105
    r.h.bh = bus;
 
106
    r.h.bl = (device << 3) + func;
 
107
    r.x.di = reg;
 
108
 
 
109
    if (__dpmi_int(0x1a, &r) != 0) {
 
110
        return -1;
 
111
    }
 
112
        
 
113
    if (r.h.ah == 0) {
 
114
        *value = r.d.ecx;
 
115
    }
 
116
 
 
117
    return r.h.ah;
 
118
}
 
119
 
 
120
 
 
121
static int pci_find_catweasel(int index)
 
122
{
 
123
    int i = 0, j = 0, res;
 
124
    int bus, device, func;
 
125
    uint32 subsysID, baseAddr;
 
126
 
 
127
    if (pci_install_check() != 0) {
 
128
        return -1;
 
129
    }
 
130
 
 
131
    while (i <= index) {
 
132
 
 
133
        /* Find the next card that uses the Tiger Jet Networks Tiger320 PCI chip */
 
134
        res = pci_find(0xe159, 0x0001, j++, &bus, &device, &func);
 
135
        if (res != 0) {
 
136
            return -1;
 
137
        }
 
138
 
 
139
        /* Read the subsystem vendor ID + subsystem ID */
 
140
        res = pci_read_config_dword(bus, device, func, 0x2c, &subsysID);
 
141
        if (res != 0) {
 
142
            continue;
 
143
        }
 
144
 
 
145
        /* Check if they match the Catweasel */
 
146
        switch (subsysID) {
 
147
            case 0x00021212:    /* Catweasel MK3 */
 
148
            case 0x00031212:    /* Catweasel MK3 alternate */
 
149
            case 0x00025213:    /* Catweasel MK4 */
 
150
            case 0x00035213:    /* Catweasel MK4 alternate */
 
151
                break;
 
152
            default:
 
153
                continue;
 
154
        }
 
155
        i++;
 
156
    }
 
157
 
 
158
    for (i = 0x10; i <= 0x24; i += 4) {
 
159
 
 
160
        /* Read a base address */
 
161
        res = pci_read_config_dword(bus, device, func, i, &baseAddr);
 
162
        if (res != 0) {
 
163
            return -1;
 
164
        }
 
165
 
 
166
        /* Check for I/O space */
 
167
        if (baseAddr & 1) {
 
168
            return baseAddr & ~3;
 
169
        }
 
170
    }
 
171
 
 
172
    return -1;
 
173
}
 
174
 
 
175
static unsigned char read_sid(unsigned char reg)
 
176
{
 
177
    unsigned char cmd;
 
178
 
 
179
    cmd = (reg & 0x1f) | 0x20;  // Read command & address
 
180
    if (sid_NTSC) {
 
181
        cmd |= 0x40;  // Make sure its correct frequency
 
182
    }
 
183
 
 
184
    // Write command to the SID
 
185
    outportb(base + CW_SID_CMD, cmd);
 
186
 
 
187
    // Waste 1ms
 
188
    inportb(base + CW_SID_DAT);
 
189
    inportb(base + CW_SID_DAT);
 
190
 
 
191
    return inportb(base + CW_SID_DAT);
 
192
}
 
193
 
 
194
static void write_sid(unsigned char reg, unsigned char data)
 
195
{
 
196
    unsigned char cmd;
 
197
 
 
198
    cmd = reg & 0x1f;
 
199
    if (sid_NTSC) {
 
200
        cmd |= 0x40;  // Make sure its correct frequency
 
201
    }
 
202
 
 
203
    // Write data to the SID
 
204
    outportb(base + CW_SID_DAT, data);
 
205
    outportb(base + CW_SID_CMD, cmd);
 
206
 
 
207
    // Waste 1ms
 
208
    inportb(base + CW_SID_DAT);
 
209
    inportb(base + CW_SID_DAT);
 
210
}
 
211
 
 
212
int catweaselmkiii_open(void)
 
213
{
 
214
    int i;
 
215
 
 
216
    base = pci_find_catweasel(0);
 
217
 
 
218
    if (base == -1) {
 
219
        log_message(LOG_DEFAULT, "Unable to find a Catweasel Mk3 PCI card\n");
 
220
        return -1;
 
221
    }
 
222
 
 
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);                                      
 
231
 
 
232
    /* mute all sids */
 
233
    memset(sidbuf, 0, sizeof(sidbuf));
 
234
    for (i = 0; i < sizeof(sidbuf); i++) {
 
235
        write_sid(i, 0);
 
236
    }
 
237
 
 
238
    log_message(LOG_DEFAULT, "CatWeasel MK3 PCI SID: opened");
 
239
 
 
240
    sidfh = 1; /* ok */
 
241
 
 
242
    return 0;
 
243
}
 
244
 
 
245
int catweaselmkiii_close(void)
 
246
{
 
247
    unsigned int i;
 
248
 
 
249
    /* mute all sids */
 
250
    memset(sidbuf, 0, sizeof(sidbuf));
 
251
    for (i = 0; i < sizeof(sidbuf); i++) {
 
252
        write_sid(i, 0);
 
253
    }
 
254
 
 
255
    log_message(LOG_DEFAULT, "CatWeasel MK3 PCI SID: closed");
 
256
 
 
257
    return 0;
 
258
}
 
259
 
 
260
/* read value from SIDs */
 
261
int catweaselmkiii_read(WORD addr, int chipno)
 
262
{
 
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);
 
269
        } else {
 
270
            addr += chipno * 0x20;
 
271
        }
 
272
 
 
273
        /* take value from sidbuf[] */
 
274
        return sidbuf[addr];
 
275
    }
 
276
 
 
277
    return 0;
 
278
}
 
279
 
 
280
/* write value into SID */
 
281
void catweaselmkiii_store(WORD addr, BYTE val, int chipno)
 
282
{
 
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[] */
 
288
        sidbuf[addr] = val;
 
289
        /* if the device is opened, write to device */
 
290
        if (sidfh >= 0) {
 
291
            write_sid(addr, val);
 
292
        }
 
293
    }
 
294
}
 
295
 
 
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)
 
299
{
 
300
    sid_NTSC = (cycles_per_sec <= 1000000) ? 0 : 1;
 
301
}