Statistics
| Branch: | Revision:

root / hw / sb16.c @ 0986ac3b

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