Statistics
| Branch: | Revision:

root / hw / sb16.c @ d8becc35

History | View | Annotate | Download (36.1 kB)

1 27503323 bellard
/*
2 27503323 bellard
 * QEMU Soundblaster 16 emulation
3 1d14ffa9 bellard
 *
4 1d14ffa9 bellard
 * Copyright (c) 2003-2005 Vassili Karpov (malc)
5 1d14ffa9 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 87ecb68b pbrook
#include "hw.h"
25 87ecb68b pbrook
#include "audiodev.h"
26 87ecb68b pbrook
#include "audio/audio.h"
27 87ecb68b pbrook
#include "isa.h"
28 f7b4f61f Gerd Hoffmann
#include "qdev.h"
29 87ecb68b pbrook
#include "qemu-timer.h"
30 057fa65c malc
#include "host-utils.h"
31 27503323 bellard
32 fb065187 bellard
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
33 15b61470 bellard
34 15b61470 bellard
/* #define DEBUG */
35 15b61470 bellard
/* #define DEBUG_SB16_MOST */
36 15b61470 bellard
37 fb065187 bellard
#ifdef DEBUG
38 fb065187 bellard
#define ldebug(...) dolog (__VA_ARGS__)
39 fb065187 bellard
#else
40 fb065187 bellard
#define ldebug(...)
41 fb065187 bellard
#endif
42 fb065187 bellard
43 85571bc7 bellard
#define IO_READ_PROTO(name)                             \
44 7d977de7 bellard
    uint32_t name (void *opaque, uint32_t nport)
45 85571bc7 bellard
#define IO_WRITE_PROTO(name)                                    \
46 7d977de7 bellard
    void name (void *opaque, uint32_t nport, uint32_t val)
47 27503323 bellard
48 85571bc7 bellard
static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
49 d329a6fb bellard
50 5e2a6443 bellard
typedef struct SB16State {
51 f7b4f61f Gerd Hoffmann
    ISADevice dev;
52 c0fe3827 bellard
    QEMUSoundCard card;
53 3a38d437 Jes Sorensen
    qemu_irq pic;
54 f7b4f61f Gerd Hoffmann
    uint32_t irq;
55 f7b4f61f Gerd Hoffmann
    uint32_t dma;
56 f7b4f61f Gerd Hoffmann
    uint32_t hdma;
57 f7b4f61f Gerd Hoffmann
    uint32_t port;
58 f7b4f61f Gerd Hoffmann
    uint32_t ver;
59 85571bc7 bellard
60 27503323 bellard
    int in_index;
61 27503323 bellard
    int out_data_len;
62 27503323 bellard
    int fmt_stereo;
63 27503323 bellard
    int fmt_signed;
64 27503323 bellard
    int fmt_bits;
65 85571bc7 bellard
    audfmt_e fmt;
66 27503323 bellard
    int dma_auto;
67 85571bc7 bellard
    int block_size;
68 27503323 bellard
    int fifo;
69 27503323 bellard
    int freq;
70 27503323 bellard
    int time_const;
71 27503323 bellard
    int speaker;
72 27503323 bellard
    int needed_bytes;
73 27503323 bellard
    int cmd;
74 27503323 bellard
    int use_hdma;
75 85571bc7 bellard
    int highspeed;
76 85571bc7 bellard
    int can_write;
77 27503323 bellard
78 27503323 bellard
    int v2x6;
79 27503323 bellard
80 85571bc7 bellard
    uint8_t csp_param;
81 85571bc7 bellard
    uint8_t csp_value;
82 85571bc7 bellard
    uint8_t csp_mode;
83 85571bc7 bellard
    uint8_t csp_regs[256];
84 85571bc7 bellard
    uint8_t csp_index;
85 85571bc7 bellard
    uint8_t csp_reg83[4];
86 85571bc7 bellard
    int csp_reg83r;
87 85571bc7 bellard
    int csp_reg83w;
88 85571bc7 bellard
89 d75d9f6b bellard
    uint8_t in2_data[10];
90 85571bc7 bellard
    uint8_t out_data[50];
91 85571bc7 bellard
    uint8_t test_reg;
92 85571bc7 bellard
    uint8_t last_read_byte;
93 85571bc7 bellard
    int nzero;
94 27503323 bellard
95 27503323 bellard
    int left_till_irq;
96 27503323 bellard
97 85571bc7 bellard
    int dma_running;
98 85571bc7 bellard
    int bytes_per_second;
99 85571bc7 bellard
    int align;
100 1d14ffa9 bellard
    int audio_free;
101 1d14ffa9 bellard
    SWVoiceOut *voice;
102 85571bc7 bellard
103 1d14ffa9 bellard
    QEMUTimer *aux_ts;
104 5e2a6443 bellard
    /* mixer state */
105 5e2a6443 bellard
    int mixer_nreg;
106 202a456a bellard
    uint8_t mixer_regs[256];
107 5e2a6443 bellard
} SB16State;
108 27503323 bellard
109 1d14ffa9 bellard
static void SB_audio_callback (void *opaque, int free);
110 1d14ffa9 bellard
111 85571bc7 bellard
static int magic_of_irq (int irq)
112 85571bc7 bellard
{
113 85571bc7 bellard
    switch (irq) {
114 85571bc7 bellard
    case 5:
115 85571bc7 bellard
        return 2;
116 85571bc7 bellard
    case 7:
117 85571bc7 bellard
        return 4;
118 85571bc7 bellard
    case 9:
119 85571bc7 bellard
        return 1;
120 85571bc7 bellard
    case 10:
121 85571bc7 bellard
        return 8;
122 85571bc7 bellard
    default:
123 85571bc7 bellard
        dolog ("bad irq %d\n", irq);
124 85571bc7 bellard
        return 2;
125 85571bc7 bellard
    }
126 85571bc7 bellard
}
127 85571bc7 bellard
128 85571bc7 bellard
static int irq_of_magic (int magic)
129 85571bc7 bellard
{
130 85571bc7 bellard
    switch (magic) {
131 85571bc7 bellard
    case 1:
132 85571bc7 bellard
        return 9;
133 85571bc7 bellard
    case 2:
134 85571bc7 bellard
        return 5;
135 85571bc7 bellard
    case 4:
136 85571bc7 bellard
        return 7;
137 85571bc7 bellard
    case 8:
138 85571bc7 bellard
        return 10;
139 85571bc7 bellard
    default:
140 85571bc7 bellard
        dolog ("bad irq magic %d\n", magic);
141 85571bc7 bellard
        return -1;
142 85571bc7 bellard
    }
143 85571bc7 bellard
}
144 85571bc7 bellard
145 85571bc7 bellard
#if 0
146 5e2a6443 bellard
static void log_dsp (SB16State *dsp)
147 5e2a6443 bellard
{
148 85571bc7 bellard
    ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
149 85571bc7 bellard
            dsp->fmt_stereo ? "Stereo" : "Mono",
150 85571bc7 bellard
            dsp->fmt_signed ? "Signed" : "Unsigned",
151 85571bc7 bellard
            dsp->fmt_bits,
152 85571bc7 bellard
            dsp->dma_auto ? "Auto" : "Single",
153 85571bc7 bellard
            dsp->block_size,
154 85571bc7 bellard
            dsp->freq,
155 85571bc7 bellard
            dsp->time_const,
156 85571bc7 bellard
            dsp->speaker);
157 85571bc7 bellard
}
158 85571bc7 bellard
#endif
159 85571bc7 bellard
160 85571bc7 bellard
static void speaker (SB16State *s, int on)
161 85571bc7 bellard
{
162 85571bc7 bellard
    s->speaker = on;
163 85571bc7 bellard
    /* AUD_enable (s->voice, on); */
164 27503323 bellard
}
165 27503323 bellard
166 85571bc7 bellard
static void control (SB16State *s, int hold)
167 27503323 bellard
{
168 85571bc7 bellard
    int dma = s->use_hdma ? s->hdma : s->dma;
169 85571bc7 bellard
    s->dma_running = hold;
170 85571bc7 bellard
171 85571bc7 bellard
    ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
172 85571bc7 bellard
173 27503323 bellard
    if (hold) {
174 85571bc7 bellard
        DMA_hold_DREQ (dma);
175 1d14ffa9 bellard
        AUD_set_active_out (s->voice, 1);
176 27503323 bellard
    }
177 27503323 bellard
    else {
178 85571bc7 bellard
        DMA_release_DREQ (dma);
179 1d14ffa9 bellard
        AUD_set_active_out (s->voice, 0);
180 27503323 bellard
    }
181 27503323 bellard
}
182 27503323 bellard
183 85571bc7 bellard
static void aux_timer (void *opaque)
184 27503323 bellard
{
185 85571bc7 bellard
    SB16State *s = opaque;
186 85571bc7 bellard
    s->can_write = 1;
187 3a38d437 Jes Sorensen
    qemu_irq_raise (s->pic);
188 85571bc7 bellard
}
189 85571bc7 bellard
190 85571bc7 bellard
#define DMA8_AUTO 1
191 85571bc7 bellard
#define DMA8_HIGH 2
192 85571bc7 bellard
193 feea13e1 bellard
static void continue_dma8 (SB16State *s)
194 feea13e1 bellard
{
195 feea13e1 bellard
    if (s->freq > 0) {
196 1ea879e5 malc
        struct audsettings as;
197 feea13e1 bellard
198 feea13e1 bellard
        s->audio_free = 0;
199 feea13e1 bellard
200 feea13e1 bellard
        as.freq = s->freq;
201 feea13e1 bellard
        as.nchannels = 1 << s->fmt_stereo;
202 feea13e1 bellard
        as.fmt = s->fmt;
203 d929eba5 bellard
        as.endianness = 0;
204 feea13e1 bellard
205 feea13e1 bellard
        s->voice = AUD_open_out (
206 feea13e1 bellard
            &s->card,
207 feea13e1 bellard
            s->voice,
208 feea13e1 bellard
            "sb16",
209 feea13e1 bellard
            s,
210 feea13e1 bellard
            SB_audio_callback,
211 d929eba5 bellard
            &as
212 feea13e1 bellard
            );
213 feea13e1 bellard
    }
214 feea13e1 bellard
215 feea13e1 bellard
    control (s, 1);
216 feea13e1 bellard
}
217 feea13e1 bellard
218 85571bc7 bellard
static void dma_cmd8 (SB16State *s, int mask, int dma_len)
219 85571bc7 bellard
{
220 85571bc7 bellard
    s->fmt = AUD_FMT_U8;
221 85571bc7 bellard
    s->use_hdma = 0;
222 85571bc7 bellard
    s->fmt_bits = 8;
223 85571bc7 bellard
    s->fmt_signed = 0;
224 85571bc7 bellard
    s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
225 85571bc7 bellard
    if (-1 == s->time_const) {
226 feea13e1 bellard
        if (s->freq <= 0)
227 feea13e1 bellard
            s->freq = 11025;
228 85571bc7 bellard
    }
229 85571bc7 bellard
    else {
230 85571bc7 bellard
        int tmp = (256 - s->time_const);
231 85571bc7 bellard
        s->freq = (1000000 + (tmp / 2)) / tmp;
232 85571bc7 bellard
    }
233 85571bc7 bellard
234 1d14ffa9 bellard
    if (dma_len != -1) {
235 15b61470 bellard
        s->block_size = dma_len << s->fmt_stereo;
236 1d14ffa9 bellard
    }
237 15b61470 bellard
    else {
238 15b61470 bellard
        /* This is apparently the only way to make both Act1/PL
239 15b61470 bellard
           and SecondReality/FC work
240 15b61470 bellard

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