/[qemu]/qemu/hw/sb16.c
ViewVC logotype

Diff of /qemu/hw/sb16.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.10 by bellard, Sat Oct 9 17:20:54 2004 UTC revision 1.11 by bellard, Sun Nov 7 18:04:02 2004 UTC
# Line 1  Line 1 
1  /*  /*
2   * QEMU Soundblaster 16 emulation   * QEMU Soundblaster 16 emulation
3   *   *
4   * Copyright (c) 2003 Vassili Karpov (malc)   * Copyright (c) 2003-2004 Vassili Karpov (malc)
5   *   *
6   * Permission is hereby granted, free of charge, to any person obtaining a copy   * Permission is hereby granted, free of charge, to any person obtaining a copy
7   * of this software and associated documentation files (the "Software"), to deal   * of this software and associated documentation files (the "Software"), to deal
# Line 23  Line 23 
23   */   */
24  #include "vl.h"  #include "vl.h"
25    
26  #define MIN(a, b) ((a)>(b)?(b):(a))  /* #define DEBUG */
27  #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))  #define AUDIO_CAP "sb16"
28    #include "audio/audio.h"
 #define dolog(...) fprintf (stderr, "sb16: " __VA_ARGS__);  
29    
30  /* #define DEBUG_SB16 */  #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
31    
32  #ifdef DEBUG_SB16  /* #define DEBUG_SB16_MOST */
 #define lwarn(...) fprintf (stderr, "sb16: " __VA_ARGS__)  
 #define linfo(...) fprintf (stderr, "sb16: " __VA_ARGS__)  
 #define ldebug(...) fprintf (stderr, "sb16: " __VA_ARGS__)  
 #else  
 #define lwarn(...)  
 #define linfo(...)  
 #define ldebug(...)  
 #endif  
33    
34  #define IO_READ_PROTO(name) \  #define IO_READ_PROTO(name)                             \
35      uint32_t name (void *opaque, uint32_t nport)      uint32_t name (void *opaque, uint32_t nport)
36  #define IO_WRITE_PROTO(name) \  #define IO_WRITE_PROTO(name)                                    \
37      void name (void *opaque, uint32_t nport, uint32_t val)      void name (void *opaque, uint32_t nport, uint32_t val)
38    
39  static const char e3[] =  static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
     "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992\0"  
     "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1994-1997";  
     /* "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1994."; */  
40    
41  static struct {  static struct {
42      int ver_lo;      int ver_lo;
# Line 57  static struct { Line 45  static struct {
45      int dma;      int dma;
46      int hdma;      int hdma;
47      int port;      int port;
48      int mix_block;  } conf = {5, 4, 5, 1, 5, 0x220};
 } sb = {5, 4, 5, 1, 5, 0x220, -1};  
   
 static int mix_block, noirq;  
49    
50  typedef struct SB16State {  typedef struct SB16State {
51        int irq;
52        int dma;
53        int hdma;
54        int port;
55        int ver;
56    
57      int in_index;      int in_index;
58      int out_data_len;      int out_data_len;
59      int fmt_stereo;      int fmt_stereo;
60      int fmt_signed;      int fmt_signed;
61      int fmt_bits;      int fmt_bits;
62        audfmt_e fmt;
63      int dma_auto;      int dma_auto;
64      int dma_buffer_size;      int block_size;
65      int fifo;      int fifo;
66      int freq;      int freq;
67      int time_const;      int time_const;
68      int speaker;      int speaker;
69      int needed_bytes;      int needed_bytes;
70      int cmd;      int cmd;
     int dma_pos;  
71      int use_hdma;      int use_hdma;
72        int highspeed;
73        int can_write;
74    
75      int v2x6;      int v2x6;
76    
77        uint8_t csp_param;
78        uint8_t csp_value;
79        uint8_t csp_mode;
80        uint8_t csp_regs[256];
81        uint8_t csp_index;
82        uint8_t csp_reg83[4];
83        int csp_reg83r;
84        int csp_reg83w;
85    
86      uint8_t in2_data[10];      uint8_t in2_data[10];
87      uint8_t out_data[1024];      uint8_t out_data[50];
88        uint8_t test_reg;
89        uint8_t last_read_byte;
90        int nzero;
91    
92      int left_till_irq;      int left_till_irq;
     uint64_t nzero;  
     uint8_t last_read_byte;  
     uint8_t test_reg;  
93    
94        int dma_running;
95        int bytes_per_second;
96        int align;
97        SWVoice *voice;
98    
99        QEMUTimer *ts, *aux_ts;
100      /* mixer state */      /* mixer state */
101      int mixer_nreg;      int mixer_nreg;
102      uint8_t mixer_regs[256];      uint8_t mixer_regs[256];
# Line 97  typedef struct SB16State { Line 105  typedef struct SB16State {
105  /* XXX: suppress that and use a context */  /* XXX: suppress that and use a context */
106  static struct SB16State dsp;  static struct SB16State dsp;
107    
108    static int magic_of_irq (int irq)
109    {
110        switch (irq) {
111        case 5:
112            return 2;
113        case 7:
114            return 4;
115        case 9:
116            return 1;
117        case 10:
118            return 8;
119        default:
120            dolog ("bad irq %d\n", irq);
121            return 2;
122        }
123    }
124    
125    static int irq_of_magic (int magic)
126    {
127        switch (magic) {
128        case 1:
129            return 9;
130        case 2:
131            return 5;
132        case 4:
133            return 7;
134        case 8:
135            return 10;
136        default:
137            dolog ("bad irq magic %d\n", magic);
138            return -1;
139        }
140    }
141    
142    #if 0
143  static void log_dsp (SB16State *dsp)  static void log_dsp (SB16State *dsp)
144  {  {
145      ldebug ("%c:%c:%d:%c:dmabuf=%d:pos=%d:freq=%d:timeconst=%d:speaker=%d\n",      ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
146             dsp->fmt_stereo ? 'S' : 'M',              dsp->fmt_stereo ? "Stereo" : "Mono",
147             dsp->fmt_signed ? 'S' : 'U',              dsp->fmt_signed ? "Signed" : "Unsigned",
148             dsp->fmt_bits,              dsp->fmt_bits,
149             dsp->dma_auto ? 'a' : 's',              dsp->dma_auto ? "Auto" : "Single",
150             dsp->dma_buffer_size,              dsp->block_size,
151             dsp->dma_pos,              dsp->freq,
152             dsp->freq,              dsp->time_const,
153             dsp->time_const,              dsp->speaker);
154             dsp->speaker);  }
155    #endif
156    
157    static void speaker (SB16State *s, int on)
158    {
159        s->speaker = on;
160        /* AUD_enable (s->voice, on); */
161  }  }
162    
163  static void control (int hold)  static void control (SB16State *s, int hold)
164  {  {
165      linfo ("%d high %d\n", hold, dsp.use_hdma);      int dma = s->use_hdma ? s->hdma : s->dma;
166        s->dma_running = hold;
167    
168        ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
169    
170      if (hold) {      if (hold) {
171          if (dsp.use_hdma)          DMA_hold_DREQ (dma);
172              DMA_hold_DREQ (sb.hdma);          AUD_enable (s->voice, 1);
         else  
             DMA_hold_DREQ (sb.dma);  
173      }      }
174      else {      else {
175          if (dsp.use_hdma)          DMA_release_DREQ (dma);
176              DMA_release_DREQ (sb.hdma);          AUD_enable (s->voice, 0);
         else  
             DMA_release_DREQ (sb.dma);  
177      }      }
178  }  }
179    
180  static void dma_cmd (uint8_t cmd, uint8_t d0, int dma_len)  static void aux_timer (void *opaque)
181  {  {
182      int bps;      SB16State *s = opaque;
183      audfmt_e fmt;      s->can_write = 1;
184        pic_set_irq (s->irq, 1);
185    }
186    
187    #define DMA8_AUTO 1
188    #define DMA8_HIGH 2
189    
190    static void dma_cmd8 (SB16State *s, int mask, int dma_len)
191    {
192        s->fmt = AUD_FMT_U8;
193        s->use_hdma = 0;
194        s->fmt_bits = 8;
195        s->fmt_signed = 0;
196        s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
197        if (-1 == s->time_const) {
198            s->freq = 11025;
199        }
200        else {
201            int tmp = (256 - s->time_const);
202            s->freq = (1000000 + (tmp / 2)) / tmp;
203        }
204    
205        if (-1 != dma_len)
206            s->block_size = dma_len + 1;
207    
208      dsp.use_hdma = cmd < 0xc0;      s->freq >>= s->fmt_stereo;
209      dsp.fifo = (cmd >> 1) & 1;      s->left_till_irq = s->block_size;
210      dsp.dma_auto = (cmd >> 2) & 1;      s->bytes_per_second = (s->freq << s->fmt_stereo);
211        /* s->highspeed = (mask & DMA8_HIGH) != 0; */
212        s->dma_auto = (mask & DMA8_AUTO) != 0;
213        s->align = (1 << s->fmt_stereo) - 1;
214    
215        ldebug ("freq %d, stereo %d, sign %d, bits %d, "
216                "dma %d, auto %d, fifo %d, high %d\n",
217                s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
218                s->block_size, s->dma_auto, s->fifo, s->highspeed);
219    
220        if (s->freq)
221            s->voice = AUD_open (s->voice, "sb16", s->freq,
222                                 1 << s->fmt_stereo, s->fmt);
223    
224        control (s, 1);
225        speaker (s, 1);
226    }
227    
228    static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
229    {
230        s->use_hdma = cmd < 0xc0;
231        s->fifo = (cmd >> 1) & 1;
232        s->dma_auto = (cmd >> 2) & 1;
233        s->fmt_signed = (d0 >> 4) & 1;
234        s->fmt_stereo = (d0 >> 5) & 1;
235    
236      switch (cmd >> 4) {      switch (cmd >> 4) {
237      case 11:      case 11:
238          dsp.fmt_bits = 16;          s->fmt_bits = 16;
239          break;          break;
240    
241      case 12:      case 12:
242          dsp.fmt_bits = 8;          s->fmt_bits = 8;
243          break;          break;
244      }      }
245    
246      dsp.fmt_signed = (d0 >> 4) & 1;      if (-1 != s->time_const) {
247      dsp.fmt_stereo = (d0 >> 5) & 1;  #if 1
248            int tmp = 256 - s->time_const;
249      if (-1 != dsp.time_const) {          s->freq = (1000000 + (tmp / 2)) / tmp;
250          int tmp;  #else
251            /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
252          tmp = 256 - dsp.time_const;          s->freq = 1000000 / ((255 - s->time_const));
253          dsp.freq = (1000000 + (tmp / 2)) / tmp;  #endif
254            s->time_const = -1;
255      }      }
     bps = 1 << (16 == dsp.fmt_bits);  
   
     if (-1 != dma_len)  
         dsp.dma_buffer_size = (dma_len + 1) * bps;  
256    
257      linfo ("frequency %d, stereo %d, signed %d, bits %d, size %d, auto %d\n",      s->block_size = dma_len + 1;
258             dsp.freq, dsp.fmt_stereo, dsp.fmt_signed, dsp.fmt_bits,      s->block_size <<= (s->fmt_bits == 16);
259             dsp.dma_buffer_size, dsp.dma_auto);      if (!s->dma_auto)           /* Miles Sound System ? */
260            s->block_size <<= s->fmt_stereo;
261      if (16 == dsp.fmt_bits) {  
262          if (dsp.fmt_signed) {      ldebug ("freq %d, stereo %d, sign %d, bits %d, "
263              fmt = AUD_FMT_S16;              "dma %d, auto %d, fifo %d, high %d\n",
264                s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
265                s->block_size, s->dma_auto, s->fifo, s->highspeed);
266    
267        if (16 == s->fmt_bits) {
268            if (s->fmt_signed) {
269                s->fmt = AUD_FMT_S16;
270          }          }
271          else {          else {
272              fmt = AUD_FMT_U16;              s->fmt = AUD_FMT_U16;
273          }          }
274      }      }
275      else {      else {
276          if (dsp.fmt_signed) {          if (s->fmt_signed) {
277              fmt = AUD_FMT_S8;              s->fmt = AUD_FMT_S8;
278          }          }
279          else {          else {
280              fmt = AUD_FMT_U8;              s->fmt = AUD_FMT_U8;
281          }          }
282      }      }
283    
284      dsp.dma_pos = 0;      s->left_till_irq = s->block_size;
     dsp.left_till_irq = dsp.dma_buffer_size;  
285    
286      if (sb.mix_block) {      s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
287          mix_block = sb.mix_block;      s->highspeed = 0;
288      }      s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
     else {  
         int align;  
289    
290          align = bps << dsp.fmt_stereo;      if (s->freq)
291          mix_block = ((dsp.freq * align) / 100) & ~(align - 1);          s->voice = AUD_open (s->voice, "sb16", s->freq,
292      }                               1 << s->fmt_stereo, s->fmt);
293    
294      if (dsp.freq)      control (s, 1);
295      AUD_reset (dsp.freq, 1 << dsp.fmt_stereo, fmt);      speaker (s, 1);
     control (1);  
     dsp.speaker = 1;  
296  }  }
297    
298  static inline void dsp_out_data(SB16State *dsp, int val)  static inline void dsp_out_data (SB16State *s, uint8_t val)
299  {  {
300      if (dsp->out_data_len < sizeof(dsp->out_data))      ldebug ("outdata %#x\n", val);
301          dsp->out_data[dsp->out_data_len++] = val;      if (s->out_data_len < sizeof (s->out_data))
302            s->out_data[s->out_data_len++] = val;
303  }  }
304    
305  static inline uint8_t dsp_get_data(SB16State *dsp)  static inline uint8_t dsp_get_data (SB16State *s)
306  {  {
307      if (dsp->in_index)      if (s->in_index)
308          return dsp->in2_data[--dsp->in_index];          return s->in2_data[--s->in_index];
309      else      else {
310            dolog ("buffer underflow\n");
311          return 0;          return 0;
312        }
313  }  }
314    
315  static void command (SB16State *dsp, uint8_t cmd)  static void command (SB16State *s, uint8_t cmd)
316  {  {
317      linfo ("command: %#x\n", cmd);      ldebug ("command %#x\n", cmd);
318    
319      if (cmd > 0xaf && cmd < 0xd0) {      if (cmd > 0xaf && cmd < 0xd0) {
320          if (cmd & 8)          if (cmd & 8) {
321              goto error;              dolog ("ADC not yet supported (command %#x)\n", cmd);
322            }
323    
324          switch (cmd >> 4) {          switch (cmd >> 4) {
325          case 11:          case 11:
326          case 12:          case 12:
327              break;              break;
328          default:          default:
329              dolog ("command: %#x wrong bits specification\n", cmd);              dolog ("%#x wrong bits\n", cmd);
             goto error;  
330          }          }
331          dsp->needed_bytes = 3;          s->needed_bytes = 3;
332      }      }
333      else {      else {
334          switch (cmd) {          switch (cmd) {
         case 0x00:  
         case 0xe7:  
             /* IMS uses those when probing for sound devices */  
             return;  
   
335          case 0x03:          case 0x03:
336                dsp_out_data (s, 0x10); /* s->csp_param); */
337                goto warn;
338    
339          case 0x04:          case 0x04:
340              dsp_out_data (dsp, 0);              s->needed_bytes = 1;
341              return;              goto warn;
342    
343          case 0x05:          case 0x05:
344              dsp->needed_bytes = 2;              s->needed_bytes = 2;
345              break;              goto warn;
346    
347            case 0x08:
348                /* __asm__ ("int3"); */
349                goto warn;
350    
351          case 0x0e:          case 0x0e:
352              dsp->needed_bytes = 2;              s->needed_bytes = 2;
353              break;              goto warn;
354    
355            case 0x09:
356                dsp_out_data (s, 0xf8);
357                goto warn;
358    
359          case 0x0f:          case 0x0f:
360              dsp->needed_bytes = 1;              s->needed_bytes = 1;
361              break;              goto warn;
362    
363          case 0x10:          case 0x10:
364              dsp->needed_bytes = 1;              s->needed_bytes = 1;
365              break;              goto warn;
366    
367          case 0x14:          case 0x14:
368              dsp->needed_bytes = 2;              s->needed_bytes = 2;
369              dsp->dma_buffer_size = 0;              s->block_size = 0;
370              break;              break;
371    
372          case 0x20:          case 0x20:              /* Direct ADC, Juice/PL */
373              dsp_out_data(dsp, 0xff);              dsp_out_data (s, 0xff);
374              break;              goto warn;
375    
376          case 0x35:          case 0x35:
377              lwarn ("MIDI commands not implemented\n");              dolog ("MIDI command(0x35) not implemented\n");
378              break;              break;
379    
380          case 0x40:          case 0x40:
381              dsp->freq = -1;              s->freq = -1;
382              dsp->time_const = -1;              s->time_const = -1;
383              dsp->needed_bytes = 1;              s->needed_bytes = 1;
384              break;              break;
385    
386          case 0x41:          case 0x41:
387          case 0x42:              s->freq = -1;
388              dsp->freq = -1;              s->time_const = -1;
389              dsp->time_const = -1;              s->needed_bytes = 2;
             dsp->needed_bytes = 2;  
390              break;              break;
391    
392            case 0x42:
393                s->freq = -1;
394                s->time_const = -1;
395                s->needed_bytes = 2;
396                goto warn;
397    
398          case 0x45:          case 0x45:
399              dsp_out_data (dsp, 0xaa);              dsp_out_data (s, 0xaa);
400                goto warn;
401    
402          case 0x47:                /* Continue Auto-Initialize DMA 16bit */          case 0x47:                /* Continue Auto-Initialize DMA 16bit */
403              break;              break;
404    
405          case 0x48:          case 0x48:
406              dsp->needed_bytes = 2;              s->needed_bytes = 2;
407              break;              break;
408    
         case 0x27:                /* ????????? */  
         case 0x4e:  
             return;  
   
409          case 0x80:          case 0x80:
410              cmd = -1;              s->needed_bytes = 2;
411              break;              break;
412    
413          case 0x90:          case 0x90:
414          case 0x91:          case 0x91:
415              {              dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
416                  uint8_t d0;              break;
   
                 d0 = 4;  
                 /* if (dsp->fmt_signed) d0 |= 16; */  
                 /* if (dsp->fmt_stereo) d0 |= 32; */  
                 dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);  
                 cmd = -1;  
                 break;  
             }  
417    
418          case 0xd0:                /* XXX */          case 0xd0:              /* halt DMA operation. 8bit */
419              control (0);              control (s, 0);
420              return;              break;
421    
422          case 0xd1:          case 0xd1:              /* speaker on */
423              dsp->speaker = 1;              speaker (s, 1);
424              break;              break;
425    
426          case 0xd3:          case 0xd3:              /* speaker off */
427              dsp->speaker = 0;              speaker (s, 0);
428              return;              break;
429    
430          case 0xd4:          case 0xd4:              /* continue DMA operation. 8bit */
431              control (1);              control (s, 1);
432              break;              break;
433    
434          case 0xd5:          case 0xd5:              /* halt DMA operation. 16bit */
435              control (0);              control (s, 0);
436              break;              break;
437    
438          case 0xd6:          case 0xd6:              /* continue DMA operation. 16bit */
439              control (1);              control (s, 1);
440              break;              break;
441    
442          case 0xd9:          case 0xd9:              /* exit auto-init DMA after this block. 16bit */
443              control (0);              s->dma_auto = 0;
444              dsp->dma_auto = 0;              break;
             return;  
445    
446          case 0xda:          case 0xda:              /* exit auto-init DMA after this block. 8bit */
447              control (0);              s->dma_auto = 0;
             dsp->dma_auto = 0;  
448              break;              break;
449    
450          case 0xe0:          case 0xe0:
451              dsp->needed_bytes = 1;              s->needed_bytes = 1;
452              break;              goto warn;
453    
454          case 0xe1:          case 0xe1:
455              dsp_out_data(dsp, sb.ver_lo);              dsp_out_data (s, s->ver & 0xff);
456              dsp_out_data(dsp, sb.ver_hi);              dsp_out_data (s, s->ver >> 8);
457              return;              break;
458    
459            case 0xe2:
460                s->needed_bytes = 1;
461                goto warn;
462    
463          case 0xe3:          case 0xe3:
464              {              {
465                  int i;                  int i;
466                  for (i = sizeof (e3) - 1; i >= 0; i--)                  for (i = sizeof (e3) - 1; i >= 0; --i)
467                      dsp_out_data (dsp, e3[i]);                      dsp_out_data (s, e3[i]);
                 return;  
468              }              }
469                break;
470    
471          case 0xe4:              /* write test reg */          case 0xe4:              /* write test reg */
472              dsp->needed_bytes = 1;              s->needed_bytes = 1;
473              break;              break;
474    
475            case 0xe7:
476                dolog ("Attempt to probe for ESS (0xe7)?\n");
477                return;
478    
479          case 0xe8:              /* read test reg */          case 0xe8:              /* read test reg */
480              dsp_out_data (dsp, dsp->test_reg);              dsp_out_data (s, s->test_reg);
481              break;              break;
482    
483          case 0xf2:          case 0xf2:
484              dsp_out_data (dsp, 0xaa);          case 0xf3:
485              dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];              dsp_out_data (s, 0xaa);
486              pic_set_irq (sb.irq, 1);              s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
487              return;              pic_set_irq (s->irq, 1);
488                break;
489    
490          case 0xf9:          case 0xf9:
491              dsp->needed_bytes = 1;              s->needed_bytes = 1;
492              break;              goto warn;
493    
494          case 0xfa:          case 0xfa:
495              dsp_out_data (dsp, 0);              dsp_out_data (s, 0);
496              break;              goto warn;
497    
498          case 0xfc:              /* FIXME */          case 0xfc:              /* FIXME */
499              dsp_out_data (dsp, 0);              dsp_out_data (s, 0);
500              break;              goto warn;
501    
502          default:          default:
503              dolog ("unrecognized command %#x\n", cmd);              dolog ("unrecognized command %#x\n", cmd);
504              goto error;              return;
505          }          }
506      }      }
507      dsp->cmd = cmd;  
508        s->cmd = cmd;
509        if (!s->needed_bytes)
510            ldebug ("\n");
511      return;      return;
512    
513   error:   warn:
514        dolog ("warning command %#x,%d is not trully understood yet\n",
515               cmd, s->needed_bytes);
516        s->cmd = cmd;
517      return;      return;
518  }  }
519    
520  static void complete (SB16State *dsp)  static uint16_t dsp_get_lohi (SB16State *s)
521    {
522        uint8_t hi = dsp_get_data (s);
523        uint8_t lo = dsp_get_data (s);
524        return (hi << 8) | lo;
525    }
526    
527    static uint16_t dsp_get_hilo (SB16State *s)
528    {
529        uint8_t lo = dsp_get_data (s);
530        uint8_t hi = dsp_get_data (s);
531        return (hi << 8) | lo;
532    }
533    
534    static void complete (SB16State *s)
535  {  {
536      int d0, d1, d2;      int d0, d1, d2;
537      linfo ("complete command %#x, in_index %d, needed_bytes %d\n",      ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
538             dsp->cmd, dsp->in_index, dsp->needed_bytes);              s->cmd, s->in_index, s->needed_bytes);
539    
540      if (dsp->cmd > 0xaf && dsp->cmd < 0xd0) {      if (s->cmd > 0xaf && s->cmd < 0xd0) {
541          d2 = dsp_get_data (dsp);          d2 = dsp_get_data (s);
542          d1 = dsp_get_data (dsp);          d1 = dsp_get_data (s);
543          d0 = dsp_get_data (dsp);          d0 = dsp_get_data (s);
544    
545          ldebug ("d0 = %d, d1 = %d, d2 = %d\n",          if (s->cmd & 8) {
546                  d0, d1, d2);              dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
547          dma_cmd (dsp->cmd, d0, d1 + (d2 << 8));                     s->cmd, d0, d1, d2);
548            }
549            else {
550                ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
551                        s->cmd, d0, d1, d2);
552                dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
553            }
554      }      }
555      else {      else {
556          switch (dsp->cmd) {          switch (s->cmd) {
557          case 0x04:          case 0x04:
558          case 0x10:              s->csp_mode = dsp_get_data (s);
559              dsp_get_data (dsp);              s->csp_reg83r = 0;
560                s->csp_reg83w = 0;
561                ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
562              break;              break;
563    
564          case 0x0f:          case 0x05:
565              d0 = dsp_get_data (dsp);              s->csp_param = dsp_get_data (s);
566              dsp_out_data (dsp, 0xf8);              s->csp_value = dsp_get_data (s);
567                ldebug ("CSP command 0x05: param=%#x value=%#x\n",
568                        s->csp_param,
569                        s->csp_value);
570              break;              break;
571    
         case 0x05:  
572          case 0x0e:          case 0x0e:
573              dsp_get_data (dsp);              d0 = dsp_get_data (s);
574              dsp_get_data (dsp);              d1 = dsp_get_data (s);
575                ldebug ("write CSP register %d <- %#x\n", d1, d0);
576                if (d1 == 0x83) {
577                    ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
578                    s->csp_reg83[s->csp_reg83r % 4] = d0;
579                    s->csp_reg83r += 1;
580                }
581                else
582                    s->csp_regs[d1] = d0;
583              break;              break;
584    
585          case 0x14:          case 0x0f:
586              {              d0 = dsp_get_data (s);
587                  int save_left;              ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
588                  int save_pos;                      d0, s->csp_regs[d0], s->csp_mode);
589                if (d0 == 0x83) {
590                  d1 = dsp_get_data (dsp);                  ldebug ("0x83[%d] -> %#x\n",
591                  d0 = dsp_get_data (dsp);                          s->csp_reg83w,
592                            s->csp_reg83[s->csp_reg83w % 4]);
593                    dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
594                    s->csp_reg83w += 1;
595                }
596                else
597                    dsp_out_data (s, s->csp_regs[d0]);
598                break;
599    
600                  save_left = dsp->left_till_irq;          case 0x10:
601                  save_pos = dsp->dma_pos;              d0 = dsp_get_data (s);
602                  dma_cmd (0xc0, 0, d0 + (d1 << 8));              dolog ("cmd 0x10 d0=%#x\n", d0);
603                  dsp->left_till_irq = save_left;              break;
                 dsp->dma_pos = save_pos;  
604    
605                  linfo ("set buffer size data[%d, %d] %d pos %d\n",          case 0x14:
606                         d0, d1, dsp->dma_buffer_size, dsp->dma_pos);              dma_cmd8 (s, 0, dsp_get_lohi (s));
607                  break;              /* s->can_write = 0; */
608              }              /* qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + (ticks_per_sec * 320) / 1000000); */
609                break;
610    
611          case 0x40:          case 0x40:
612              dsp->time_const = dsp_get_data (dsp);              s->time_const = dsp_get_data (s);
613              linfo ("set time const %d\n", dsp->time_const);              ldebug ("set time const %d\n", s->time_const);
614              break;              break;
615    
616          case 0x41:          case 0x42:              /* FT2 sets output freq with this, go figure */
617          case 0x42:              dolog ("cmd 0x42 might not do what it think it should\n");
             d1 = dsp_get_data (dsp);  
             d0 = dsp_get_data (dsp);  
618    
619              dsp->freq = d1 + (d0 << 8);          case 0x41:
620              linfo ("set freq %#x, %#x = %d\n", d1, d0, dsp->freq);              s->freq = dsp_get_hilo (s);
621                ldebug ("set freq %d\n", s->freq);
622              break;              break;
623    
624          case 0x48:          case 0x48:
625              d1 = dsp_get_data (dsp);              s->block_size = dsp_get_lohi (s);
626              d0 = dsp_get_data (dsp);              /* s->highspeed = 1; */
627              dsp->dma_buffer_size = d1 + (d0 << 8);              ldebug ("set dma block len %d\n", s->block_size);
628              linfo ("set dma len %#x, %#x = %d\n",              break;
629                     d1, d0, dsp->dma_buffer_size);  
630            case 0x80:
631                {
632                    int samples, bytes;
633                    int64_t ticks;
634    
635                    if (-1 == s->freq)
636                        s->freq = 11025;
637                    samples = dsp_get_lohi (s);
638                    bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
639                    ticks = ticks_per_sec / (s->freq / bytes);
640                    if (ticks < ticks_per_sec / 1024)
641                        pic_set_irq (s->irq, 1);
642                    else
643                        qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
644                    ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
645                }
646              break;              break;
647    
648          case 0xe0:          case 0xe0:
649              d0 = dsp_get_data (dsp);              d0 = dsp_get_data (s);
650              dsp->out_data_len = 0;              s->out_data_len = 0;
651              linfo ("data = %#x\n", d0);              ldebug ("E0 data = %#x\n", d0);
652              dsp_out_data (dsp, d0 ^ 0xff);              dsp_out_data(s, ~d0);
653              break;              break;
654    
655          case 0xe4:          case 0xe2:
656              dsp->test_reg = dsp_get_data (dsp);              d0 = dsp_get_data (s);
657                dolog ("E2 = %#x\n", d0);
658              break;              break;
659    
660            case 0xe4:
661                s->test_reg = dsp_get_data (s);
662                break;
663    
664          case 0xf9:          case 0xf9:
665              d0 = dsp_get_data (dsp);              d0 = dsp_get_data (s);
666              ldebug ("f9 <- %#x\n", d0);              ldebug ("command 0xf9 with %#x\n", d0);
667              switch (d0) {              switch (d0) {
668              case 0x0e: dsp_out_data (dsp, 0xff); break;              case 0x0e:
669              case 0x0f: dsp_out_data (dsp, 0x07); break;                  dsp_out_data (s, 0xff);
670              case 0xf9: dsp_out_data (dsp, 0x00); break;                  break;
671    
672                case 0x0f:
673                    dsp_out_data (s, 0x07);
674                    break;
675    
676              case 0x37:              case 0x37:
677                  dsp_out_data (dsp, 0x38); break;                  dsp_out_data (s, 0x38);
678                    break;
679    
680              default:              default:
681                  dsp_out_data (dsp, 0);                  dsp_out_data (s, 0x00);
682                    break;
683              }              }
684              break;              break;
685    
686          default:          default:
687              dolog ("complete: unrecognized command %#x\n", dsp->cmd);              dolog ("complete: unrecognized command %#x\n", s->cmd);
688              return;              return;
689          }          }
690      }      }
691    
692      dsp->needed_bytes = 0;      ldebug ("\n");
693      dsp->cmd = -1;      s->cmd = -1;
694      return;      return;
695  }  }
696    
697    static void reset (SB16State *s)
698    {
699        pic_set_irq (s->irq, 0);
700        if (s->dma_auto) {
701            pic_set_irq (s->irq, 1);
702            pic_set_irq (s->irq, 0);
703        }
704    
705        s->mixer_regs[0x82] = 0;
706        s->dma_auto = 0;
707        s->in_index = 0;
708        s->out_data_len = 0;
709        s->left_till_irq = 0;
710        s->needed_bytes = 0;
711        s->block_size = -1;
712        s->nzero = 0;
713        s->highspeed = 0;
714        s->v2x6 = 0;
715    
716        dsp_out_data(s, 0xaa);
717        speaker (s, 0);
718        control (s, 0);
719    }
720    
721  static IO_WRITE_PROTO (dsp_write)  static IO_WRITE_PROTO (dsp_write)
722  {  {
723      SB16State *dsp = opaque;      SB16State *s = opaque;
724      int iport;      int iport;
725    
726      iport = nport - sb.port;      iport = nport - s->port;
727    
728      ldebug ("dsp_write %#x <- %#x\n", nport, val);      ldebug ("write %#x <- %#x\n", nport, val);
729      switch (iport) {      switch (iport) {
730      case 0x6:      case 0x06:
731          control (0);          switch (val) {
732          if (0 == val)          case 0x00:
733              dsp->v2x6 = 0;              if (s->v2x6 == 1) {
734          else if ((1 == val) && (0 == dsp->v2x6)) {                  if (0 && s->highspeed) {
735              dsp->v2x6 = 1;                      s->highspeed = 0;
736              dsp->dma_pos = 0;                      pic_set_irq (s->irq, 0);
737              dsp->dma_auto = 0;                      control (s, 0);
738              dsp->in_index = 0;                  }
739              dsp->out_data_len = 0;                  else
740              dsp->left_till_irq = 0;                      reset (s);
             dsp->speaker = 0;  
             dsp->needed_bytes = 0;  
             pic_set_irq (sb.irq, 0);  
             dsp_out_data(dsp, 0xaa);  
         }  
         else  
             dsp->v2x6 = ~0;  
         break;  
   
     case 0xc:                   /* write data or command | write status */  
         if (0 == dsp->needed_bytes) {  
             command (dsp, val);  
             if (0 == dsp->needed_bytes) {  
                 log_dsp (dsp);  
741              }              }
742                s->v2x6 = 0;
743                break;
744    
745            case 0x01:
746            case 0x03:              /* FreeBSD kludge */
747                s->v2x6 = 1;
748                break;
749    
750            case 0xc6:
751                s->v2x6 = 0;        /* Prince of Persia, csp.sys, diagnose.exe */
752                break;
753    
754            case 0xb8:              /* Panic */
755                reset (s);
756                break;
757    
758            case 0x39:
759                dsp_out_data (s, 0x38);
760                reset (s);
761                s->v2x6 = 0x39;
762                break;
763    
764            default:
765                s->v2x6 = val;
766                break;
767            }
768            break;
769    
770        case 0x0c:                  /* write data or command | write status */
771    /*         if (s->highspeed) */
772    /*             break; */
773    
774            if (0 == s->needed_bytes) {
775                command (s, val);
776    #if 0
777                if (0 == s->needed_bytes) {
778                    log_dsp (s);
779                }
780    #endif
781          }          }
782          else {          else {
783              if (dsp->in_index == sizeof (dsp->in2_data)) {              if (s->in_index == sizeof (s->in2_data)) {
784                  dolog ("in data overrun\n");                  dolog ("in data overrun\n");
785              }              }
786              else {              else {
787                  dsp->in2_data[dsp->in_index++] = val;                  s->in2_data[s->in_index++] = val;
788              if (dsp->in_index == dsp->needed_bytes) {                  if (s->in_index == s->needed_bytes) {
789                  dsp->needed_bytes = 0;                      s->needed_bytes = 0;
790                  complete (dsp);                      complete (s);
791                  log_dsp (dsp);  #if 0
792                        log_dsp (s);
793    #endif
794                    }
795              }              }
796          }          }
         }  
797          break;          break;
798    
799      default:      default:
800          dolog ("dsp_write (nport=%#x, val=%#x)\n", nport, val);          ldebug ("(nport=%#x, val=%#x)\n", nport, val);
801          break;          break;
802      }      }
803  }  }
804    
805  static IO_READ_PROTO (dsp_read)  static IO_READ_PROTO (dsp_read)
806  {  {
807      SB16State *dsp = opaque;      SB16State *s = opaque;
808      int iport, retval;      int iport, retval, ack = 0;
809    
810      iport = nport - sb.port;      iport = nport - s->port;
811    
812      switch (iport) {      switch (iport) {
813      case 0x6:                   /* reset */      case 0x06:                  /* reset */
814          control (0);          retval = 0xff;
         retval = 0;  
         dsp->speaker = 0;  
815          break;          break;
816    
817      case 0xa:                   /* read data */      case 0x0a:                  /* read data */
818          if (dsp->out_data_len) {          if (s->out_data_len) {
819              retval = dsp->out_data[--dsp->out_data_len];              retval = s->out_data[--s->out_data_len];
820              dsp->last_read_byte = retval;              s->last_read_byte = retval;
821          } else {          }
822              retval = dsp->last_read_byte;          else {
823              dolog ("empty output buffer\n");              dolog ("empty output buffer\n");
824                retval = s->last_read_byte;
825              /* goto error; */              /* goto error; */
826          }          }
827          break;          break;
828    
829      case 0xc:                   /* 0xxxxxxx can write */      case 0x0c:                  /* 0 can write */
830          retval = 0;          retval = s->can_write ? 0 : 0x80;
         if (dsp->out_data_len == sizeof (dsp->out_data)) retval |= 0x80;  
831          break;          break;
832    
833      case 0xd:                   /* timer interrupt clear */      case 0x0d:                  /* timer interrupt clear */
834          dolog ("timer interrupt clear\n");          /* dolog ("timer interrupt clear\n"); */
835          goto error;          retval = 0;
836            break;
837    
838      case 0xe:                   /* data available status | irq 8 ack */      case 0x0e:                  /* data available status | irq 8 ack */
839          /* XXX drop pic irq line here? */          retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
840          /* ldebug ("8 ack\n"); */          if (s->mixer_regs[0x82] & 1) {
841          retval = dsp->out_data_len ? 0x80 : 0;              ack = 1;
842          dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];              s->mixer_regs[0x82] &= 1;
843          pic_set_irq (sb.irq, 0);              pic_set_irq (s->irq, 0);
844            }
845          break;          break;
846    
847      case 0xf:                   /* irq 16 ack */      case 0x0f:                  /* irq 16 ack */
         /* XXX drop pic irq line here? */  
         ldebug ("16 ack\n");  
848          retval = 0xff;          retval = 0xff;
849          dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];          if (s->mixer_regs[0x82] & 2) {
850          pic_set_irq (sb.irq, 0);              ack = 1;
851                s->mixer_regs[0x82] &= 2;
852                pic_set_irq (s->irq, 0);
853            }
854          break;          break;
855    
856      default:      default:
857          goto error;          goto error;
858      }      }
859    
860      if (0xe == iport) {      if (!ack)
861          if (0 == retval) {          ldebug ("read %#x -> %#x\n", nport, retval);
             if (!dsp->nzero) {  
                 ldebug ("dsp_read (nport=%#x iport %#x) = %#x, %lld\n",  
                         nport, iport, retval, dsp->nzero);  
             }  
             dsp->nzero += 1;  
         }  
         else {  
             ldebug ("dsp_read (nport=%#x iport %#x) = %#x, %lld\n",  
                     nport, iport, retval, dsp->nzero);  
             dsp->nzero = 0;  
         }  
     }  
     else {  
         ldebug ("dsp_read (nport=%#x iport %#x) = %#x\n",  
                 nport, iport, retval);  
     }  
862    
863      return retval;      return retval;
864    
865   error:   error:
866      printf ("dsp_read error %#x\n", nport);      dolog ("WARNING dsp_read %#x error\n", nport);
867      return 0xff;      return 0xff;
868  }  }
869    
870    static void reset_mixer (SB16State *s)
871    {
872        int i;
873    
874        memset (s->mixer_regs, 0xff, 0x7f);
875        memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
876    
877        s->mixer_regs[0x02] = 4;    /* master volume 3bits */
878        s->mixer_regs[0x06] = 4;    /* MIDI volume 3bits */
879        s->mixer_regs[0x08] = 0;    /* CD volume 3bits */
880        s->mixer_regs[0x0a] = 0;    /* voice volume 2bits */
881    
882        /* d5=input filt, d3=lowpass filt, d1,d2=input source */
883        s->mixer_regs[0x0c] = 0;
884    
885        /* d5=output filt, d1=stereo switch */
886        s->mixer_regs[0x0e] = 0;
887    
888        /* voice volume L d5,d7, R d1,d3 */
889        s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
890        /* master ... */
891        s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
892        /* MIDI ... */
893        s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
894    
895        for (i = 0x30; i < 0x48; i++) {
896            s->mixer_regs[i] = 0x20;
897        }
898    }
899    
900  static IO_WRITE_PROTO(mixer_write_indexb)  static IO_WRITE_PROTO(mixer_write_indexb)
901  {  {
902      SB16State *dsp = opaque;      SB16State *s = opaque;
903      dsp->mixer_nreg = val;      s->mixer_nreg = val;
904  }  }
905    
906  static IO_WRITE_PROTO(mixer_write_datab)  static IO_WRITE_PROTO(mixer_write_datab)
907  {  {
908      SB16State *dsp = opaque;      SB16State *s = opaque;
     int i;  
909    
910      linfo ("mixer [%#x] <- %#x\n", dsp->mixer_nreg, val);      ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
911      switch (dsp->mixer_nreg) {      if (s->mixer_nreg > sizeof (s->mixer_regs))
912            return;
913    
914        switch (s->mixer_nreg) {
915      case 0x00:      case 0x00:
916          /* Bochs */          reset_mixer (s);
         dsp->mixer_regs[0x04] = 0xcc;  
         dsp->mixer_regs[0x0a] = 0x00;  
         dsp->mixer_regs[0x22] = 0xcc;  
         dsp->mixer_regs[0x26] = 0xcc;  
         dsp->mixer_regs[0x28] = 0x00;  
         dsp->mixer_regs[0x2e] = 0x00;  
         dsp->mixer_regs[0x3c] = 0x1f;  
         dsp->mixer_regs[0x3d] = 0x15;  
         dsp->mixer_regs[0x3e] = 0x0b;  
   
         for (i = 0x30; i <= 0x35; i++)  
             dsp->mixer_regs[i] = 0xc0;  
   
         for (i = 0x36; i <= 0x3b; i++)  
             dsp->mixer_regs[i] = 0x00;  
   
         for (i = 0x3f; i <= 0x43; i++)  
             dsp->mixer_regs[i] = 0x00;  
   
         for (i = 0x44; i <= 0x47; i++)  
             dsp->mixer_regs[i] = 0x80;  
   
         for (i = 0x30; i < 0x48; i++) {  
             dsp->mixer_regs[i] = 0x20;  
         }  
917          break;          break;
918    
     case 0x04:  
     case 0x0a:  
     case 0x22:  
     case 0x26:  
     case 0x28:  
     case 0x2e:  
     case 0x30:  
     case 0x31:  
     case 0x32:  
     case 0x33:  
     case 0x34:  
     case 0x35:  
     case 0x36:  
     case 0x37:  
     case 0x38:  
     case 0x39:  
     case 0x3a:  
     case 0x3b:  
     case 0x3c:  
     case 0x3d:  
     case 0x3e:  
     case 0x3f:  
     case 0x40:  
     case 0x41:  
     case 0x42:  
     case 0x43:  
     case 0x44:  
     case 0x45:  
     case 0x46:  
     case 0x47:  
919      case 0x80:      case 0x80:
920      case 0x81:          {
921                int irq = irq_of_magic (val);
922                ldebug ("setting irq to %d (val=%#x)\n", irq, val);
923                if (irq > 0)
924                    s->irq = irq;
925            }
926          break;          break;
     default:  
         return;  
     }  
     dsp->mixer_regs[dsp->mixer_nreg] = val;  
 }  
927    
928  static IO_WRITE_PROTO(mpu_write)      case 0x81:
929  {          {
930      linfo ("mpu: %#x\n", val);              int dma, hdma;
 }  
931    
932  static IO_WRITE_PROTO(adlib_write)              dma = lsbindex (val & 0xf);
933  {              hdma = lsbindex (val & 0xf0);
934      linfo ("adlib: %#x\n", val);              dolog ("attempt to set DMA register 8bit %d, 16bit %d (val=%#x)\n",
935  }                     dma, hdma, val);
936    #if 0
937                s->dma = dma;
938                s->hdma = hdma;
939    #endif
940            }
941            break;
942    
943  static IO_READ_PROTO(mpu_read)      case 0x82:
944  {          dolog ("attempt to write into IRQ status register (val=%#x)\n",
945      linfo ("mpu read: %#x\n", nport);                 val);
946      return 0x80;          return;
 }  
947    
948  static IO_READ_PROTO(adlib_read)      default:
949  {          if (s->mixer_nreg >= 0x80)
950      linfo ("adlib read: %#x\n", nport);              dolog ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
951      return 0;          break;
952        }
953    
954        s->mixer_regs[s->mixer_nreg] = val;
955  }  }
956    
957  static IO_WRITE_PROTO(mixer_write_indexw)  static IO_WRITE_PROTO(mixer_write_indexw)
# Line 765  static IO_WRITE_PROTO(mixer_write_indexw Line 962  static IO_WRITE_PROTO(mixer_write_indexw
962    
963  static IO_READ_PROTO(mixer_read)  static IO_READ_PROTO(mixer_read)
964  {  {
965      SB16State *dsp = opaque;      SB16State *s = opaque;
966      linfo ("mixer [%#x] -> %#x\n", dsp->mixer_nreg, dsp->mixer_regs[dsp->mixer_nreg]);      ldebug ("mixer_read[%#x] -> %#x\n",
967      return dsp->mixer_regs[dsp->mixer_nreg];              s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
968  }      return s->mixer_regs[s->mixer_nreg];
   
 void SB16_run (void)  
 {  
     if (0 == dsp.speaker)  
         return;  
   
     AUD_run ();  
969  }  }
970    
971  static int write_audio (uint32_t addr, int len, int size)  static int write_audio (SB16State *s, int nchan, int dma_pos,
972                            int dma_len, int len)
973  {  {
974      int temp, net;      int temp, net;
975      uint8_t tmpbuf[4096];      uint8_t tmpbuf[4096];
976    
977      temp = size;      temp = len;
   
978      net = 0;      net = 0;
979    
980      while (temp) {      while (temp) {
981          int left_till_end;          int left = dma_len - dma_pos;
982          int to_copy;          int to_copy, copied;
         int copied;  
   
         left_till_end = len - dsp.dma_pos;  
983    
984          to_copy = MIN (temp, left_till_end);          to_copy = audio_MIN (temp, left);
985          if (to_copy > sizeof(tmpbuf))          if (to_copy > sizeof(tmpbuf))
986              to_copy = sizeof(tmpbuf);              to_copy = sizeof(tmpbuf);
         cpu_physical_memory_read(addr + dsp.dma_pos, tmpbuf, to_copy);  
         copied = AUD_write (tmpbuf, to_copy);  
987    
988          temp -= copied;          copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
989          dsp.dma_pos += copied;          copied = AUD_write (s->voice, tmpbuf, copied);
   
         if (dsp.dma_pos == len) {  
             dsp.dma_pos = 0;  
         }  
990    
991            temp -= copied;
992            dma_pos = (dma_pos + copied) % dma_len;
993          net += copied;          net += copied;
994    
995          if (copied != to_copy)          if (!copied)
996              return net;              break;
997      }      }
998    
999      return net;      return net;
1000  }  }
1001    
1002  static int SB_read_DMA (void *opaque, target_ulong addr, int size)  static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
1003  {  {
1004      SB16State *dsp = opaque;      SB16State *s = opaque;
1005      int free, till, copy, written;      int free, rfree, till, copy, written, elapsed;
1006    
1007      if (0 == dsp->speaker)      if (s->left_till_irq < 0) {
1008          return 0;          s->left_till_irq = s->block_size;
   
     if (dsp->left_till_irq < 0) {  
         ldebug ("left_till_irq < 0, %d, pos %d \n",  
                 dsp->left_till_irq, dsp->dma_buffer_size);  
         dsp->left_till_irq += dsp->dma_buffer_size;  
         return dsp->dma_pos;  
1009      }      }
1010    
1011      free = AUD_get_free ();      elapsed = AUD_calc_elapsed (s->voice);
1012        free = elapsed;/* AUD_get_free (s->voice); */
1013      if ((free <= 0) || (0 == size)) {      rfree = free;
1014          ldebug ("returning, since free = %d and size = %d\n", free, size);      free = audio_MIN (free, elapsed) & ~s->align;
         return dsp->dma_pos;  
     }  
1015    
1016      if (mix_block > 0) {      if ((free <= 0) || !dma_len) {
1017          copy = MIN (free, mix_block);          return dma_pos;
     }  
     else {  
         copy = free;  
1018      }      }
1019    
1020      till = dsp->left_till_irq;      copy = free;
1021        till = s->left_till_irq;
1022    
1023  #ifdef DEBUG_SB16_MOST  #ifdef DEBUG_SB16_MOST
1024      ldebug ("addr:%#010x free:%d till:%d size:%d\n",      dolog ("pos:%06d free:%d,%d till:%d len:%d\n",
1025              addr, free, till, size);             dma_pos, free, AUD_get_free (s->voice), till, dma_len);
1026  #endif  #endif
1027    
1028      if (till <= copy) {      if (till <= copy) {
1029          if (0 == dsp->dma_auto) {          if (0 == s->dma_auto) {
1030              copy = till;              copy = till;
1031          }          }
1032      }      }
1033    
1034      written = write_audio (addr, size, copy);      written = write_audio (s, nchan, dma_pos, dma_len, copy);
1035      dsp->left_till_irq -= written;      dma_pos = (dma_pos + written) % dma_len;
1036      AUD_adjust_estimate (free - written);      s->left_till_irq -= written;
1037    
1038      if (dsp->left_till_irq <= 0) {      if (s->left_till_irq <= 0) {
1039          dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];          s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
1040          if (0 == noirq) {          pic_set_irq (s->irq, 1);
1041              ldebug ("request irq pos %d, left %d\n",          if (0 == s->dma_auto) {
1042                      dsp->dma_pos, dsp->left_till_irq);              control (s, 0);
1043              pic_set_irq(sb.irq, 1);              speaker (s, 0);
         }  
   
         if (0 == dsp->dma_auto) {  
             control (0);  
1044          }          }
1045      }      }
1046    
1047  #ifdef DEBUG_SB16_MOST  #ifdef DEBUG_SB16_MOST
1048      ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",      ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
1049              dsp->dma_pos, free, size, dsp->left_till_irq, copy,              dma_pos, free, dma_len, s->left_till_irq, copy, s->block_size);
             dsp->dma_buffer_size);  
1050  #endif  #endif
1051    
1052      if (dsp->left_till_irq <= 0) {      while (s->left_till_irq <= 0) {
1053          dsp->left_till_irq += dsp->dma_buffer_size;          s->left_till_irq = s->block_size + s->left_till_irq;
1054      }      }
1055    
1056      return dsp->dma_pos;      AUD_adjust (s->voice, written);
1057        return dma_pos;
1058  }  }
1059    
1060  static int magic_of_irq (int irq)  void SB_timer (void *opaque)
1061  {  {
1062      switch (irq) {      SB16State *s = opaque;
1063      case 2:      AUD_run ();
1064          return 1;      qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
     case 5:  
         return 2;  
     case 7:  
         return 4;  
     case 10:  
         return 8;  
     default:  
         dolog ("bad irq %d\n", irq);  
         return 2;  
     }  
1065  }  }
1066    
1067  #if 0  static void SB_save (QEMUFile *f, void *opaque)
 static int irq_of_magic (int magic)  
1068  {  {
1069      switch (magic) {      SB16State *s = opaque;
     case 1:  
         return 2;  
     case 2:  
         return 5;  
     case 4:  
         return 7;  
     case 8:  
         return 10;  
     default:  
         dolog ("bad irq magic %d\n", magic);  
         return 2;  
     }  
 }  
 #endif  
1070    
1071  #ifdef SB16_TRAP_ALL      qemu_put_be32s (f, &s->irq);
1072  static IO_READ_PROTO (trap_read)      qemu_put_be32s (f, &s->dma);
1073  {      qemu_put_be32s (f, &s->hdma);
1074      switch (nport) {      qemu_put_be32s (f, &s->port);
1075      case 0x220:      qemu_put_be32s (f, &s->ver);
1076          return 0;      qemu_put_be32s (f, &s->in_index);
1077      case 0x226:      qemu_put_be32s (f, &s->out_data_len);
1078      case 0x22a:      qemu_put_be32s (f, &s->fmt_stereo);
1079      case 0x22c:      qemu_put_be32s (f, &s->fmt_signed);
1080      case 0x22d:      qemu_put_be32s (f, &s->fmt_bits);
1081      case 0x22e:      qemu_put_be32s (f, &s->fmt);
1082      case 0x22f:      qemu_put_be32s (f, &s->dma_auto);
1083          return dsp_read (opaque, nport);      qemu_put_be32s (f, &s->block_size);
1084      }      qemu_put_be32s (f, &s->fifo);
1085      linfo ("trap_read: %#x\n", nport);      qemu_put_be32s (f, &s->freq);
1086      return 0xff;      qemu_put_be32s (f, &s->time_const);
1087  }      qemu_put_be32s (f, &s->speaker);
1088        qemu_put_be32s (f, &s->needed_bytes);
1089        qemu_put_be32s (f, &s->cmd);
1090        qemu_put_be32s (f, &s->use_hdma);
1091        qemu_put_be32s (f, &s->highspeed);
1092        qemu_put_be32s (f, &s->can_write);
1093        qemu_put_be32s (f, &s->v2x6);
1094    
1095        qemu_put_8s (f, &s->csp_param);
1096        qemu_put_8s (f, &s->csp_value);
1097        qemu_put_8s (f, &s->csp_mode);
1098        qemu_put_8s (f, &s->csp_param);
1099        qemu_put_buffer (f, s->csp_regs, 256);
1100        qemu_put_8s (f, &s->csp_index);
1101        qemu_put_buffer (f, s->csp_reg83, 4);
1102        qemu_put_be32s (f, &s->csp_reg83r);
1103        qemu_put_be32s (f, &s->csp_reg83w);
1104    
1105        qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
1106        qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
1107        qemu_put_8s (f, &s->test_reg);
1108        qemu_put_8s (f, &s->last_read_byte);
1109    
1110        qemu_put_be32s (f, &s->nzero);
1111        qemu_put_be32s (f, &s->left_till_irq);
1112        qemu_put_be32s (f, &s->dma_running);
1113        qemu_put_be32s (f, &s->bytes_per_second);
1114        qemu_put_be32s (f, &s->align);
1115    
1116        qemu_put_be32s (f, &s->mixer_nreg);
1117        qemu_put_buffer (f, s->mixer_regs, 256);
1118    }
1119    
1120    static int SB_load (QEMUFile *f, void *opaque, int version_id)
1121    {
1122        SB16State *s = opaque;
1123    
1124        if (version_id != 1)
1125            return -EINVAL;
1126    
1127        qemu_get_be32s (f, &s->irq);
1128        qemu_get_be32s (f, &s->dma);
1129        qemu_get_be32s (f, &s->hdma);
1130        qemu_get_be32s (f, &s->port);
1131        qemu_get_be32s (f, &s->ver);
1132        qemu_get_be32s (f, &s->in_index);
1133        qemu_get_be32s (f, &s->out_data_len);
1134        qemu_get_be32s (f, &s->fmt_stereo);
1135        qemu_get_be32s (f, &s->fmt_signed);
1136        qemu_get_be32s (f, &s->fmt_bits);
1137        qemu_get_be32s (f, &s->fmt);
1138        qemu_get_be32s (f, &s->dma_auto);
1139        qemu_get_be32s (f, &s->block_size);
1140        qemu_get_be32s (f, &s->fifo);
1141        qemu_get_be32s (f, &s->freq);
1142        qemu_get_be32s (f, &s->time_const);
1143        qemu_get_be32s (f, &s->speaker);
1144        qemu_get_be32s (f, &s->needed_bytes);
1145        qemu_get_be32s (f, &s->cmd);
1146        qemu_get_be32s (f, &s->use_hdma);
1147        qemu_get_be32s (f, &s->highspeed);
1148        qemu_get_be32s (f, &s->can_write);
1149        qemu_get_be32s (f, &s->v2x6);
1150    
1151        qemu_get_8s (f, &s->csp_param);
1152        qemu_get_8s (f, &s->csp_value);
1153        qemu_get_8s (f, &s->csp_mode);
1154        qemu_get_8s (f, &s->csp_param);
1155        qemu_get_buffer (f, s->csp_regs, 256);
1156        qemu_get_8s (f, &s->csp_index);
1157        qemu_get_buffer (f, s->csp_reg83, 4);
1158        qemu_get_be32s (f, &s->csp_reg83r);
1159        qemu_get_be32s (f, &s->csp_reg83w);
1160    
1161        qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
1162        qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
1163        qemu_get_8s (f, &s->test_reg);
1164        qemu_get_8s (f, &s->last_read_byte);
1165    
1166        qemu_get_be32s (f, &s->nzero);
1167        qemu_get_be32s (f, &s->left_till_irq);
1168        qemu_get_be32s (f, &s->dma_running);
1169        qemu_get_be32s (f, &s->bytes_per_second);
1170        qemu_get_be32s (f, &s->align);
1171    
1172        qemu_get_be32s (f, &s->mixer_nreg);
1173        qemu_get_buffer (f, s->mixer_regs, 256);
1174    
1175        if (s->voice)
1176            AUD_reset (s->voice);
1177    
1178        if (s->dma_running) {
1179            if (s->freq)
1180                s->voice = AUD_open (s->voice, "sb16", s->freq,
1181                                     1 << s->fmt_stereo, s->fmt);
1182    
1183  static IO_WRITE_PROTO (trap_write)          control (s, 1);
1184  {          speaker (s, s->speaker);
     switch (nport) {  
     case 0x226:  
     case 0x22c:  
         dsp_write (opaque, nport, val);  
         return;  
1185      }      }
1186      linfo ("trap_write: %#x = %#x\n", nport, val);      return 0;
1187  }  }
 #endif  
1188    
1189  void SB16_init (void)  void SB16_init (void)
1190  {  {
# Line 961  void SB16_init (void) Line 1193  void SB16_init (void)
1193      static const uint8_t dsp_write_ports[] = {0x6, 0xc};      static const uint8_t dsp_write_ports[] = {0x6, 0xc};
1194      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};
1195    
1196      memset(s->mixer_regs, 0xff, sizeof(s->mixer_regs));      s->ts = qemu_new_timer (vm_clock, SB_timer, s);
1197        if (!s->ts)
1198            return;
1199    
1200      s->mixer_regs[0x00] = 0;      s->irq = conf.irq;
1201      s->mixer_regs[0x0e] = ~0;      s->dma = conf.dma;
1202      s->mixer_regs[0x80] = magic_of_irq (sb.irq);      s->hdma = conf.hdma;
1203      s->mixer_regs[0x81] = 0x80 | 0x10 | (sb.dma << 1);      s->port = conf.port;
1204      s->mixer_regs[0x82] = 0;      s->ver = conf.ver_lo | (conf.ver_hi << 8);
1205      s->mixer_regs[0xfd] = 16;   /* bochs */  
1206      s->mixer_regs[0xfe] = 6;    /* bochs */      s->mixer_regs[0x80] = magic_of_irq (s->irq);
1207      mixer_write_indexw (s, 0x224, 0);      s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
1208        s->mixer_regs[0x82] = 2 << 5;
1209  #ifdef SB16_TRAP_ALL  
1210      for (i = 0; i < 0x100; i++) {      s->csp_regs[5] = 1;
1211          if (i != 4 && i != 5) {      s->csp_regs[9] = 0xf8;
1212              register_ioport_write (sb.port + i, 1, 1, trap_write, s);  
1213              register_ioport_read (sb.port + i, 1, 1, trap_read, s);      reset_mixer (s);
1214          }      s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
1215      }      if (!s->aux_ts)
1216  #else          return;
1217    
1218      for (i = 0; i < LENOFA (dsp_write_ports); i++) {      for (i = 0; i < LENOFA (dsp_write_ports); i++) {
1219          register_ioport_write (sb.port + dsp_write_ports[i], 1, 1, dsp_write, s);          register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
1220      }      }
1221    
1222      for (i = 0; i < LENOFA (dsp_read_ports); i++) {      for (i = 0; i < LENOFA (dsp_read_ports); i++) {
1223          register_ioport_read (sb.port + dsp_read_ports[i], 1, 1, dsp_read, s);          register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
1224      }      }
 #endif  
1225    
1226      register_ioport_write (sb.port + 0x4, 1, 1, mixer_write_indexb, s);      register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
1227      register_ioport_write (sb.port + 0x4, 1, 2, mixer_write_indexw, s);      register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
1228      register_ioport_read (sb.port + 0x5, 1, 1, mixer_read, s);      register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
1229      register_ioport_write (sb.port + 0x5, 1, 1, mixer_write_datab, s);      register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
1230    
1231      for (i = 0; 4 < 4; i++) {      DMA_register_channel (s->hdma, SB_read_DMA, s);
1232          register_ioport_read (0x330 + i, 1, 1, mpu_read, s);      DMA_register_channel (s->dma, SB_read_DMA, s);
1233          register_ioport_write (0x330 + i, 1, 1, mpu_write, s);      s->can_write = 1;
         register_ioport_read (0x388 + i, 1, 1, adlib_read, s);  
         register_ioport_write (0x388 + i, 1, 1, adlib_write, s);  
     }  
1234    
1235      DMA_register_channel (sb.hdma, SB_read_DMA, s);      qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
1236      DMA_register_channel (sb.dma, SB_read_DMA, s);      register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
1237  }  }

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.11

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26