Statistics
| Branch: | Revision:

root / hw / sb16.c @ c0fe3827

History | View | Annotate | Download (34.8 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 85571bc7 bellard
static void dma_cmd8 (SB16State *s, int mask, int dma_len)
197 85571bc7 bellard
{
198 85571bc7 bellard
    s->fmt = AUD_FMT_U8;
199 85571bc7 bellard
    s->use_hdma = 0;
200 85571bc7 bellard
    s->fmt_bits = 8;
201 85571bc7 bellard
    s->fmt_signed = 0;
202 85571bc7 bellard
    s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
203 85571bc7 bellard
    if (-1 == s->time_const) {
204 85571bc7 bellard
        s->freq = 11025;
205 85571bc7 bellard
    }
206 85571bc7 bellard
    else {
207 85571bc7 bellard
        int tmp = (256 - s->time_const);
208 85571bc7 bellard
        s->freq = (1000000 + (tmp / 2)) / tmp;
209 85571bc7 bellard
    }
210 85571bc7 bellard
211 1d14ffa9 bellard
    if (dma_len != -1) {
212 15b61470 bellard
        s->block_size = dma_len << s->fmt_stereo;
213 1d14ffa9 bellard
    }
214 15b61470 bellard
    else {
215 15b61470 bellard
        /* This is apparently the only way to make both Act1/PL
216 15b61470 bellard
           and SecondReality/FC work
217 15b61470 bellard

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