Statistics
| Branch: | Revision:

root / hw / sb16.c @ 06113719

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

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