53 |
} conf = {5, 4, 5, 1, 5, 0x220}; |
} conf = {5, 4, 5, 1, 5, 0x220}; |
54 |
|
|
55 |
typedef struct SB16State { |
typedef struct SB16State { |
56 |
|
QEMUSoundCard card; |
57 |
int irq; |
int irq; |
58 |
int dma; |
int dma; |
59 |
int hdma; |
int hdma; |
109 |
uint8_t mixer_regs[256]; |
uint8_t mixer_regs[256]; |
110 |
} SB16State; |
} SB16State; |
111 |
|
|
|
/* XXX: suppress that and use a context */ |
|
|
static struct SB16State dsp; |
|
|
|
|
112 |
static void SB_audio_callback (void *opaque, int free); |
static void SB_audio_callback (void *opaque, int free); |
113 |
|
|
114 |
static int magic_of_irq (int irq) |
static int magic_of_irq (int irq) |
240 |
s->block_size, s->dma_auto, s->fifo, s->highspeed); |
s->block_size, s->dma_auto, s->fifo, s->highspeed); |
241 |
|
|
242 |
if (s->freq) { |
if (s->freq) { |
243 |
|
audsettings_t as; |
244 |
|
|
245 |
s->audio_free = 0; |
s->audio_free = 0; |
246 |
|
|
247 |
|
as.freq = s->freq; |
248 |
|
as.nchannels = 1 << s->fmt_stereo; |
249 |
|
as.fmt = s->fmt; |
250 |
|
|
251 |
s->voice = AUD_open_out ( |
s->voice = AUD_open_out ( |
252 |
|
&s->card, |
253 |
s->voice, |
s->voice, |
254 |
"sb16", |
"sb16", |
255 |
s, |
s, |
256 |
SB_audio_callback, |
SB_audio_callback, |
257 |
s->freq, |
&as |
|
1 << s->fmt_stereo, |
|
|
s->fmt |
|
258 |
); |
); |
259 |
} |
} |
260 |
|
|
334 |
} |
} |
335 |
|
|
336 |
if (s->freq) { |
if (s->freq) { |
337 |
|
audsettings_t as; |
338 |
|
|
339 |
s->audio_free = 0; |
s->audio_free = 0; |
340 |
|
|
341 |
|
as.freq = s->freq; |
342 |
|
as.nchannels = 1 << s->fmt_stereo; |
343 |
|
as.fmt = s->fmt; |
344 |
|
|
345 |
s->voice = AUD_open_out ( |
s->voice = AUD_open_out ( |
346 |
|
&s->card, |
347 |
s->voice, |
s->voice, |
348 |
"sb16", |
"sb16", |
349 |
s, |
s, |
350 |
SB_audio_callback, |
SB_audio_callback, |
351 |
s->freq, |
&as |
|
1 << s->fmt_stereo, |
|
|
s->fmt |
|
352 |
); |
); |
353 |
} |
} |
354 |
|
|
359 |
static inline void dsp_out_data (SB16State *s, uint8_t val) |
static inline void dsp_out_data (SB16State *s, uint8_t val) |
360 |
{ |
{ |
361 |
ldebug ("outdata %#x\n", val); |
ldebug ("outdata %#x\n", val); |
362 |
if (s->out_data_len < sizeof (s->out_data)) { |
if ((size_t) s->out_data_len < sizeof (s->out_data)) { |
363 |
s->out_data[s->out_data_len++] = val; |
s->out_data[s->out_data_len++] = val; |
364 |
} |
} |
365 |
} |
} |
1028 |
static IO_WRITE_PROTO(mixer_write_indexb) |
static IO_WRITE_PROTO(mixer_write_indexb) |
1029 |
{ |
{ |
1030 |
SB16State *s = opaque; |
SB16State *s = opaque; |
1031 |
|
(void) nport; |
1032 |
s->mixer_nreg = val; |
s->mixer_nreg = val; |
1033 |
} |
} |
1034 |
|
|
1036 |
{ |
{ |
1037 |
SB16State *s = opaque; |
SB16State *s = opaque; |
1038 |
|
|
1039 |
|
(void) nport; |
1040 |
ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val); |
ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val); |
|
if (s->mixer_nreg > sizeof (s->mixer_regs)) { |
|
|
return; |
|
|
} |
|
1041 |
|
|
1042 |
switch (s->mixer_nreg) { |
switch (s->mixer_nreg) { |
1043 |
case 0x00: |
case 0x00: |
1097 |
static IO_READ_PROTO(mixer_read) |
static IO_READ_PROTO(mixer_read) |
1098 |
{ |
{ |
1099 |
SB16State *s = opaque; |
SB16State *s = opaque; |
1100 |
|
|
1101 |
|
(void) nport; |
1102 |
#ifndef DEBUG_SB16_MOST |
#ifndef DEBUG_SB16_MOST |
1103 |
if (s->mixer_nreg != 0x82) { |
if (s->mixer_nreg != 0x82) { |
1104 |
ldebug ("mixer_read[%#x] -> %#x\n", |
ldebug ("mixer_read[%#x] -> %#x\n", |
1122 |
|
|
1123 |
while (temp) { |
while (temp) { |
1124 |
int left = dma_len - dma_pos; |
int left = dma_len - dma_pos; |
1125 |
int to_copy, copied; |
int copied; |
1126 |
|
size_t to_copy; |
1127 |
|
|
1128 |
to_copy = audio_MIN (temp, left); |
to_copy = audio_MIN (temp, left); |
1129 |
if (to_copy > sizeof(tmpbuf)) { |
if (to_copy > sizeof (tmpbuf)) { |
1130 |
to_copy = sizeof(tmpbuf); |
to_copy = sizeof (tmpbuf); |
1131 |
} |
} |
1132 |
|
|
1133 |
copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy); |
copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy); |
1320 |
qemu_get_buffer (f, s->mixer_regs, 256); |
qemu_get_buffer (f, s->mixer_regs, 256); |
1321 |
|
|
1322 |
if (s->voice) { |
if (s->voice) { |
1323 |
AUD_close_out (s->voice); |
AUD_close_out (&s->card, s->voice); |
1324 |
s->voice = NULL; |
s->voice = NULL; |
1325 |
} |
} |
1326 |
|
|
1327 |
if (s->dma_running) { |
if (s->dma_running) { |
1328 |
if (s->freq) { |
if (s->freq) { |
1329 |
|
audsettings_t as; |
1330 |
|
|
1331 |
s->audio_free = 0; |
s->audio_free = 0; |
1332 |
|
|
1333 |
|
as.freq = s->freq; |
1334 |
|
as.nchannels = 1 << s->fmt_stereo; |
1335 |
|
as.fmt = s->fmt; |
1336 |
|
|
1337 |
s->voice = AUD_open_out ( |
s->voice = AUD_open_out ( |
1338 |
|
&s->card, |
1339 |
s->voice, |
s->voice, |
1340 |
"sb16", |
"sb16", |
1341 |
s, |
s, |
1342 |
SB_audio_callback, |
SB_audio_callback, |
1343 |
s->freq, |
&as |
|
1 << s->fmt_stereo, |
|
|
s->fmt |
|
1344 |
); |
); |
1345 |
} |
} |
1346 |
|
|
1350 |
return 0; |
return 0; |
1351 |
} |
} |
1352 |
|
|
1353 |
void SB16_init (void) |
int SB16_init (AudioState *audio) |
1354 |
{ |
{ |
1355 |
SB16State *s = &dsp; |
SB16State *s; |
1356 |
int i; |
int i; |
1357 |
static const uint8_t dsp_write_ports[] = {0x6, 0xc}; |
static const uint8_t dsp_write_ports[] = {0x6, 0xc}; |
1358 |
static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf}; |
static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf}; |
1359 |
|
|
1360 |
|
if (!audio) { |
1361 |
|
dolog ("No audio state\n"); |
1362 |
|
return -1; |
1363 |
|
} |
1364 |
|
|
1365 |
|
s = qemu_mallocz (sizeof (*s)); |
1366 |
|
if (!s) { |
1367 |
|
dolog ("Could not allocate memory for SB16 (%d bytes)\n", |
1368 |
|
sizeof (*s)); |
1369 |
|
return -1; |
1370 |
|
} |
1371 |
|
|
1372 |
s->cmd = -1; |
s->cmd = -1; |
1373 |
s->irq = conf.irq; |
s->irq = conf.irq; |
1374 |
s->dma = conf.dma; |
s->dma = conf.dma; |
1386 |
reset_mixer (s); |
reset_mixer (s); |
1387 |
s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s); |
s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s); |
1388 |
if (!s->aux_ts) { |
if (!s->aux_ts) { |
1389 |
dolog ("Can not create auxiliary timer\n"); |
dolog ("warning: Could not create auxiliary timer\n"); |
1390 |
} |
} |
1391 |
|
|
1392 |
for (i = 0; i < LENOFA (dsp_write_ports); i++) { |
for (i = 0; i < LENOFA (dsp_write_ports); i++) { |
1407 |
s->can_write = 1; |
s->can_write = 1; |
1408 |
|
|
1409 |
register_savevm ("sb16", 0, 1, SB_save, SB_load, s); |
register_savevm ("sb16", 0, 1, SB_save, SB_load, s); |
1410 |
|
AUD_register_card (audio, "sb16", &s->card); |
1411 |
|
return 0; |
1412 |
} |
} |