Statistics
| Branch: | Revision:

root / hw / sb16.c @ 008ff9d7

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

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