Statistics
| Branch: | Revision:

root / hw / sb16.c @ feea13e1

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

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