Commit d329a6fb2213e53008a9b1cd186fe2ff258fa272

Authored by bellard
1 parent 7ebb5e41

audip fixes (malc)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@911 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 275 additions and 198 deletions
hw/sb16.c
@@ -26,7 +26,10 @@ @@ -26,7 +26,10 @@
26 #define MIN(a, b) ((a)>(b)?(b):(a)) 26 #define MIN(a, b) ((a)>(b)?(b):(a))
27 #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) 27 #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
28 28
29 -#define log(...) fprintf (stderr, "sb16: " __VA_ARGS__) 29 +#define log(...) do { \
  30 + fprintf (stderr, "sb16: " __VA_ARGS__); \
  31 + fputc ('\n', stderr); \
  32 +} while (0)
30 33
31 /* #define DEBUG_SB16 */ 34 /* #define DEBUG_SB16 */
32 #ifdef DEBUG_SB16 35 #ifdef DEBUG_SB16
@@ -44,6 +47,8 @@ @@ -44,6 +47,8 @@
44 #define IO_WRITE_PROTO(name) \ 47 #define IO_WRITE_PROTO(name) \
45 void name (void *opaque, uint32_t nport, uint32_t val) 48 void name (void *opaque, uint32_t nport, uint32_t val)
46 49
  50 +static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
  51 +
47 static struct { 52 static struct {
48 int ver_lo; 53 int ver_lo;
49 int ver_hi; 54 int ver_hi;
@@ -76,7 +81,7 @@ typedef struct SB16State { @@ -76,7 +81,7 @@ typedef struct SB16State {
76 int v2x6; 81 int v2x6;
77 82
78 uint8_t in_data[10]; 83 uint8_t in_data[10];
79 - uint8_t out_data[10]; 84 + uint8_t out_data[50];
80 85
81 int left_till_irq; 86 int left_till_irq;
82 87
@@ -223,6 +228,20 @@ static void command (SB16State *dsp, uint8_t cmd) @@ -223,6 +228,20 @@ static void command (SB16State *dsp, uint8_t cmd)
223 /* IMS uses those when probing for sound devices */ 228 /* IMS uses those when probing for sound devices */
224 return; 229 return;
225 230
  231 + case 0x04:
  232 + dsp->needed_bytes = 1;
  233 + break;
  234 +
  235 + case 0x05:
  236 + case 0x0e:
  237 + dsp->needed_bytes = 2;
  238 + break;
  239 +
  240 + case 0x0f:
  241 + dsp->needed_bytes = 1;
  242 + dsp_out_data (dsp, 0);
  243 + break;
  244 +
226 case 0x10: 245 case 0x10:
227 dsp->needed_bytes = 1; 246 dsp->needed_bytes = 1;
228 break; 247 break;
@@ -274,8 +293,8 @@ static void command (SB16State *dsp, uint8_t cmd) @@ -274,8 +293,8 @@ static void command (SB16State *dsp, uint8_t cmd)
274 uint8_t d0; 293 uint8_t d0;
275 294
276 d0 = 4; 295 d0 = 4;
277 - if (dsp->fmt_signed) d0 |= 16;  
278 - if (dsp->fmt_stereo) d0 |= 32; 296 + /* if (dsp->fmt_signed) d0 |= 16; */
  297 + /* if (dsp->fmt_stereo) d0 |= 32; */
279 dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1); 298 dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);
280 cmd = -1; 299 cmd = -1;
281 break; 300 break;
@@ -324,6 +343,14 @@ static void command (SB16State *dsp, uint8_t cmd) @@ -324,6 +343,14 @@ static void command (SB16State *dsp, uint8_t cmd)
324 dsp_out_data(dsp, sb.ver_hi); 343 dsp_out_data(dsp, sb.ver_hi);
325 return; 344 return;
326 345
  346 + case 0xe3:
  347 + {
  348 + int i;
  349 + for (i = sizeof (e3) - 1; i >= 0; --i)
  350 + dsp_out_data (dsp, e3[i]);
  351 + return;
  352 + }
  353 +
327 case 0xf2: 354 case 0xf2:
328 dsp_out_data(dsp, 0xaa); 355 dsp_out_data(dsp, 0xaa);
329 dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80]; 356 dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
@@ -360,6 +387,11 @@ static void complete (SB16State *dsp) @@ -360,6 +387,11 @@ static void complete (SB16State *dsp)
360 } 387 }
361 else { 388 else {
362 switch (dsp->cmd) { 389 switch (dsp->cmd) {
  390 + case 0x05:
  391 + case 0x04:
  392 + case 0x0e:
  393 + case 0x0f:
  394 + break;
363 395
364 case 0x10: 396 case 0x10:
365 break; 397 break;
@@ -425,8 +457,10 @@ static IO_WRITE_PROTO (dsp_write) @@ -425,8 +457,10 @@ static IO_WRITE_PROTO (dsp_write)
425 457
426 iport = nport - sb.port; 458 iport = nport - sb.port;
427 459
  460 + ldebug ("write %#x %#x\n", nport, iport);
428 switch (iport) { 461 switch (iport) {
429 case 0x6: 462 case 0x6:
  463 + control (0);
430 if (0 == val) 464 if (0 == val)
431 dsp->v2x6 = 0; 465 dsp->v2x6 = 0;
432 else if ((1 == val) && (0 == dsp->v2x6)) { 466 else if ((1 == val) && (0 == dsp->v2x6)) {
@@ -477,7 +511,7 @@ static IO_READ_PROTO (dsp_read) @@ -477,7 +511,7 @@ static IO_READ_PROTO (dsp_read)
477 if (dsp->out_data_len) { 511 if (dsp->out_data_len) {
478 retval = dsp->out_data[--dsp->out_data_len]; 512 retval = dsp->out_data[--dsp->out_data_len];
479 } else { 513 } else {
480 - log("empty output buffer\n"); 514 + log("empty output buffer");
481 goto error; 515 goto error;
482 } 516 }
483 break; 517 break;
@@ -487,7 +521,7 @@ static IO_READ_PROTO (dsp_read) @@ -487,7 +521,7 @@ static IO_READ_PROTO (dsp_read)
487 break; 521 break;
488 522
489 case 0xd: /* timer interrupt clear */ 523 case 0xd: /* timer interrupt clear */
490 - log("timer interrupt clear\n"); 524 + log("timer interrupt clear");
491 goto error; 525 goto error;
492 526
493 case 0xe: /* data available status | irq 8 ack */ 527 case 0xe: /* data available status | irq 8 ack */
@@ -669,7 +703,7 @@ static int magic_of_irq (int irq) @@ -669,7 +703,7 @@ static int magic_of_irq (int irq)
669 case 10: 703 case 10:
670 return 8; 704 return 8;
671 default: 705 default:
672 - log ("bad irq %d\n", irq); 706 + log ("bad irq %d", irq);
673 return 2; 707 return 2;
674 } 708 }
675 } 709 }
@@ -687,7 +721,7 @@ static int irq_of_magic (int magic) @@ -687,7 +721,7 @@ static int irq_of_magic (int magic)
687 case 8: 721 case 8:
688 return 10; 722 return 10;
689 default: 723 default:
690 - log ("bad irq magic %d\n", magic); 724 + log ("bad irq magic %d", magic);
691 return 2; 725 return 2;
692 } 726 }
693 } 727 }
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
24 #include "vl.h" 24 #include "vl.h"
25 25
26 #ifndef _WIN32 26 #ifndef _WIN32
  27 +#include <ctype.h>
27 #include <fcntl.h> 28 #include <fcntl.h>
28 #include <errno.h> 29 #include <errno.h>
29 #include <stdio.h> 30 #include <stdio.h>
@@ -32,6 +33,7 @@ @@ -32,6 +33,7 @@
32 #include <stdlib.h> 33 #include <stdlib.h>
33 #include <limits.h> 34 #include <limits.h>
34 #include <inttypes.h> 35 #include <inttypes.h>
  36 +#include <sys/mman.h>
35 #include <sys/types.h> 37 #include <sys/types.h>
36 #include <sys/ioctl.h> 38 #include <sys/ioctl.h>
37 #include <sys/soundcard.h> 39 #include <sys/soundcard.h>
@@ -90,25 +92,38 @@ static inline uint32_t lsbindex (uint32_t u) @@ -90,25 +92,38 @@ static inline uint32_t lsbindex (uint32_t u)
90 ldebug ("ioctl " #args " = %d\n", ret); \ 92 ldebug ("ioctl " #args " = %d\n", ret); \
91 } while (0) 93 } while (0)
92 94
93 -static int audio_fd = -1;  
94 -static int freq;  
95 -static int conf_nfrags = 4;  
96 -static int conf_fragsize;  
97 -static int nfrags;  
98 -static int fragsize;  
99 -static int bufsize;  
100 -static int nchannels;  
101 -static int fmt;  
102 -static int rpos;  
103 -static int wpos;  
104 -static int atom;  
105 -static int live;  
106 -static int leftover;  
107 -static int bytes_per_second;  
108 -static void *buf;  
109 -static enum {DONT, DSP, TID} estimate = TID;  
110 -  
111 -static void (*copy_fn)(void *, void *, int); 95 +static struct {
  96 + int fd;
  97 + int freq;
  98 + int bits16;
  99 + int nchannels;
  100 + int rpos;
  101 + int wpos;
  102 + int live;
  103 + int oss_fmt;
  104 + int bytes_per_second;
  105 + int is_mapped;
  106 + void *buf;
  107 + int bufsize;
  108 + int nfrags;
  109 + int fragsize;
  110 + int old_optr;
  111 + int leftover;
  112 + uint64_t old_ticks;
  113 + void (*copy_fn)(void *, void *, int);
  114 +} oss = { .fd = -1 };
  115 +
  116 +static struct {
  117 + int try_mmap;
  118 + int nfrags;
  119 + int fragsize;
  120 +} conf = {
  121 + .try_mmap = 0,
  122 + .nfrags = 4,
  123 + .fragsize = 4096
  124 +};
  125 +
  126 +static enum {DONT, DSP, TID} est = DONT;
112 127
113 static void copy_no_conversion (void *dst, void *src, int size) 128 static void copy_no_conversion (void *dst, void *src, int size)
114 { 129 {
@@ -141,70 +156,124 @@ static void pab (struct audio_buf_info *abinfo) @@ -141,70 +156,124 @@ static void pab (struct audio_buf_info *abinfo)
141 rpos, wpos, live); 156 rpos, wpos, live);
142 } 157 }
143 158
144 -void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt) 159 +static void do_open ()
145 { 160 {
146 - int fmt_;  
147 - int bits16; 161 + int mmmmssss;
  162 + audio_buf_info abinfo;
  163 + int fmt, freq, nchannels;
148 164
149 - if (-1 == audio_fd) {  
150 - AUD_open (rfreq, rnchannels, rfmt);  
151 - return; 165 + if (oss.buf) {
  166 + if (-1 == munmap (oss.buf, oss.bufsize)) {
  167 + ERRFail ("failed to unmap audio buffer %p %d",
  168 + oss.buf, oss.bufsize);
  169 + }
  170 + oss.buf = NULL;
152 } 171 }
153 172
154 - switch (rfmt) {  
155 - case AUD_FMT_U8:  
156 - bits16 = 0;  
157 - fmt_ = AFMT_U8;  
158 - copy_fn = copy_no_conversion;  
159 - atom = 1;  
160 - break; 173 + if (-1 != oss.fd)
  174 + close (oss.fd);
161 175
162 - case AUD_FMT_S8:  
163 - Fail ("can not play 8bit signed"); 176 + oss.fd = open ("/dev/dsp", O_RDWR | O_NONBLOCK);
  177 + if (-1 == oss.fd) {
  178 + ERRFail ("can not open /dev/dsp");
  179 + }
164 180
165 - case AUD_FMT_S16:  
166 - bits16 = 1;  
167 - fmt_ = AFMT_S16_LE;  
168 - copy_fn = copy_no_conversion;  
169 - atom = 2;  
170 - break; 181 + fmt = oss.oss_fmt;
  182 + freq = oss.freq;
  183 + nchannels = oss.nchannels;
  184 +
  185 + IOCTL ((oss.fd, SNDCTL_DSP_RESET, 1));
  186 + IOCTL ((oss.fd, SNDCTL_DSP_SAMPLESIZE, &fmt));
  187 + IOCTL ((oss.fd, SNDCTL_DSP_CHANNELS, &nchannels));
  188 + IOCTL ((oss.fd, SNDCTL_DSP_SPEED, &freq));
  189 + IOCTL ((oss.fd, SNDCTL_DSP_NONBLOCK));
  190 +
  191 + mmmmssss = (conf.nfrags << 16) | conf.fragsize;
  192 + IOCTL ((oss.fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));
  193 +
  194 + if ((oss.oss_fmt != fmt)
  195 + || (oss.nchannels != nchannels)
  196 + || (oss.freq != freq)) {
  197 + Fail ("failed to set audio parameters\n"
  198 + "parameter | requested value | obtained value\n"
  199 + "format | %10d | %10d\n"
  200 + "channels | %10d | %10d\n"
  201 + "frequency | %10d | %10d\n",
  202 + oss.oss_fmt, fmt,
  203 + oss.nchannels, nchannels,
  204 + oss.freq, freq);
  205 + }
171 206
172 - case AUD_FMT_U16:  
173 - bits16 = 1;  
174 - fmt_ = AFMT_S16_LE;  
175 - copy_fn = copy_u16_to_s16;  
176 - atom = 2;  
177 - break; 207 + IOCTL ((oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo));
178 208
179 - default:  
180 - abort ();  
181 - } 209 + oss.nfrags = abinfo.fragstotal;
  210 + oss.fragsize = abinfo.fragsize;
  211 + oss.bufsize = oss.nfrags * oss.fragsize;
  212 + oss.old_optr = 0;
182 213
183 - if ((fmt_ == fmt) && (bits16 + 1 == nchannels) && (rfreq == freq))  
184 - return; 214 + oss.bytes_per_second = (freq << (nchannels >> 1)) << oss.bits16;
  215 +
  216 + linfo ("bytes per second %d\n", oss.bytes_per_second);
  217 +
  218 + linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
  219 + abinfo.fragments,
  220 + abinfo.fragstotal,
  221 + abinfo.fragsize,
  222 + abinfo.bytes,
  223 + oss.bufsize);
  224 +
  225 + oss.buf = MAP_FAILED;
  226 + oss.is_mapped = 0;
  227 +
  228 + if (conf.try_mmap) {
  229 + oss.buf = mmap (NULL, oss.bufsize, PROT_WRITE, MAP_SHARED, oss.fd, 0);
  230 + if (MAP_FAILED == oss.buf) {
  231 + int err;
  232 +
  233 + err = errno;
  234 + log ("failed to mmap audio, size %d, fd %d\n"
  235 + "syserr: %s\n",
  236 + oss.bufsize, oss.fd, strerror (err));
  237 + }
185 else { 238 else {
186 - AUD_open (rfreq, rnchannels, rfmt); 239 + est = TID;
  240 + oss.is_mapped = 1;
  241 + }
  242 + }
  243 +
  244 + if (MAP_FAILED == oss.buf) {
  245 + est = TID;
  246 + oss.buf = mmap (NULL, oss.bufsize, PROT_READ | PROT_WRITE,
  247 + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  248 + if (MAP_FAILED == oss.buf) {
  249 + ERRFail ("mmap audio buf, size %d", oss.bufsize);
  250 + }
  251 + }
  252 +
  253 + oss.rpos = 0;
  254 + oss.wpos = 0;
  255 + oss.live = 0;
  256 +
  257 + if (oss.is_mapped) {
  258 + int trig;
  259 +
  260 + trig = 0;
  261 + IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig));
  262 + trig = PCM_ENABLE_OUTPUT;
  263 + IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig));
187 } 264 }
188 } 265 }
189 266
190 -void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt) 267 +static void maybe_open (int req_freq, int req_nchannels,
  268 + audfmt_e req_fmt, int force_open)
191 { 269 {
192 - int fmt_;  
193 - int mmmmssss;  
194 - struct audio_buf_info abinfo;  
195 - int _fmt;  
196 - int _freq;  
197 - int _nchannels;  
198 - int bits16; 270 + int oss_fmt, bits16;
199 271
200 - bits16 = 0;  
201 -  
202 - switch (rfmt) { 272 + switch (req_fmt) {
203 case AUD_FMT_U8: 273 case AUD_FMT_U8:
204 bits16 = 0; 274 bits16 = 0;
205 - fmt_ = AFMT_U8;  
206 - copy_fn = copy_no_conversion;  
207 - atom = 1; 275 + oss_fmt = AFMT_U8;
  276 + oss.copy_fn = copy_no_conversion;
208 break; 277 break;
209 278
210 case AUD_FMT_S8: 279 case AUD_FMT_S8:
@@ -212,111 +281,42 @@ void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt) @@ -212,111 +281,42 @@ void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt)
212 281
213 case AUD_FMT_S16: 282 case AUD_FMT_S16:
214 bits16 = 1; 283 bits16 = 1;
215 - fmt_ = AFMT_S16_LE;  
216 - copy_fn = copy_no_conversion;  
217 - atom = 2; 284 + oss_fmt = AFMT_S16_LE;
  285 + oss.copy_fn = copy_no_conversion;
218 break; 286 break;
219 287
220 case AUD_FMT_U16: 288 case AUD_FMT_U16:
221 bits16 = 1; 289 bits16 = 1;
222 - fmt_ = AFMT_S16_LE;  
223 - copy_fn = copy_u16_to_s16;  
224 - atom = 2; 290 + oss_fmt = AFMT_S16_LE;
  291 + oss.copy_fn = copy_u16_to_s16;
225 break; 292 break;
226 293
227 default: 294 default:
228 abort (); 295 abort ();
229 } 296 }
230 297
231 - if (buf) {  
232 - free (buf);  
233 - buf = 0;  
234 - }  
235 -  
236 - if (-1 != audio_fd)  
237 - close (audio_fd);  
238 -  
239 - audio_fd = open ("/dev/dsp", O_WRONLY | O_NONBLOCK);  
240 - if (-1 == audio_fd) {  
241 - ERRFail ("can not open /dev/dsp");  
242 - }  
243 -  
244 - _fmt = fmt_;  
245 - _freq = rfreq;  
246 - _nchannels = rnchannels;  
247 -  
248 - IOCTL ((audio_fd, SNDCTL_DSP_RESET, 1));  
249 - IOCTL ((audio_fd, SNDCTL_DSP_SAMPLESIZE, &_fmt));  
250 - IOCTL ((audio_fd, SNDCTL_DSP_CHANNELS, &_nchannels));  
251 - IOCTL ((audio_fd, SNDCTL_DSP_SPEED, &_freq));  
252 - IOCTL ((audio_fd, SNDCTL_DSP_NONBLOCK));  
253 -  
254 - /* from oss.pdf:  
255 -  
256 - The argument to this call is an integer encoded as 0xMMMMSSSS (in  
257 - hex). The 16 least significant bits determine the fragment  
258 - size. The size is 2^SSSS. For examp le SSSS=0008 gives fragment  
259 - size of 256 bytes (2^8). The minimum is 16 bytes (SSSS=4) and the  
260 - maximum is total_buffer_size/2. Some devices or processor  
261 - architectures may require larger fragments - in this case the  
262 - requested fragment size is automatically increased.  
263 -  
264 - So ahem... 4096 = 2^12, and grand total 0x0004000c  
265 - */  
266 -  
267 - mmmmssss = (conf_nfrags << 16) | conf_fragsize;  
268 - IOCTL ((audio_fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));  
269 -  
270 - linfo ("_fmt = %d, fmt = %d\n"  
271 - "_channels = %d, rnchannels = %d\n"  
272 - "_freq = %d, freq = %d\n",  
273 - _fmt, fmt_,  
274 - _nchannels, rnchannels,  
275 - _freq, rfreq);  
276 -  
277 - if (_fmt != fmt_) {  
278 - Fail ("format %d != %d", _fmt, fmt_);  
279 - }  
280 -  
281 - if (_nchannels != rnchannels) {  
282 - Fail ("channels %d != %d", _nchannels, rnchannels); 298 + if (force_open
  299 + || (-1 == oss.fd)
  300 + || (oss_fmt != oss.oss_fmt)
  301 + || (req_nchannels != oss.nchannels)
  302 + || (req_freq != oss.freq)
  303 + || (bits16 != oss.bits16)) {
  304 + oss.oss_fmt = oss_fmt;
  305 + oss.nchannels = req_nchannels;
  306 + oss.freq = req_freq;
  307 + oss.bits16 = bits16;
  308 + do_open ();
283 } 309 }
  310 +}
284 311
285 - if (_freq != rfreq) {  
286 - Fail ("freq %d != %d", _freq, rfreq);  
287 - }  
288 -  
289 - IOCTL ((audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo));  
290 -  
291 - nfrags = abinfo.fragstotal;  
292 - fragsize = abinfo.fragsize;  
293 - freq = _freq;  
294 - fmt = _fmt;  
295 - nchannels = rnchannels;  
296 - atom <<= nchannels >> 1;  
297 - bufsize = nfrags * fragsize;  
298 -  
299 - bytes_per_second = (freq << (nchannels >> 1)) << bits16;  
300 -  
301 - linfo ("bytes per second %d\n", bytes_per_second);  
302 -  
303 - linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",  
304 - abinfo.fragments,  
305 - abinfo.fragstotal,  
306 - abinfo.fragsize,  
307 - abinfo.bytes,  
308 - bufsize);  
309 -  
310 - if (NULL == buf) {  
311 - buf = malloc (bufsize);  
312 - if (NULL == buf) {  
313 - abort ();  
314 - }  
315 - } 312 +void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt)
  313 +{
  314 + maybe_open (req_freq, req_nchannels, req_fmt, 0);
  315 +}
316 316
317 - rpos = 0;  
318 - wpos = 0;  
319 - live = 0; 317 +void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
  318 +{
  319 + maybe_open (req_freq, req_nchannels, req_fmt, 1);
320 } 320 }
321 321
322 int AUD_write (void *in_buf, int size) 322 int AUD_write (void *in_buf, int size)
@@ -324,27 +324,27 @@ int AUD_write (void *in_buf, int size) @@ -324,27 +324,27 @@ int AUD_write (void *in_buf, int size)
324 int to_copy, temp; 324 int to_copy, temp;
325 uint8_t *in, *out; 325 uint8_t *in, *out;
326 326
327 - to_copy = MIN (bufsize - live, size); 327 + to_copy = MIN (oss.bufsize - oss.live, size);
328 328
329 temp = to_copy; 329 temp = to_copy;
330 330
331 in = in_buf; 331 in = in_buf;
332 - out = buf; 332 + out = oss.buf;
333 333
334 while (temp) { 334 while (temp) {
335 int copy; 335 int copy;
336 336
337 - copy = MIN (temp, bufsize - wpos);  
338 - copy_fn (out + wpos, in, copy); 337 + copy = MIN (temp, oss.bufsize - oss.wpos);
  338 + oss.copy_fn (out + oss.wpos, in, copy);
339 339
340 - wpos += copy;  
341 - if (wpos == bufsize) {  
342 - wpos = 0; 340 + oss.wpos += copy;
  341 + if (oss.wpos == oss.bufsize) {
  342 + oss.wpos = 0;
343 } 343 }
344 344
345 temp -= copy; 345 temp -= copy;
346 in += copy; 346 in += copy;
347 - live += copy; 347 + oss.live += copy;
348 } 348 }
349 349
350 return to_copy; 350 return to_copy;
@@ -356,10 +356,34 @@ void AUD_run (void) @@ -356,10 +356,34 @@ void AUD_run (void)
356 int bytes; 356 int bytes;
357 struct audio_buf_info abinfo; 357 struct audio_buf_info abinfo;
358 358
359 - if (0 == live) 359 + if (0 == oss.live)
360 return; 360 return;
361 361
362 - res = ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo); 362 + if (oss.is_mapped) {
  363 + count_info info;
  364 +
  365 + res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info);
  366 + if (-1 == res) {
  367 + int err;
  368 +
  369 + err = errno;
  370 + lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
  371 + return;
  372 + }
  373 +
  374 + if (info.ptr > oss.old_optr) {
  375 + bytes = info.ptr - oss.old_optr;
  376 + }
  377 + else {
  378 + bytes = oss.bufsize + info.ptr - oss.old_optr;
  379 + }
  380 +
  381 + oss.old_optr = info.ptr;
  382 + oss.live -= bytes;
  383 + return;
  384 + }
  385 +
  386 + res = ioctl (oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo);
363 387
364 if (-1 == res) { 388 if (-1 == res) {
365 int err; 389 int err;
@@ -369,7 +393,7 @@ void AUD_run (void) @@ -369,7 +393,7 @@ void AUD_run (void)
369 } 393 }
370 394
371 bytes = abinfo.bytes; 395 bytes = abinfo.bytes;
372 - bytes = MIN (live, bytes); 396 + bytes = MIN (oss.live, bytes);
373 #if 0 397 #if 0
374 bytes = (bytes / fragsize) * fragsize; 398 bytes = (bytes / fragsize) * fragsize;
375 #endif 399 #endif
@@ -377,9 +401,9 @@ void AUD_run (void) @@ -377,9 +401,9 @@ void AUD_run (void)
377 while (bytes) { 401 while (bytes) {
378 int left, play, written; 402 int left, play, written;
379 403
380 - left = bufsize - rpos; 404 + left = oss.bufsize - oss.rpos;
381 play = MIN (left, bytes); 405 play = MIN (left, bytes);
382 - written = write (audio_fd, (void *) ((uint32_t) buf + rpos), play); 406 + written = write (oss.fd, (void *) ((uint32_t) oss.buf + oss.rpos), play);
383 407
384 if (-1 == written) { 408 if (-1 == written) {
385 if (EAGAIN == errno || EINTR == errno) { 409 if (EAGAIN == errno || EINTR == errno) {
@@ -391,12 +415,12 @@ void AUD_run (void) @@ -391,12 +415,12 @@ void AUD_run (void)
391 } 415 }
392 416
393 play = written; 417 play = written;
394 - live -= play;  
395 - rpos += play; 418 + oss.live -= play;
  419 + oss.rpos += play;
396 bytes -= play; 420 bytes -= play;
397 421
398 - if (rpos == bufsize) {  
399 - rpos = 0; 422 + if (oss.rpos == oss.bufsize) {
  423 + oss.rpos = 0;
400 } 424 }
401 } 425 }
402 } 426 }
@@ -406,7 +430,7 @@ static int get_dsp_bytes (void) @@ -406,7 +430,7 @@ static int get_dsp_bytes (void)
406 int res; 430 int res;
407 struct count_info info; 431 struct count_info info;
408 432
409 - res = ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &info); 433 + res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info);
410 if (-1 == res) { 434 if (-1 == res) {
411 int err; 435 int err;
412 436
@@ -420,22 +444,22 @@ static int get_dsp_bytes (void) @@ -420,22 +444,22 @@ static int get_dsp_bytes (void)
420 } 444 }
421 } 445 }
422 446
423 -void AUD_adjust_estimate (int _leftover) 447 +void AUD_adjust_estimate (int leftover)
424 { 448 {
425 - leftover = _leftover; 449 + oss.leftover = leftover;
426 } 450 }
427 451
428 int AUD_get_free (void) 452 int AUD_get_free (void)
429 { 453 {
430 int free, elapsed; 454 int free, elapsed;
431 455
432 - free = bufsize - live; 456 + free = oss.bufsize - oss.live;
433 457
434 if (0 == free) 458 if (0 == free)
435 return 0; 459 return 0;
436 460
437 elapsed = free; 461 elapsed = free;
438 - switch (estimate) { 462 + switch (est) {
439 case DONT: 463 case DONT:
440 break; 464 break;
441 465
@@ -456,16 +480,15 @@ int AUD_get_free (void) @@ -456,16 +480,15 @@ int AUD_get_free (void)
456 480
457 case TID: 481 case TID:
458 { 482 {
459 - static uint64_t old_ticks;  
460 uint64_t ticks, delta; 483 uint64_t ticks, delta;
461 uint64_t ua_elapsed; 484 uint64_t ua_elapsed;
462 uint64_t al_elapsed; 485 uint64_t al_elapsed;
463 486
464 ticks = qemu_get_clock(rt_clock); 487 ticks = qemu_get_clock(rt_clock);
465 - delta = ticks - old_ticks;  
466 - old_ticks = ticks; 488 + delta = ticks - oss.old_ticks;
  489 + oss.old_ticks = ticks;
467 490
468 - ua_elapsed = (delta * bytes_per_second) / 1000; 491 + ua_elapsed = (delta * oss.bytes_per_second) / 1000;
469 al_elapsed = ua_elapsed & ~3ULL; 492 al_elapsed = ua_elapsed & ~3ULL;
470 493
471 ldebug ("tid elapsed %llu bytes\n", ua_elapsed); 494 ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
@@ -475,7 +498,7 @@ int AUD_get_free (void) @@ -475,7 +498,7 @@ int AUD_get_free (void)
475 else 498 else
476 elapsed = al_elapsed; 499 elapsed = al_elapsed;
477 500
478 - elapsed += leftover; 501 + elapsed += oss.leftover;
479 } 502 }
480 } 503 }
481 504
@@ -490,27 +513,47 @@ int AUD_get_free (void) @@ -490,27 +513,47 @@ int AUD_get_free (void)
490 513
491 int AUD_get_live (void) 514 int AUD_get_live (void)
492 { 515 {
493 - return live; 516 + return oss.live;
494 } 517 }
495 518
496 int AUD_get_buffer_size (void) 519 int AUD_get_buffer_size (void)
497 { 520 {
498 - return bufsize; 521 + return oss.bufsize;
  522 +}
  523 +
  524 +#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
  525 +#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
  526 +#define QC_OSS_MMAP "QEMU_OSS_MMAP"
  527 +
  528 +static int get_conf_val (const char *key, int defval)
  529 +{
  530 + int val = defval;
  531 + char *strval;
  532 +
  533 + strval = getenv (key);
  534 + if (strval) {
  535 + val = atoi (strval);
  536 + }
  537 +
  538 + return val;
499 } 539 }
500 540
501 void AUD_init (void) 541 void AUD_init (void)
502 { 542 {
503 int fsp; 543 int fsp;
504 - int _fragsize = 4096;  
505 544
506 DEREF (pab); 545 DEREF (pab);
507 546
508 - fsp = _fragsize; 547 + conf.fragsize = get_conf_val (QC_OSS_FRAGSIZE, conf.fragsize);
  548 + conf.nfrags = get_conf_val (QC_OSS_NFRAGS, conf.nfrags);
  549 + conf.try_mmap = get_conf_val (QC_OSS_MMAP, conf.try_mmap);
  550 +
  551 + fsp = conf.fragsize;
509 if (0 != (fsp & (fsp - 1))) { 552 if (0 != (fsp & (fsp - 1))) {
510 Fail ("fragment size %d is not power of 2", fsp); 553 Fail ("fragment size %d is not power of 2", fsp);
511 } 554 }
512 555
513 - conf_fragsize = lsbindex (fsp); 556 + conf.fragsize = lsbindex (fsp);
514 } 557 }
515 558
516 #else 559 #else