| 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 |
} |
} |