Statistics
| Branch: | Revision:

root / hw / sb16.c @ df97b920

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

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