Statistics
| Branch: | Revision:

root / hw / sb16.c @ 546fa6ab

History | View | Annotate | Download (31.7 kB)

1 27503323 bellard
/*
2 27503323 bellard
 * QEMU Soundblaster 16 emulation
3 27503323 bellard
 * 
4 85571bc7 bellard
 * Copyright (c) 2003-2004 Vassili Karpov (malc)
5 27503323 bellard
 * 
6 27503323 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 27503323 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 27503323 bellard
 * in the Software without restriction, including without limitation the rights
9 27503323 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 27503323 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 27503323 bellard
 * furnished to do so, subject to the following conditions:
12 27503323 bellard
 *
13 27503323 bellard
 * The above copyright notice and this permission notice shall be included in
14 27503323 bellard
 * all copies or substantial portions of the Software.
15 27503323 bellard
 *
16 27503323 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 27503323 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 27503323 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 27503323 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 27503323 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 27503323 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 27503323 bellard
 * THE SOFTWARE.
23 27503323 bellard
 */
24 27503323 bellard
#include "vl.h"
25 27503323 bellard
26 85571bc7 bellard
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
27 d75d9f6b bellard
28 fb065187 bellard
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
29 15b61470 bellard
30 15b61470 bellard
/* #define DEBUG */
31 15b61470 bellard
/* #define DEBUG_SB16_MOST */
32 15b61470 bellard
33 fb065187 bellard
#ifdef DEBUG
34 fb065187 bellard
#define ldebug(...) dolog (__VA_ARGS__)
35 fb065187 bellard
#else
36 fb065187 bellard
#define ldebug(...)
37 fb065187 bellard
#endif
38 fb065187 bellard
39 85571bc7 bellard
#define IO_READ_PROTO(name)                             \
40 7d977de7 bellard
    uint32_t name (void *opaque, uint32_t nport)
41 85571bc7 bellard
#define IO_WRITE_PROTO(name)                                    \
42 7d977de7 bellard
    void name (void *opaque, uint32_t nport, uint32_t val)
43 27503323 bellard
44 85571bc7 bellard
static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
45 d329a6fb bellard
46 27503323 bellard
static struct {
47 27503323 bellard
    int ver_lo;
48 27503323 bellard
    int ver_hi;
49 27503323 bellard
    int irq;
50 27503323 bellard
    int dma;
51 27503323 bellard
    int hdma;
52 27503323 bellard
    int port;
53 85571bc7 bellard
} conf = {5, 4, 5, 1, 5, 0x220};
54 27503323 bellard
55 5e2a6443 bellard
typedef struct SB16State {
56 85571bc7 bellard
    int irq;
57 85571bc7 bellard
    int dma;
58 85571bc7 bellard
    int hdma;
59 85571bc7 bellard
    int port;
60 85571bc7 bellard
    int ver;
61 85571bc7 bellard
62 27503323 bellard
    int in_index;
63 27503323 bellard
    int out_data_len;
64 27503323 bellard
    int fmt_stereo;
65 27503323 bellard
    int fmt_signed;
66 27503323 bellard
    int fmt_bits;
67 85571bc7 bellard
    audfmt_e fmt;
68 27503323 bellard
    int dma_auto;
69 85571bc7 bellard
    int block_size;
70 27503323 bellard
    int fifo;
71 27503323 bellard
    int freq;
72 27503323 bellard
    int time_const;
73 27503323 bellard
    int speaker;
74 27503323 bellard
    int needed_bytes;
75 27503323 bellard
    int cmd;
76 27503323 bellard
    int use_hdma;
77 85571bc7 bellard
    int highspeed;
78 85571bc7 bellard
    int can_write;
79 27503323 bellard
80 27503323 bellard
    int v2x6;
81 27503323 bellard
82 85571bc7 bellard
    uint8_t csp_param;
83 85571bc7 bellard
    uint8_t csp_value;
84 85571bc7 bellard
    uint8_t csp_mode;
85 85571bc7 bellard
    uint8_t csp_regs[256];
86 85571bc7 bellard
    uint8_t csp_index;
87 85571bc7 bellard
    uint8_t csp_reg83[4];
88 85571bc7 bellard
    int csp_reg83r;
89 85571bc7 bellard
    int csp_reg83w;
90 85571bc7 bellard
91 d75d9f6b bellard
    uint8_t in2_data[10];
92 85571bc7 bellard
    uint8_t out_data[50];
93 85571bc7 bellard
    uint8_t test_reg;
94 85571bc7 bellard
    uint8_t last_read_byte;
95 85571bc7 bellard
    int nzero;
96 27503323 bellard
97 27503323 bellard
    int left_till_irq;
98 27503323 bellard
99 85571bc7 bellard
    int dma_running;
100 85571bc7 bellard
    int bytes_per_second;
101 85571bc7 bellard
    int align;
102 85571bc7 bellard
    SWVoice *voice;
103 85571bc7 bellard
104 85571bc7 bellard
    QEMUTimer *ts, *aux_ts;
105 5e2a6443 bellard
    /* mixer state */
106 5e2a6443 bellard
    int mixer_nreg;
107 202a456a bellard
    uint8_t mixer_regs[256];
108 5e2a6443 bellard
} SB16State;
109 27503323 bellard
110 5e2a6443 bellard
/* XXX: suppress that and use a context */
111 5e2a6443 bellard
static struct SB16State dsp;
112 27503323 bellard
113 85571bc7 bellard
static int magic_of_irq (int irq)
114 85571bc7 bellard
{
115 85571bc7 bellard
    switch (irq) {
116 85571bc7 bellard
    case 5:
117 85571bc7 bellard
        return 2;
118 85571bc7 bellard
    case 7:
119 85571bc7 bellard
        return 4;
120 85571bc7 bellard
    case 9:
121 85571bc7 bellard
        return 1;
122 85571bc7 bellard
    case 10:
123 85571bc7 bellard
        return 8;
124 85571bc7 bellard
    default:
125 85571bc7 bellard
        dolog ("bad irq %d\n", irq);
126 85571bc7 bellard
        return 2;
127 85571bc7 bellard
    }
128 85571bc7 bellard
}
129 85571bc7 bellard
130 85571bc7 bellard
static int irq_of_magic (int magic)
131 85571bc7 bellard
{
132 85571bc7 bellard
    switch (magic) {
133 85571bc7 bellard
    case 1:
134 85571bc7 bellard
        return 9;
135 85571bc7 bellard
    case 2:
136 85571bc7 bellard
        return 5;
137 85571bc7 bellard
    case 4:
138 85571bc7 bellard
        return 7;
139 85571bc7 bellard
    case 8:
140 85571bc7 bellard
        return 10;
141 85571bc7 bellard
    default:
142 85571bc7 bellard
        dolog ("bad irq magic %d\n", magic);
143 85571bc7 bellard
        return -1;
144 85571bc7 bellard
    }
145 85571bc7 bellard
}
146 85571bc7 bellard
147 85571bc7 bellard
#if 0
148 5e2a6443 bellard
static void log_dsp (SB16State *dsp)
149 5e2a6443 bellard
{
150 85571bc7 bellard
    ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
151 85571bc7 bellard
            dsp->fmt_stereo ? "Stereo" : "Mono",
152 85571bc7 bellard
            dsp->fmt_signed ? "Signed" : "Unsigned",
153 85571bc7 bellard
            dsp->fmt_bits,
154 85571bc7 bellard
            dsp->dma_auto ? "Auto" : "Single",
155 85571bc7 bellard
            dsp->block_size,
156 85571bc7 bellard
            dsp->freq,
157 85571bc7 bellard
            dsp->time_const,
158 85571bc7 bellard
            dsp->speaker);
159 85571bc7 bellard
}
160 85571bc7 bellard
#endif
161 85571bc7 bellard
162 85571bc7 bellard
static void speaker (SB16State *s, int on)
163 85571bc7 bellard
{
164 85571bc7 bellard
    s->speaker = on;
165 85571bc7 bellard
    /* AUD_enable (s->voice, on); */
166 27503323 bellard
}
167 27503323 bellard
168 85571bc7 bellard
static void control (SB16State *s, int hold)
169 27503323 bellard
{
170 85571bc7 bellard
    int dma = s->use_hdma ? s->hdma : s->dma;
171 85571bc7 bellard
    s->dma_running = hold;
172 85571bc7 bellard
173 85571bc7 bellard
    ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
174 85571bc7 bellard
175 27503323 bellard
    if (hold) {
176 85571bc7 bellard
        DMA_hold_DREQ (dma);
177 85571bc7 bellard
        AUD_enable (s->voice, 1);
178 27503323 bellard
    }
179 27503323 bellard
    else {
180 85571bc7 bellard
        DMA_release_DREQ (dma);
181 85571bc7 bellard
        AUD_enable (s->voice, 0);
182 27503323 bellard
    }
183 27503323 bellard
}
184 27503323 bellard
185 85571bc7 bellard
static void aux_timer (void *opaque)
186 27503323 bellard
{
187 85571bc7 bellard
    SB16State *s = opaque;
188 85571bc7 bellard
    s->can_write = 1;
189 85571bc7 bellard
    pic_set_irq (s->irq, 1);
190 85571bc7 bellard
}
191 85571bc7 bellard
192 85571bc7 bellard
#define DMA8_AUTO 1
193 85571bc7 bellard
#define DMA8_HIGH 2
194 85571bc7 bellard
195 85571bc7 bellard
static void dma_cmd8 (SB16State *s, int mask, int dma_len)
196 85571bc7 bellard
{
197 85571bc7 bellard
    s->fmt = AUD_FMT_U8;
198 85571bc7 bellard
    s->use_hdma = 0;
199 85571bc7 bellard
    s->fmt_bits = 8;
200 85571bc7 bellard
    s->fmt_signed = 0;
201 85571bc7 bellard
    s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
202 85571bc7 bellard
    if (-1 == s->time_const) {
203 85571bc7 bellard
        s->freq = 11025;
204 85571bc7 bellard
    }
205 85571bc7 bellard
    else {
206 85571bc7 bellard
        int tmp = (256 - s->time_const);
207 85571bc7 bellard
        s->freq = (1000000 + (tmp / 2)) / tmp;
208 85571bc7 bellard
    }
209 85571bc7 bellard
210 15b61470 bellard
    if (dma_len != -1)
211 15b61470 bellard
        s->block_size = dma_len << s->fmt_stereo;
212 15b61470 bellard
    else {
213 15b61470 bellard
        /* This is apparently the only way to make both Act1/PL
214 15b61470 bellard
           and SecondReality/FC work
215 15b61470 bellard

216 15b61470 bellard
           Act1 sets block size via command 0x48 and it's an odd number
217 15b61470 bellard
           SR does the same with even number
218 15b61470 bellard
           Both use stereo, and Creatives own documentation states that
219 15b61470 bellard
           0x48 sets block size in bytes less one.. go figure */
220 15b61470 bellard
        s->block_size &= ~s->fmt_stereo;
221 15b61470 bellard
    }
222 85571bc7 bellard
223 85571bc7 bellard
    s->freq >>= s->fmt_stereo;
224 85571bc7 bellard
    s->left_till_irq = s->block_size;
225 85571bc7 bellard
    s->bytes_per_second = (s->freq << s->fmt_stereo);
226 85571bc7 bellard
    /* s->highspeed = (mask & DMA8_HIGH) != 0; */
227 85571bc7 bellard
    s->dma_auto = (mask & DMA8_AUTO) != 0;
228 85571bc7 bellard
    s->align = (1 << s->fmt_stereo) - 1;
229 85571bc7 bellard
230 15b61470 bellard
    if (s->block_size & s->align)
231 15b61470 bellard
        dolog ("warning: unaligned buffer\n");
232 15b61470 bellard
233 85571bc7 bellard
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
234 85571bc7 bellard
            "dma %d, auto %d, fifo %d, high %d\n",
235 85571bc7 bellard
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
236 85571bc7 bellard
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
237 85571bc7 bellard
238 85571bc7 bellard
    if (s->freq)
239 85571bc7 bellard
        s->voice = AUD_open (s->voice, "sb16", s->freq,
240 85571bc7 bellard
                             1 << s->fmt_stereo, s->fmt);
241 85571bc7 bellard
242 85571bc7 bellard
    control (s, 1);
243 85571bc7 bellard
    speaker (s, 1);
244 85571bc7 bellard
}
245 27503323 bellard
246 85571bc7 bellard
static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
247 85571bc7 bellard
{
248 85571bc7 bellard
    s->use_hdma = cmd < 0xc0;
249 85571bc7 bellard
    s->fifo = (cmd >> 1) & 1;
250 85571bc7 bellard
    s->dma_auto = (cmd >> 2) & 1;
251 85571bc7 bellard
    s->fmt_signed = (d0 >> 4) & 1;
252 85571bc7 bellard
    s->fmt_stereo = (d0 >> 5) & 1;
253 27503323 bellard
254 27503323 bellard
    switch (cmd >> 4) {
255 27503323 bellard
    case 11:
256 85571bc7 bellard
        s->fmt_bits = 16;
257 27503323 bellard
        break;
258 27503323 bellard
259 27503323 bellard
    case 12:
260 85571bc7 bellard
        s->fmt_bits = 8;
261 27503323 bellard
        break;
262 27503323 bellard
    }
263 27503323 bellard
264 85571bc7 bellard
    if (-1 != s->time_const) {
265 85571bc7 bellard
#if 1
266 85571bc7 bellard
        int tmp = 256 - s->time_const;
267 85571bc7 bellard
        s->freq = (1000000 + (tmp / 2)) / tmp;
268 85571bc7 bellard
#else
269 85571bc7 bellard
        /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
270 85571bc7 bellard
        s->freq = 1000000 / ((255 - s->time_const));
271 85571bc7 bellard
#endif
272 85571bc7 bellard
        s->time_const = -1;
273 27503323 bellard
    }
274 27503323 bellard
275 85571bc7 bellard
    s->block_size = dma_len + 1;
276 85571bc7 bellard
    s->block_size <<= (s->fmt_bits == 16);
277 15b61470 bellard
    if (!s->dma_auto) {
278 15b61470 bellard
        /* It is clear that for DOOM and auto-init this value
279 15b61470 bellard
           shouldn't take stereo into account, while Miles Sound Systems
280 15b61470 bellard
           setsound.exe with single transfer mode wouldn't work without it
281 15b61470 bellard
           wonders of SB16 yet again */
282 85571bc7 bellard
        s->block_size <<= s->fmt_stereo;
283 15b61470 bellard
    }
284 27503323 bellard
285 85571bc7 bellard
    ldebug ("freq %d, stereo %d, sign %d, bits %d, "
286 85571bc7 bellard
            "dma %d, auto %d, fifo %d, high %d\n",
287 85571bc7 bellard
            s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
288 85571bc7 bellard
            s->block_size, s->dma_auto, s->fifo, s->highspeed);
289 27503323 bellard
290 85571bc7 bellard
    if (16 == s->fmt_bits) {
291 85571bc7 bellard
        if (s->fmt_signed) {
292 85571bc7 bellard
            s->fmt = AUD_FMT_S16;
293 27503323 bellard
        }
294 27503323 bellard
        else {
295 85571bc7 bellard
            s->fmt = AUD_FMT_U16;
296 27503323 bellard
        }
297 27503323 bellard
    }
298 27503323 bellard
    else {
299 85571bc7 bellard
        if (s->fmt_signed) {
300 85571bc7 bellard
            s->fmt = AUD_FMT_S8;
301 27503323 bellard
        }
302 27503323 bellard
        else {
303 85571bc7 bellard
            s->fmt = AUD_FMT_U8;
304 27503323 bellard
        }
305 27503323 bellard
    }
306 27503323 bellard
307 85571bc7 bellard
    s->left_till_irq = s->block_size;
308 27503323 bellard
309 85571bc7 bellard
    s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
310 85571bc7 bellard
    s->highspeed = 0;
311 85571bc7 bellard
    s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
312 15b61470 bellard
    if (s->block_size & s->align)
313 15b61470 bellard
        dolog ("warning: unaligned buffer\n");
314 27503323 bellard
315 85571bc7 bellard
    if (s->freq)
316 85571bc7 bellard
        s->voice = AUD_open (s->voice, "sb16", s->freq,
317 85571bc7 bellard
                             1 << s->fmt_stereo, s->fmt);
318 27503323 bellard
319 85571bc7 bellard
    control (s, 1);
320 85571bc7 bellard
    speaker (s, 1);
321 27503323 bellard
}
322 27503323 bellard
323 85571bc7 bellard
static inline void dsp_out_data (SB16State *s, uint8_t val)
324 202a456a bellard
{
325 85571bc7 bellard
    ldebug ("outdata %#x\n", val);
326 85571bc7 bellard
    if (s->out_data_len < sizeof (s->out_data))
327 85571bc7 bellard
        s->out_data[s->out_data_len++] = val;
328 202a456a bellard
}
329 202a456a bellard
330 85571bc7 bellard
static inline uint8_t dsp_get_data (SB16State *s)
331 d75d9f6b bellard
{
332 85571bc7 bellard
    if (s->in_index)
333 85571bc7 bellard
        return s->in2_data[--s->in_index];
334 85571bc7 bellard
    else {
335 85571bc7 bellard
        dolog ("buffer underflow\n");
336 d75d9f6b bellard
        return 0;
337 85571bc7 bellard
    }
338 d75d9f6b bellard
}
339 d75d9f6b bellard
340 85571bc7 bellard
static void command (SB16State *s, uint8_t cmd)
341 27503323 bellard
{
342 85571bc7 bellard
    ldebug ("command %#x\n", cmd);
343 27503323 bellard
344 27503323 bellard
    if (cmd > 0xaf && cmd < 0xd0) {
345 85571bc7 bellard
        if (cmd & 8) {
346 85571bc7 bellard
            dolog ("ADC not yet supported (command %#x)\n", cmd);
347 85571bc7 bellard
        }
348 27503323 bellard
349 27503323 bellard
        switch (cmd >> 4) {
350 27503323 bellard
        case 11:
351 27503323 bellard
        case 12:
352 27503323 bellard
            break;
353 27503323 bellard
        default:
354 85571bc7 bellard
            dolog ("%#x wrong bits\n", cmd);
355 27503323 bellard
        }
356 85571bc7 bellard
        s->needed_bytes = 3;
357 27503323 bellard
    }
358 27503323 bellard
    else {
359 27503323 bellard
        switch (cmd) {
360 d75d9f6b bellard
        case 0x03:
361 85571bc7 bellard
            dsp_out_data (s, 0x10); /* s->csp_param); */
362 85571bc7 bellard
            goto warn;
363 85571bc7 bellard
364 d329a6fb bellard
        case 0x04:
365 85571bc7 bellard
            s->needed_bytes = 1;
366 85571bc7 bellard
            goto warn;
367 d329a6fb bellard
368 d329a6fb bellard
        case 0x05:
369 85571bc7 bellard
            s->needed_bytes = 2;
370 85571bc7 bellard
            goto warn;
371 85571bc7 bellard
372 85571bc7 bellard
        case 0x08:
373 85571bc7 bellard
            /* __asm__ ("int3"); */
374 85571bc7 bellard
            goto warn;
375 d75d9f6b bellard
376 d329a6fb bellard
        case 0x0e:
377 85571bc7 bellard
            s->needed_bytes = 2;
378 85571bc7 bellard
            goto warn;
379 85571bc7 bellard
380 85571bc7 bellard
        case 0x09:
381 85571bc7 bellard
            dsp_out_data (s, 0xf8);
382 85571bc7 bellard
            goto warn;
383 d329a6fb bellard
384 d329a6fb bellard
        case 0x0f:
385 85571bc7 bellard
            s->needed_bytes = 1;
386 85571bc7 bellard
            goto warn;
387 d329a6fb bellard
388 27503323 bellard
        case 0x10:
389 85571bc7 bellard
            s->needed_bytes = 1;
390 85571bc7 bellard
            goto warn;
391 27503323 bellard
392 27503323 bellard
        case 0x14:
393 85571bc7 bellard
            s->needed_bytes = 2;
394 85571bc7 bellard
            s->block_size = 0;
395 27503323 bellard
            break;
396 27503323 bellard
397 15b61470 bellard
        case 0x1c:              /* Auto-Initialize DMA DAC, 8-bit */
398 15b61470 bellard
            control (s, 1);
399 15b61470 bellard
            break;
400 15b61470 bellard
401 85571bc7 bellard
        case 0x20:              /* Direct ADC, Juice/PL */
402 85571bc7 bellard
            dsp_out_data (s, 0xff);
403 85571bc7 bellard
            goto warn;
404 27503323 bellard
405 27503323 bellard
        case 0x35:
406 85571bc7 bellard
            dolog ("MIDI command(0x35) not implemented\n");
407 27503323 bellard
            break;
408 27503323 bellard
409 27503323 bellard
        case 0x40:
410 85571bc7 bellard
            s->freq = -1;
411 85571bc7 bellard
            s->time_const = -1;
412 85571bc7 bellard
            s->needed_bytes = 1;
413 27503323 bellard
            break;
414 27503323 bellard
415 27503323 bellard
        case 0x41:
416 85571bc7 bellard
            s->freq = -1;
417 85571bc7 bellard
            s->time_const = -1;
418 85571bc7 bellard
            s->needed_bytes = 2;
419 27503323 bellard
            break;
420 27503323 bellard
421 85571bc7 bellard
        case 0x42:
422 85571bc7 bellard
            s->freq = -1;
423 85571bc7 bellard
            s->time_const = -1;
424 85571bc7 bellard
            s->needed_bytes = 2;
425 85571bc7 bellard
            goto warn;
426 85571bc7 bellard
427 d75d9f6b bellard
        case 0x45:
428 85571bc7 bellard
            dsp_out_data (s, 0xaa);
429 85571bc7 bellard
            goto warn;
430 85571bc7 bellard
431 27503323 bellard
        case 0x47:                /* Continue Auto-Initialize DMA 16bit */
432 27503323 bellard
            break;
433 27503323 bellard
434 27503323 bellard
        case 0x48:
435 85571bc7 bellard
            s->needed_bytes = 2;
436 27503323 bellard
            break;
437 27503323 bellard
438 27503323 bellard
        case 0x80:
439 85571bc7 bellard
            s->needed_bytes = 2;
440 27503323 bellard
            break;
441 27503323 bellard
442 27503323 bellard
        case 0x90:
443 27503323 bellard
        case 0x91:
444 85571bc7 bellard
            dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
445 85571bc7 bellard
            break;
446 27503323 bellard
447 85571bc7 bellard
        case 0xd0:              /* halt DMA operation. 8bit */
448 85571bc7 bellard
            control (s, 0);
449 85571bc7 bellard
            break;
450 27503323 bellard
451 85571bc7 bellard
        case 0xd1:              /* speaker on */
452 85571bc7 bellard
            speaker (s, 1);
453 27503323 bellard
            break;
454 27503323 bellard
455 85571bc7 bellard
        case 0xd3:              /* speaker off */
456 85571bc7 bellard
            speaker (s, 0);
457 85571bc7 bellard
            break;
458 27503323 bellard
459 85571bc7 bellard
        case 0xd4:              /* continue DMA operation. 8bit */
460 85571bc7 bellard
            control (s, 1);
461 27503323 bellard
            break;
462 27503323 bellard
463 85571bc7 bellard
        case 0xd5:              /* halt DMA operation. 16bit */
464 85571bc7 bellard
            control (s, 0);
465 27503323 bellard
            break;
466 27503323 bellard
467 85571bc7 bellard
        case 0xd6:              /* continue DMA operation. 16bit */
468 85571bc7 bellard
            control (s, 1);
469 27503323 bellard
            break;
470 27503323 bellard
471 85571bc7 bellard
        case 0xd9:              /* exit auto-init DMA after this block. 16bit */
472 85571bc7 bellard
            s->dma_auto = 0;
473 85571bc7 bellard
            break;
474 27503323 bellard
475 85571bc7 bellard
        case 0xda:              /* exit auto-init DMA after this block. 8bit */
476 85571bc7 bellard
            s->dma_auto = 0;
477 27503323 bellard
            break;
478 27503323 bellard
479 27503323 bellard
        case 0xe0:
480 85571bc7 bellard
            s->needed_bytes = 1;
481 85571bc7 bellard
            goto warn;
482 27503323 bellard
483 27503323 bellard
        case 0xe1:
484 85571bc7 bellard
            dsp_out_data (s, s->ver & 0xff);
485 85571bc7 bellard
            dsp_out_data (s, s->ver >> 8);
486 85571bc7 bellard
            break;
487 85571bc7 bellard
488 85571bc7 bellard
        case 0xe2:
489 85571bc7 bellard
            s->needed_bytes = 1;
490 85571bc7 bellard
            goto warn;
491 27503323 bellard
492 d329a6fb bellard
        case 0xe3:
493 d329a6fb bellard
            {
494 d329a6fb bellard
                int i;
495 85571bc7 bellard
                for (i = sizeof (e3) - 1; i >= 0; --i)
496 85571bc7 bellard
                    dsp_out_data (s, e3[i]);
497 d329a6fb bellard
            }
498 85571bc7 bellard
            break;
499 d329a6fb bellard
500 d75d9f6b bellard
        case 0xe4:              /* write test reg */
501 85571bc7 bellard
            s->needed_bytes = 1;
502 d75d9f6b bellard
            break;
503 d75d9f6b bellard
504 85571bc7 bellard
        case 0xe7:
505 85571bc7 bellard
            dolog ("Attempt to probe for ESS (0xe7)?\n");
506 85571bc7 bellard
            return;
507 85571bc7 bellard
508 d75d9f6b bellard
        case 0xe8:              /* read test reg */
509 85571bc7 bellard
            dsp_out_data (s, s->test_reg);
510 d75d9f6b bellard
            break;
511 d75d9f6b bellard
512 27503323 bellard
        case 0xf2:
513 85571bc7 bellard
        case 0xf3:
514 85571bc7 bellard
            dsp_out_data (s, 0xaa);
515 85571bc7 bellard
            s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
516 85571bc7 bellard
            pic_set_irq (s->irq, 1);
517 85571bc7 bellard
            break;
518 27503323 bellard
519 d75d9f6b bellard
        case 0xf9:
520 85571bc7 bellard
            s->needed_bytes = 1;
521 85571bc7 bellard
            goto warn;
522 d75d9f6b bellard
523 d75d9f6b bellard
        case 0xfa:
524 85571bc7 bellard
            dsp_out_data (s, 0);
525 85571bc7 bellard
            goto warn;
526 d75d9f6b bellard
527 d75d9f6b bellard
        case 0xfc:              /* FIXME */
528 85571bc7 bellard
            dsp_out_data (s, 0);
529 85571bc7 bellard
            goto warn;
530 d75d9f6b bellard
531 27503323 bellard
        default:
532 d75d9f6b bellard
            dolog ("unrecognized command %#x\n", cmd);
533 85571bc7 bellard
            return;
534 27503323 bellard
        }
535 27503323 bellard
    }
536 85571bc7 bellard
537 85571bc7 bellard
    s->cmd = cmd;
538 85571bc7 bellard
    if (!s->needed_bytes)
539 85571bc7 bellard
        ldebug ("\n");
540 27503323 bellard
    return;
541 27503323 bellard
542 85571bc7 bellard
 warn:
543 fb065187 bellard
    dolog ("warning: command %#x,%d is not trully understood yet\n",
544 85571bc7 bellard
           cmd, s->needed_bytes);
545 85571bc7 bellard
    s->cmd = cmd;
546 27503323 bellard
    return;
547 27503323 bellard
}
548 27503323 bellard
549 85571bc7 bellard
static uint16_t dsp_get_lohi (SB16State *s)
550 85571bc7 bellard
{
551 85571bc7 bellard
    uint8_t hi = dsp_get_data (s);
552 85571bc7 bellard
    uint8_t lo = dsp_get_data (s);
553 85571bc7 bellard
    return (hi << 8) | lo;
554 85571bc7 bellard
}
555 85571bc7 bellard
556 85571bc7 bellard
static uint16_t dsp_get_hilo (SB16State *s)
557 85571bc7 bellard
{
558 85571bc7 bellard
    uint8_t lo = dsp_get_data (s);
559 85571bc7 bellard
    uint8_t hi = dsp_get_data (s);
560 85571bc7 bellard
    return (hi << 8) | lo;
561 85571bc7 bellard
}
562 85571bc7 bellard
563 85571bc7 bellard
static void complete (SB16State *s)
564 27503323 bellard
{
565 d75d9f6b bellard
    int d0, d1, d2;
566 85571bc7 bellard
    ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
567 85571bc7 bellard
            s->cmd, s->in_index, s->needed_bytes);
568 27503323 bellard
569 85571bc7 bellard
    if (s->cmd > 0xaf && s->cmd < 0xd0) {
570 85571bc7 bellard
        d2 = dsp_get_data (s);
571 85571bc7 bellard
        d1 = dsp_get_data (s);
572 85571bc7 bellard
        d0 = dsp_get_data (s);
573 27503323 bellard
574 85571bc7 bellard
        if (s->cmd & 8) {
575 85571bc7 bellard
            dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
576 85571bc7 bellard
                   s->cmd, d0, d1, d2);
577 85571bc7 bellard
        }
578 85571bc7 bellard
        else {
579 85571bc7 bellard
            ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
580 85571bc7 bellard
                    s->cmd, d0, d1, d2);
581 85571bc7 bellard
            dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
582 85571bc7 bellard
        }
583 27503323 bellard
    }
584 27503323 bellard
    else {
585 85571bc7 bellard
        switch (s->cmd) {
586 d329a6fb bellard
        case 0x04:
587 85571bc7 bellard
            s->csp_mode = dsp_get_data (s);
588 85571bc7 bellard
            s->csp_reg83r = 0;
589 85571bc7 bellard
            s->csp_reg83w = 0;
590 85571bc7 bellard
            ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
591 d75d9f6b bellard
            break;
592 d75d9f6b bellard
593 85571bc7 bellard
        case 0x05:
594 85571bc7 bellard
            s->csp_param = dsp_get_data (s);
595 85571bc7 bellard
            s->csp_value = dsp_get_data (s);
596 85571bc7 bellard
            ldebug ("CSP command 0x05: param=%#x value=%#x\n",
597 85571bc7 bellard
                    s->csp_param,
598 85571bc7 bellard
                    s->csp_value);
599 d329a6fb bellard
            break;
600 27503323 bellard
601 d75d9f6b bellard
        case 0x0e:
602 85571bc7 bellard
            d0 = dsp_get_data (s);
603 85571bc7 bellard
            d1 = dsp_get_data (s);
604 85571bc7 bellard
            ldebug ("write CSP register %d <- %#x\n", d1, d0);
605 85571bc7 bellard
            if (d1 == 0x83) {
606 85571bc7 bellard
                ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
607 85571bc7 bellard
                s->csp_reg83[s->csp_reg83r % 4] = d0;
608 85571bc7 bellard
                s->csp_reg83r += 1;
609 85571bc7 bellard
            }
610 85571bc7 bellard
            else
611 85571bc7 bellard
                s->csp_regs[d1] = d0;
612 27503323 bellard
            break;
613 27503323 bellard
614 85571bc7 bellard
        case 0x0f:
615 85571bc7 bellard
            d0 = dsp_get_data (s);
616 85571bc7 bellard
            ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
617 85571bc7 bellard
                    d0, s->csp_regs[d0], s->csp_mode);
618 85571bc7 bellard
            if (d0 == 0x83) {
619 85571bc7 bellard
                ldebug ("0x83[%d] -> %#x\n",
620 85571bc7 bellard
                        s->csp_reg83w,
621 85571bc7 bellard
                        s->csp_reg83[s->csp_reg83w % 4]);
622 85571bc7 bellard
                dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
623 85571bc7 bellard
                s->csp_reg83w += 1;
624 85571bc7 bellard
            }
625 85571bc7 bellard
            else
626 85571bc7 bellard
                dsp_out_data (s, s->csp_regs[d0]);
627 85571bc7 bellard
            break;
628 27503323 bellard
629 85571bc7 bellard
        case 0x10:
630 85571bc7 bellard
            d0 = dsp_get_data (s);
631 85571bc7 bellard
            dolog ("cmd 0x10 d0=%#x\n", d0);
632 85571bc7 bellard
            break;
633 27503323 bellard
634 85571bc7 bellard
        case 0x14:
635 15b61470 bellard
            dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
636 85571bc7 bellard
            break;
637 27503323 bellard
638 27503323 bellard
        case 0x40:
639 85571bc7 bellard
            s->time_const = dsp_get_data (s);
640 85571bc7 bellard
            ldebug ("set time const %d\n", s->time_const);
641 27503323 bellard
            break;
642 27503323 bellard
643 85571bc7 bellard
        case 0x42:              /* FT2 sets output freq with this, go figure */
644 85571bc7 bellard
            dolog ("cmd 0x42 might not do what it think it should\n");
645 d75d9f6b bellard
646 85571bc7 bellard
        case 0x41:
647 85571bc7 bellard
            s->freq = dsp_get_hilo (s);
648 85571bc7 bellard
            ldebug ("set freq %d\n", s->freq);
649 27503323 bellard
            break;
650 27503323 bellard
651 27503323 bellard
        case 0x48:
652 15b61470 bellard
            s->block_size = dsp_get_lohi (s) + 1;
653 85571bc7 bellard
            ldebug ("set dma block len %d\n", s->block_size);
654 85571bc7 bellard
            break;
655 85571bc7 bellard
656 85571bc7 bellard
        case 0x80:
657 85571bc7 bellard
            {
658 15b61470 bellard
                int freq, samples, bytes;
659 85571bc7 bellard
                int64_t ticks;
660 85571bc7 bellard
661 15b61470 bellard
                freq = s->freq > 0 ? s->freq : 11025;
662 15b61470 bellard
                samples = dsp_get_lohi (s) + 1;
663 85571bc7 bellard
                bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
664 15b61470 bellard
                ticks = (bytes * ticks_per_sec) / freq;
665 15b61470 bellard
                if (ticks < ticks_per_sec / 1024)
666 85571bc7 bellard
                    pic_set_irq (s->irq, 1);
667 85571bc7 bellard
                else
668 85571bc7 bellard
                    qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
669 85571bc7 bellard
                ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
670 85571bc7 bellard
            }
671 27503323 bellard
            break;
672 27503323 bellard
673 27503323 bellard
        case 0xe0:
674 85571bc7 bellard
            d0 = dsp_get_data (s);
675 85571bc7 bellard
            s->out_data_len = 0;
676 85571bc7 bellard
            ldebug ("E0 data = %#x\n", d0);
677 85571bc7 bellard
            dsp_out_data(s, ~d0);
678 d75d9f6b bellard
            break;
679 d75d9f6b bellard
680 85571bc7 bellard
        case 0xe2:
681 85571bc7 bellard
            d0 = dsp_get_data (s);
682 15b61470 bellard
            ldebug ("E2 = %#x\n", d0);
683 d75d9f6b bellard
            break;
684 d75d9f6b bellard
685 85571bc7 bellard
        case 0xe4:
686 85571bc7 bellard
            s->test_reg = dsp_get_data (s);
687 85571bc7 bellard
            break;
688 d75d9f6b bellard
689 d75d9f6b bellard
        case 0xf9:
690 85571bc7 bellard
            d0 = dsp_get_data (s);
691 85571bc7 bellard
            ldebug ("command 0xf9 with %#x\n", d0);
692 d75d9f6b bellard
            switch (d0) {
693 85571bc7 bellard
            case 0x0e:
694 85571bc7 bellard
                dsp_out_data (s, 0xff);
695 85571bc7 bellard
                break;
696 85571bc7 bellard
697 85571bc7 bellard
            case 0x0f:
698 85571bc7 bellard
                dsp_out_data (s, 0x07);
699 85571bc7 bellard
                break;
700 85571bc7 bellard
701 d75d9f6b bellard
            case 0x37:
702 85571bc7 bellard
                dsp_out_data (s, 0x38);
703 85571bc7 bellard
                break;
704 85571bc7 bellard
705 d75d9f6b bellard
            default:
706 85571bc7 bellard
                dsp_out_data (s, 0x00);
707 85571bc7 bellard
                break;
708 d75d9f6b bellard
            }
709 27503323 bellard
            break;
710 27503323 bellard
711 27503323 bellard
        default:
712 85571bc7 bellard
            dolog ("complete: unrecognized command %#x\n", s->cmd);
713 5e2a6443 bellard
            return;
714 27503323 bellard
        }
715 27503323 bellard
    }
716 27503323 bellard
717 85571bc7 bellard
    ldebug ("\n");
718 85571bc7 bellard
    s->cmd = -1;
719 27503323 bellard
    return;
720 27503323 bellard
}
721 27503323 bellard
722 85571bc7 bellard
static void reset (SB16State *s)
723 85571bc7 bellard
{
724 85571bc7 bellard
    pic_set_irq (s->irq, 0);
725 85571bc7 bellard
    if (s->dma_auto) {
726 85571bc7 bellard
        pic_set_irq (s->irq, 1);
727 85571bc7 bellard
        pic_set_irq (s->irq, 0);
728 85571bc7 bellard
    }
729 85571bc7 bellard
730 85571bc7 bellard
    s->mixer_regs[0x82] = 0;
731 85571bc7 bellard
    s->dma_auto = 0;
732 85571bc7 bellard
    s->in_index = 0;
733 85571bc7 bellard
    s->out_data_len = 0;
734 85571bc7 bellard
    s->left_till_irq = 0;
735 85571bc7 bellard
    s->needed_bytes = 0;
736 85571bc7 bellard
    s->block_size = -1;
737 85571bc7 bellard
    s->nzero = 0;
738 85571bc7 bellard
    s->highspeed = 0;
739 85571bc7 bellard
    s->v2x6 = 0;
740 85571bc7 bellard
741 85571bc7 bellard
    dsp_out_data(s, 0xaa);
742 85571bc7 bellard
    speaker (s, 0);
743 85571bc7 bellard
    control (s, 0);
744 85571bc7 bellard
}
745 85571bc7 bellard
746 27503323 bellard
static IO_WRITE_PROTO (dsp_write)
747 27503323 bellard
{
748 85571bc7 bellard
    SB16State *s = opaque;
749 27503323 bellard
    int iport;
750 27503323 bellard
751 85571bc7 bellard
    iport = nport - s->port;
752 27503323 bellard
753 85571bc7 bellard
    ldebug ("write %#x <- %#x\n", nport, val);
754 27503323 bellard
    switch (iport) {
755 85571bc7 bellard
    case 0x06:
756 85571bc7 bellard
        switch (val) {
757 85571bc7 bellard
        case 0x00:
758 85571bc7 bellard
            if (s->v2x6 == 1) {
759 85571bc7 bellard
                if (0 && s->highspeed) {
760 85571bc7 bellard
                    s->highspeed = 0;
761 85571bc7 bellard
                    pic_set_irq (s->irq, 0);
762 85571bc7 bellard
                    control (s, 0);
763 85571bc7 bellard
                }
764 85571bc7 bellard
                else
765 85571bc7 bellard
                    reset (s);
766 85571bc7 bellard
            }
767 85571bc7 bellard
            s->v2x6 = 0;
768 85571bc7 bellard
            break;
769 85571bc7 bellard
770 85571bc7 bellard
        case 0x01:
771 85571bc7 bellard
        case 0x03:              /* FreeBSD kludge */
772 85571bc7 bellard
            s->v2x6 = 1;
773 85571bc7 bellard
            break;
774 85571bc7 bellard
775 85571bc7 bellard
        case 0xc6:
776 85571bc7 bellard
            s->v2x6 = 0;        /* Prince of Persia, csp.sys, diagnose.exe */
777 85571bc7 bellard
            break;
778 85571bc7 bellard
779 85571bc7 bellard
        case 0xb8:              /* Panic */
780 85571bc7 bellard
            reset (s);
781 85571bc7 bellard
            break;
782 85571bc7 bellard
783 85571bc7 bellard
        case 0x39:
784 85571bc7 bellard
            dsp_out_data (s, 0x38);
785 85571bc7 bellard
            reset (s);
786 85571bc7 bellard
            s->v2x6 = 0x39;
787 85571bc7 bellard
            break;
788 85571bc7 bellard
789 85571bc7 bellard
        default:
790 85571bc7 bellard
            s->v2x6 = val;
791 85571bc7 bellard
            break;
792 27503323 bellard
        }
793 27503323 bellard
        break;
794 27503323 bellard
795 85571bc7 bellard
    case 0x0c:                  /* write data or command | write status */
796 85571bc7 bellard
/*         if (s->highspeed) */
797 85571bc7 bellard
/*             break; */
798 85571bc7 bellard
799 85571bc7 bellard
        if (0 == s->needed_bytes) {
800 85571bc7 bellard
            command (s, val);
801 85571bc7 bellard
#if 0
802 85571bc7 bellard
            if (0 == s->needed_bytes) {
803 85571bc7 bellard
                log_dsp (s);
804 27503323 bellard
            }
805 85571bc7 bellard
#endif
806 27503323 bellard
        }
807 27503323 bellard
        else {
808 85571bc7 bellard
            if (s->in_index == sizeof (s->in2_data)) {
809 d75d9f6b bellard
                dolog ("in data overrun\n");
810 d75d9f6b bellard
            }
811 d75d9f6b bellard
            else {
812 85571bc7 bellard
                s->in2_data[s->in_index++] = val;
813 85571bc7 bellard
                if (s->in_index == s->needed_bytes) {
814 85571bc7 bellard
                    s->needed_bytes = 0;
815 85571bc7 bellard
                    complete (s);
816 85571bc7 bellard
#if 0
817 85571bc7 bellard
                    log_dsp (s);
818 85571bc7 bellard
#endif
819 85571bc7 bellard
                }
820 27503323 bellard
            }
821 27503323 bellard
        }
822 27503323 bellard
        break;
823 27503323 bellard
824 27503323 bellard
    default:
825 85571bc7 bellard
        ldebug ("(nport=%#x, val=%#x)\n", nport, val);
826 5e2a6443 bellard
        break;
827 27503323 bellard
    }
828 27503323 bellard
}
829 27503323 bellard
830 27503323 bellard
static IO_READ_PROTO (dsp_read)
831 27503323 bellard
{
832 85571bc7 bellard
    SB16State *s = opaque;
833 85571bc7 bellard
    int iport, retval, ack = 0;
834 27503323 bellard
835 85571bc7 bellard
    iport = nport - s->port;
836 27503323 bellard
837 27503323 bellard
    switch (iport) {
838 85571bc7 bellard
    case 0x06:                  /* reset */
839 85571bc7 bellard
        retval = 0xff;
840 d75d9f6b bellard
        break;
841 27503323 bellard
842 85571bc7 bellard
    case 0x0a:                  /* read data */
843 85571bc7 bellard
        if (s->out_data_len) {
844 85571bc7 bellard
            retval = s->out_data[--s->out_data_len];
845 85571bc7 bellard
            s->last_read_byte = retval;
846 85571bc7 bellard
        }
847 85571bc7 bellard
        else {
848 d75d9f6b bellard
            dolog ("empty output buffer\n");
849 85571bc7 bellard
            retval = s->last_read_byte;
850 d75d9f6b bellard
            /* goto error; */
851 27503323 bellard
        }
852 27503323 bellard
        break;
853 27503323 bellard
854 85571bc7 bellard
    case 0x0c:                  /* 0 can write */
855 85571bc7 bellard
        retval = s->can_write ? 0 : 0x80;
856 27503323 bellard
        break;
857 27503323 bellard
858 85571bc7 bellard
    case 0x0d:                  /* timer interrupt clear */
859 85571bc7 bellard
        /* dolog ("timer interrupt clear\n"); */
860 85571bc7 bellard
        retval = 0;
861 85571bc7 bellard
        break;
862 27503323 bellard
863 85571bc7 bellard
    case 0x0e:                  /* data available status | irq 8 ack */
864 85571bc7 bellard
        retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
865 85571bc7 bellard
        if (s->mixer_regs[0x82] & 1) {
866 85571bc7 bellard
            ack = 1;
867 85571bc7 bellard
            s->mixer_regs[0x82] &= 1;
868 85571bc7 bellard
            pic_set_irq (s->irq, 0);
869 85571bc7 bellard
        }
870 27503323 bellard
        break;
871 27503323 bellard
872 85571bc7 bellard
    case 0x0f:                  /* irq 16 ack */
873 bc0b1dc1 bellard
        retval = 0xff;
874 85571bc7 bellard
        if (s->mixer_regs[0x82] & 2) {
875 85571bc7 bellard
            ack = 1;
876 85571bc7 bellard
            s->mixer_regs[0x82] &= 2;
877 85571bc7 bellard
            pic_set_irq (s->irq, 0);
878 85571bc7 bellard
        }
879 27503323 bellard
        break;
880 27503323 bellard
881 27503323 bellard
    default:
882 27503323 bellard
        goto error;
883 27503323 bellard
    }
884 27503323 bellard
885 85571bc7 bellard
    if (!ack)
886 85571bc7 bellard
        ldebug ("read %#x -> %#x\n", nport, retval);
887 27503323 bellard
888 27503323 bellard
    return retval;
889 27503323 bellard
890 27503323 bellard
 error:
891 85571bc7 bellard
    dolog ("WARNING dsp_read %#x error\n", nport);
892 d75d9f6b bellard
    return 0xff;
893 27503323 bellard
}
894 27503323 bellard
895 85571bc7 bellard
static void reset_mixer (SB16State *s)
896 85571bc7 bellard
{
897 85571bc7 bellard
    int i;
898 85571bc7 bellard
899 85571bc7 bellard
    memset (s->mixer_regs, 0xff, 0x7f);
900 85571bc7 bellard
    memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
901 85571bc7 bellard
902 85571bc7 bellard
    s->mixer_regs[0x02] = 4;    /* master volume 3bits */
903 85571bc7 bellard
    s->mixer_regs[0x06] = 4;    /* MIDI volume 3bits */
904 85571bc7 bellard
    s->mixer_regs[0x08] = 0;    /* CD volume 3bits */
905 85571bc7 bellard
    s->mixer_regs[0x0a] = 0;    /* voice volume 2bits */
906 85571bc7 bellard
907 85571bc7 bellard
    /* d5=input filt, d3=lowpass filt, d1,d2=input source */
908 85571bc7 bellard
    s->mixer_regs[0x0c] = 0;
909 85571bc7 bellard
910 85571bc7 bellard
    /* d5=output filt, d1=stereo switch */
911 85571bc7 bellard
    s->mixer_regs[0x0e] = 0;
912 85571bc7 bellard
913 85571bc7 bellard
    /* voice volume L d5,d7, R d1,d3 */
914 85571bc7 bellard
    s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
915 85571bc7 bellard
    /* master ... */
916 85571bc7 bellard
    s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
917 85571bc7 bellard
    /* MIDI ... */
918 85571bc7 bellard
    s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
919 85571bc7 bellard
920 85571bc7 bellard
    for (i = 0x30; i < 0x48; i++) {
921 85571bc7 bellard
        s->mixer_regs[i] = 0x20;
922 85571bc7 bellard
    }
923 85571bc7 bellard
}
924 85571bc7 bellard
925 27503323 bellard
static IO_WRITE_PROTO(mixer_write_indexb)
926 27503323 bellard
{
927 85571bc7 bellard
    SB16State *s = opaque;
928 85571bc7 bellard
    s->mixer_nreg = val;
929 27503323 bellard
}
930 27503323 bellard
931 27503323 bellard
static IO_WRITE_PROTO(mixer_write_datab)
932 27503323 bellard
{
933 85571bc7 bellard
    SB16State *s = opaque;
934 85571bc7 bellard
935 85571bc7 bellard
    ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
936 85571bc7 bellard
    if (s->mixer_nreg > sizeof (s->mixer_regs))
937 85571bc7 bellard
        return;
938 202a456a bellard
939 85571bc7 bellard
    switch (s->mixer_nreg) {
940 d75d9f6b bellard
    case 0x00:
941 85571bc7 bellard
        reset_mixer (s);
942 d75d9f6b bellard
        break;
943 d75d9f6b bellard
944 d75d9f6b bellard
    case 0x80:
945 85571bc7 bellard
        {
946 85571bc7 bellard
            int irq = irq_of_magic (val);
947 85571bc7 bellard
            ldebug ("setting irq to %d (val=%#x)\n", irq, val);
948 85571bc7 bellard
            if (irq > 0)
949 85571bc7 bellard
                s->irq = irq;
950 85571bc7 bellard
        }
951 d75d9f6b bellard
        break;
952 27503323 bellard
953 85571bc7 bellard
    case 0x81:
954 85571bc7 bellard
        {
955 85571bc7 bellard
            int dma, hdma;
956 d75d9f6b bellard
957 85571bc7 bellard
            dma = lsbindex (val & 0xf);
958 85571bc7 bellard
            hdma = lsbindex (val & 0xf0);
959 85571bc7 bellard
            dolog ("attempt to set DMA register 8bit %d, 16bit %d (val=%#x)\n",
960 85571bc7 bellard
                   dma, hdma, val);
961 85571bc7 bellard
#if 0
962 85571bc7 bellard
            s->dma = dma;
963 85571bc7 bellard
            s->hdma = hdma;
964 85571bc7 bellard
#endif
965 85571bc7 bellard
        }
966 85571bc7 bellard
        break;
967 d75d9f6b bellard
968 85571bc7 bellard
    case 0x82:
969 85571bc7 bellard
        dolog ("attempt to write into IRQ status register (val=%#x)\n",
970 85571bc7 bellard
               val);
971 85571bc7 bellard
        return;
972 d75d9f6b bellard
973 85571bc7 bellard
    default:
974 85571bc7 bellard
        if (s->mixer_nreg >= 0x80)
975 85571bc7 bellard
            dolog ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
976 85571bc7 bellard
        break;
977 85571bc7 bellard
    }
978 85571bc7 bellard
979 85571bc7 bellard
    s->mixer_regs[s->mixer_nreg] = val;
980 d75d9f6b bellard
}
981 d75d9f6b bellard
982 27503323 bellard
static IO_WRITE_PROTO(mixer_write_indexw)
983 27503323 bellard
{
984 7d977de7 bellard
    mixer_write_indexb (opaque, nport, val & 0xff);
985 7d977de7 bellard
    mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
986 27503323 bellard
}
987 27503323 bellard
988 27503323 bellard
static IO_READ_PROTO(mixer_read)
989 27503323 bellard
{
990 85571bc7 bellard
    SB16State *s = opaque;
991 15b61470 bellard
#ifndef DEBUG_SB16_MOST
992 15b61470 bellard
    if (s->mixer_nreg != 0x82)
993 15b61470 bellard
#endif
994 85571bc7 bellard
    ldebug ("mixer_read[%#x] -> %#x\n",
995 85571bc7 bellard
            s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
996 85571bc7 bellard
    return s->mixer_regs[s->mixer_nreg];
997 27503323 bellard
}
998 27503323 bellard
999 85571bc7 bellard
static int write_audio (SB16State *s, int nchan, int dma_pos,
1000 85571bc7 bellard
                        int dma_len, int len)
1001 27503323 bellard
{
1002 27503323 bellard
    int temp, net;
1003 f9e92e97 bellard
    uint8_t tmpbuf[4096];
1004 27503323 bellard
1005 85571bc7 bellard
    temp = len;
1006 27503323 bellard
    net = 0;
1007 27503323 bellard
1008 27503323 bellard
    while (temp) {
1009 85571bc7 bellard
        int left = dma_len - dma_pos;
1010 85571bc7 bellard
        int to_copy, copied;
1011 27503323 bellard
1012 85571bc7 bellard
        to_copy = audio_MIN (temp, left);
1013 f9e92e97 bellard
        if (to_copy > sizeof(tmpbuf))
1014 f9e92e97 bellard
            to_copy = sizeof(tmpbuf);
1015 27503323 bellard
1016 85571bc7 bellard
        copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
1017 85571bc7 bellard
        copied = AUD_write (s->voice, tmpbuf, copied);
1018 27503323 bellard
1019 85571bc7 bellard
        temp -= copied;
1020 85571bc7 bellard
        dma_pos = (dma_pos + copied) % dma_len;
1021 27503323 bellard
        net += copied;
1022 27503323 bellard
1023 85571bc7 bellard
        if (!copied)
1024 85571bc7 bellard
            break;
1025 27503323 bellard
    }
1026 27503323 bellard
1027 27503323 bellard
    return net;
1028 27503323 bellard
}
1029 27503323 bellard
1030 85571bc7 bellard
static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1031 27503323 bellard
{
1032 85571bc7 bellard
    SB16State *s = opaque;
1033 85571bc7 bellard
    int free, rfree, till, copy, written, elapsed;
1034 27503323 bellard
1035 85571bc7 bellard
    if (s->left_till_irq < 0) {
1036 85571bc7 bellard
        s->left_till_irq = s->block_size;
1037 27503323 bellard
    }
1038 27503323 bellard
1039 85571bc7 bellard
    elapsed = AUD_calc_elapsed (s->voice);
1040 85571bc7 bellard
    free = elapsed;/* AUD_get_free (s->voice); */
1041 85571bc7 bellard
    rfree = free;
1042 85571bc7 bellard
    free = audio_MIN (free, elapsed) & ~s->align;
1043 27503323 bellard
1044 85571bc7 bellard
    if ((free <= 0) || !dma_len) {
1045 85571bc7 bellard
        return dma_pos;
1046 27503323 bellard
    }
1047 27503323 bellard
1048 85571bc7 bellard
    copy = free;
1049 85571bc7 bellard
    till = s->left_till_irq;
1050 27503323 bellard
1051 d75d9f6b bellard
#ifdef DEBUG_SB16_MOST
1052 85571bc7 bellard
    dolog ("pos:%06d free:%d,%d till:%d len:%d\n",
1053 85571bc7 bellard
           dma_pos, free, AUD_get_free (s->voice), till, dma_len);
1054 d75d9f6b bellard
#endif
1055 d75d9f6b bellard
1056 27503323 bellard
    if (till <= copy) {
1057 85571bc7 bellard
        if (0 == s->dma_auto) {
1058 27503323 bellard
            copy = till;
1059 27503323 bellard
        }
1060 27503323 bellard
    }
1061 27503323 bellard
1062 85571bc7 bellard
    written = write_audio (s, nchan, dma_pos, dma_len, copy);
1063 85571bc7 bellard
    dma_pos = (dma_pos + written) % dma_len;
1064 85571bc7 bellard
    s->left_till_irq -= written;
1065 27503323 bellard
1066 85571bc7 bellard
    if (s->left_till_irq <= 0) {
1067 85571bc7 bellard
        s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1068 85571bc7 bellard
        pic_set_irq (s->irq, 1);
1069 85571bc7 bellard
        if (0 == s->dma_auto) {
1070 85571bc7 bellard
            control (s, 0);
1071 85571bc7 bellard
            speaker (s, 0);
1072 27503323 bellard
        }
1073 27503323 bellard
    }
1074 27503323 bellard
1075 d75d9f6b bellard
#ifdef DEBUG_SB16_MOST
1076 15b61470 bellard
    ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
1077 15b61470 bellard
            dma_pos, free, dma_len, s->left_till_irq, copy, written,
1078 15b61470 bellard
            s->block_size);
1079 d75d9f6b bellard
#endif
1080 27503323 bellard
1081 85571bc7 bellard
    while (s->left_till_irq <= 0) {
1082 85571bc7 bellard
        s->left_till_irq = s->block_size + s->left_till_irq;
1083 27503323 bellard
    }
1084 27503323 bellard
1085 85571bc7 bellard
    AUD_adjust (s->voice, written);
1086 85571bc7 bellard
    return dma_pos;
1087 27503323 bellard
}
1088 27503323 bellard
1089 85571bc7 bellard
void SB_timer (void *opaque)
1090 27503323 bellard
{
1091 85571bc7 bellard
    SB16State *s = opaque;
1092 85571bc7 bellard
    AUD_run ();
1093 85571bc7 bellard
    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
1094 27503323 bellard
}
1095 27503323 bellard
1096 85571bc7 bellard
static void SB_save (QEMUFile *f, void *opaque)
1097 d75d9f6b bellard
{
1098 85571bc7 bellard
    SB16State *s = opaque;
1099 85571bc7 bellard
1100 85571bc7 bellard
    qemu_put_be32s (f, &s->irq);
1101 85571bc7 bellard
    qemu_put_be32s (f, &s->dma);
1102 85571bc7 bellard
    qemu_put_be32s (f, &s->hdma);
1103 85571bc7 bellard
    qemu_put_be32s (f, &s->port);
1104 85571bc7 bellard
    qemu_put_be32s (f, &s->ver);
1105 85571bc7 bellard
    qemu_put_be32s (f, &s->in_index);
1106 85571bc7 bellard
    qemu_put_be32s (f, &s->out_data_len);
1107 85571bc7 bellard
    qemu_put_be32s (f, &s->fmt_stereo);
1108 85571bc7 bellard
    qemu_put_be32s (f, &s->fmt_signed);
1109 85571bc7 bellard
    qemu_put_be32s (f, &s->fmt_bits);
1110 85571bc7 bellard
    qemu_put_be32s (f, &s->fmt);
1111 85571bc7 bellard
    qemu_put_be32s (f, &s->dma_auto);
1112 85571bc7 bellard
    qemu_put_be32s (f, &s->block_size);
1113 85571bc7 bellard
    qemu_put_be32s (f, &s->fifo);
1114 85571bc7 bellard
    qemu_put_be32s (f, &s->freq);
1115 85571bc7 bellard
    qemu_put_be32s (f, &s->time_const);
1116 85571bc7 bellard
    qemu_put_be32s (f, &s->speaker);
1117 85571bc7 bellard
    qemu_put_be32s (f, &s->needed_bytes);
1118 85571bc7 bellard
    qemu_put_be32s (f, &s->cmd);
1119 85571bc7 bellard
    qemu_put_be32s (f, &s->use_hdma);
1120 85571bc7 bellard
    qemu_put_be32s (f, &s->highspeed);
1121 85571bc7 bellard
    qemu_put_be32s (f, &s->can_write);
1122 85571bc7 bellard
    qemu_put_be32s (f, &s->v2x6);
1123 85571bc7 bellard
1124 85571bc7 bellard
    qemu_put_8s (f, &s->csp_param);
1125 85571bc7 bellard
    qemu_put_8s (f, &s->csp_value);
1126 85571bc7 bellard
    qemu_put_8s (f, &s->csp_mode);
1127 85571bc7 bellard
    qemu_put_8s (f, &s->csp_param);
1128 85571bc7 bellard
    qemu_put_buffer (f, s->csp_regs, 256);
1129 85571bc7 bellard
    qemu_put_8s (f, &s->csp_index);
1130 85571bc7 bellard
    qemu_put_buffer (f, s->csp_reg83, 4);
1131 85571bc7 bellard
    qemu_put_be32s (f, &s->csp_reg83r);
1132 85571bc7 bellard
    qemu_put_be32s (f, &s->csp_reg83w);
1133 85571bc7 bellard
1134 85571bc7 bellard
    qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1135 85571bc7 bellard
    qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1136 85571bc7 bellard
    qemu_put_8s (f, &s->test_reg);
1137 85571bc7 bellard
    qemu_put_8s (f, &s->last_read_byte);
1138 85571bc7 bellard
1139 85571bc7 bellard
    qemu_put_be32s (f, &s->nzero);
1140 85571bc7 bellard
    qemu_put_be32s (f, &s->left_till_irq);
1141 85571bc7 bellard
    qemu_put_be32s (f, &s->dma_running);
1142 85571bc7 bellard
    qemu_put_be32s (f, &s->bytes_per_second);
1143 85571bc7 bellard
    qemu_put_be32s (f, &s->align);
1144 85571bc7 bellard
1145 85571bc7 bellard
    qemu_put_be32s (f, &s->mixer_nreg);
1146 85571bc7 bellard
    qemu_put_buffer (f, s->mixer_regs, 256);
1147 d75d9f6b bellard
}
1148 d75d9f6b bellard
1149 85571bc7 bellard
static int SB_load (QEMUFile *f, void *opaque, int version_id)
1150 d75d9f6b bellard
{
1151 85571bc7 bellard
    SB16State *s = opaque;
1152 85571bc7 bellard
1153 85571bc7 bellard
    if (version_id != 1)
1154 85571bc7 bellard
        return -EINVAL;
1155 85571bc7 bellard
1156 85571bc7 bellard
    qemu_get_be32s (f, &s->irq);
1157 85571bc7 bellard
    qemu_get_be32s (f, &s->dma);
1158 85571bc7 bellard
    qemu_get_be32s (f, &s->hdma);
1159 85571bc7 bellard
    qemu_get_be32s (f, &s->port);
1160 85571bc7 bellard
    qemu_get_be32s (f, &s->ver);
1161 85571bc7 bellard
    qemu_get_be32s (f, &s->in_index);
1162 85571bc7 bellard
    qemu_get_be32s (f, &s->out_data_len);
1163 85571bc7 bellard
    qemu_get_be32s (f, &s->fmt_stereo);
1164 85571bc7 bellard
    qemu_get_be32s (f, &s->fmt_signed);
1165 85571bc7 bellard
    qemu_get_be32s (f, &s->fmt_bits);
1166 85571bc7 bellard
    qemu_get_be32s (f, &s->fmt);
1167 85571bc7 bellard
    qemu_get_be32s (f, &s->dma_auto);
1168 85571bc7 bellard
    qemu_get_be32s (f, &s->block_size);
1169 85571bc7 bellard
    qemu_get_be32s (f, &s->fifo);
1170 85571bc7 bellard
    qemu_get_be32s (f, &s->freq);
1171 85571bc7 bellard
    qemu_get_be32s (f, &s->time_const);
1172 85571bc7 bellard
    qemu_get_be32s (f, &s->speaker);
1173 85571bc7 bellard
    qemu_get_be32s (f, &s->needed_bytes);
1174 85571bc7 bellard
    qemu_get_be32s (f, &s->cmd);
1175 85571bc7 bellard
    qemu_get_be32s (f, &s->use_hdma);
1176 85571bc7 bellard
    qemu_get_be32s (f, &s->highspeed);
1177 85571bc7 bellard
    qemu_get_be32s (f, &s->can_write);
1178 85571bc7 bellard
    qemu_get_be32s (f, &s->v2x6);
1179 85571bc7 bellard
1180 85571bc7 bellard
    qemu_get_8s (f, &s->csp_param);
1181 85571bc7 bellard
    qemu_get_8s (f, &s->csp_value);
1182 85571bc7 bellard
    qemu_get_8s (f, &s->csp_mode);
1183 85571bc7 bellard
    qemu_get_8s (f, &s->csp_param);
1184 85571bc7 bellard
    qemu_get_buffer (f, s->csp_regs, 256);
1185 85571bc7 bellard
    qemu_get_8s (f, &s->csp_index);
1186 85571bc7 bellard
    qemu_get_buffer (f, s->csp_reg83, 4);
1187 85571bc7 bellard
    qemu_get_be32s (f, &s->csp_reg83r);
1188 85571bc7 bellard
    qemu_get_be32s (f, &s->csp_reg83w);
1189 85571bc7 bellard
1190 85571bc7 bellard
    qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1191 85571bc7 bellard
    qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1192 85571bc7 bellard
    qemu_get_8s (f, &s->test_reg);
1193 85571bc7 bellard
    qemu_get_8s (f, &s->last_read_byte);
1194 85571bc7 bellard
1195 85571bc7 bellard
    qemu_get_be32s (f, &s->nzero);
1196 85571bc7 bellard
    qemu_get_be32s (f, &s->left_till_irq);
1197 85571bc7 bellard
    qemu_get_be32s (f, &s->dma_running);
1198 85571bc7 bellard
    qemu_get_be32s (f, &s->bytes_per_second);
1199 85571bc7 bellard
    qemu_get_be32s (f, &s->align);
1200 85571bc7 bellard
1201 85571bc7 bellard
    qemu_get_be32s (f, &s->mixer_nreg);
1202 85571bc7 bellard
    qemu_get_buffer (f, s->mixer_regs, 256);
1203 85571bc7 bellard
1204 fb065187 bellard
    if (s->voice) {
1205 fb065187 bellard
        AUD_close (s->voice);
1206 fb065187 bellard
        s->voice = NULL;
1207 fb065187 bellard
    }
1208 85571bc7 bellard
1209 85571bc7 bellard
    if (s->dma_running) {
1210 85571bc7 bellard
        if (s->freq)
1211 85571bc7 bellard
            s->voice = AUD_open (s->voice, "sb16", s->freq,
1212 85571bc7 bellard
                                 1 << s->fmt_stereo, s->fmt);
1213 85571bc7 bellard
1214 85571bc7 bellard
        control (s, 1);
1215 85571bc7 bellard
        speaker (s, s->speaker);
1216 d75d9f6b bellard
    }
1217 85571bc7 bellard
    return 0;
1218 d75d9f6b bellard
}
1219 d75d9f6b bellard
1220 27503323 bellard
void SB16_init (void)
1221 27503323 bellard
{
1222 5e2a6443 bellard
    SB16State *s = &dsp;
1223 27503323 bellard
    int i;
1224 27503323 bellard
    static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1225 27503323 bellard
    static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
1226 27503323 bellard
1227 85571bc7 bellard
    s->ts = qemu_new_timer (vm_clock, SB_timer, s);
1228 85571bc7 bellard
    if (!s->ts)
1229 85571bc7 bellard
        return;
1230 85571bc7 bellard
1231 85571bc7 bellard
    s->irq = conf.irq;
1232 85571bc7 bellard
    s->dma = conf.dma;
1233 85571bc7 bellard
    s->hdma = conf.hdma;
1234 85571bc7 bellard
    s->port = conf.port;
1235 85571bc7 bellard
    s->ver = conf.ver_lo | (conf.ver_hi << 8);
1236 202a456a bellard
1237 85571bc7 bellard
    s->mixer_regs[0x80] = magic_of_irq (s->irq);
1238 85571bc7 bellard
    s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1239 85571bc7 bellard
    s->mixer_regs[0x82] = 2 << 5;
1240 85571bc7 bellard
1241 85571bc7 bellard
    s->csp_regs[5] = 1;
1242 85571bc7 bellard
    s->csp_regs[9] = 0xf8;
1243 85571bc7 bellard
1244 85571bc7 bellard
    reset_mixer (s);
1245 85571bc7 bellard
    s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1246 85571bc7 bellard
    if (!s->aux_ts)
1247 85571bc7 bellard
        return;
1248 27503323 bellard
1249 27503323 bellard
    for (i = 0; i < LENOFA (dsp_write_ports); i++) {
1250 85571bc7 bellard
        register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1251 27503323 bellard
    }
1252 27503323 bellard
1253 27503323 bellard
    for (i = 0; i < LENOFA (dsp_read_ports); i++) {
1254 85571bc7 bellard
        register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1255 27503323 bellard
    }
1256 27503323 bellard
1257 85571bc7 bellard
    register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1258 85571bc7 bellard
    register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1259 85571bc7 bellard
    register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1260 85571bc7 bellard
    register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1261 27503323 bellard
1262 85571bc7 bellard
    DMA_register_channel (s->hdma, SB_read_DMA, s);
1263 85571bc7 bellard
    DMA_register_channel (s->dma, SB_read_DMA, s);
1264 85571bc7 bellard
    s->can_write = 1;
1265 d75d9f6b bellard
1266 85571bc7 bellard
    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
1267 85571bc7 bellard
    register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1268 27503323 bellard
}