1 /* MikMod sound library
2 (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 /*==============================================================================
23 Driver for GUS cards under DOS
24 Written by Andrew Zabolotny <bit@eltech.ru>
26 ==============================================================================*/
38 #include <sys/farptr.h>
39 #include <sys/nearptr.h>
44 #include "mikmod.h" /* for MikMod_malloc() & co */
46 /********************************************* Private variables/routines *****/
48 /* The Gravis Ultrasound state/info */
51 /* Try to avoid holes in DRAM less than this size */
52 #define DRAM_HOLE_THRESHOLD 8192
53 /* If hole is larger than that, create a free block describing it */
54 #define DRAM_SPLIT_THRESHOLD 64
55 /* The size of DMA buffer used for RAM->DRAM transfers */
56 #define GF1_DMA_BUFFER_SIZE 8192
58 /* Debug macro: useful to change screen locations when some event occurs */
60 # define DEBUG_PRINT(x) printf x;
61 # define DEBUG_OFS(addr, attr) \
64 _dosmemgetw (0xb8780 + addr*2, 1, &x); \
65 if ((x >> 8) != attr) x = '0'; \
66 x = ((x + 1) & 0xff) | (attr << 8); \
67 _dosmemputw (&x, 1, 0xb8780 + addr*2); \
70 # define DEBUG_PRINT(x)
71 # define DEBUG_OFS(addr, attr)
74 static unsigned short __gus_volume_table[512] = {
75 0x0000, 0x7000, 0x7ff0, 0x8800, 0x8ff0, 0x9400, 0x9800, 0x9c00,
76 0x9ff0, 0xa200, 0xa400, 0xa600, 0xa800, 0xaa00, 0xac00, 0xae00,
77 0xaff0, 0xb100, 0xb200, 0xb300, 0xb400, 0xb500, 0xb600, 0xb700,
78 0xb800, 0xb900, 0xba00, 0xbb00, 0xbc00, 0xbd00, 0xbe00, 0xbf00,
79 0xbff0, 0xc080, 0xc100, 0xc180, 0xc200, 0xc280, 0xc300, 0xc380,
80 0xc400, 0xc480, 0xc500, 0xc580, 0xc600, 0xc680, 0xc700, 0xc780,
81 0xc800, 0xc880, 0xc900, 0xc980, 0xca00, 0xca80, 0xcb00, 0xcb80,
82 0xcc00, 0xcc80, 0xcd00, 0xcd80, 0xce00, 0xce80, 0xcf00, 0xcf80,
83 0xcff0, 0xd040, 0xd080, 0xd0c0, 0xd100, 0xd140, 0xd180, 0xd1c0,
84 0xd200, 0xd240, 0xd280, 0xd2c0, 0xd300, 0xd340, 0xd380, 0xd3c0,
85 0xd400, 0xd440, 0xd480, 0xd4c0, 0xd500, 0xd540, 0xd580, 0xd5c0,
86 0xd600, 0xd640, 0xd680, 0xd6c0, 0xd700, 0xd740, 0xd780, 0xd7c0,
87 0xd800, 0xd840, 0xd880, 0xd8c0, 0xd900, 0xd940, 0xd980, 0xd9c0,
88 0xda00, 0xda40, 0xda80, 0xdac0, 0xdb00, 0xdb40, 0xdb80, 0xdbc0,
89 0xdc00, 0xdc40, 0xdc80, 0xdcc0, 0xdd00, 0xdd40, 0xdd80, 0xddc0,
90 0xde00, 0xde40, 0xde80, 0xdec0, 0xdf00, 0xdf40, 0xdf80, 0xdfc0,
91 0xdff0, 0xe020, 0xe040, 0xe060, 0xe080, 0xe0a0, 0xe0c0, 0xe0e0,
92 0xe100, 0xe120, 0xe140, 0xe160, 0xe180, 0xe1a0, 0xe1c0, 0xe1e0,
93 0xe200, 0xe220, 0xe240, 0xe260, 0xe280, 0xe2a0, 0xe2c0, 0xe2e0,
94 0xe300, 0xe320, 0xe340, 0xe360, 0xe380, 0xe3a0, 0xe3c0, 0xe3e0,
95 0xe400, 0xe420, 0xe440, 0xe460, 0xe480, 0xe4a0, 0xe4c0, 0xe4e0,
96 0xe500, 0xe520, 0xe540, 0xe560, 0xe580, 0xe5a0, 0xe5c0, 0xe5e0,
97 0xe600, 0xe620, 0xe640, 0xe660, 0xe680, 0xe6a0, 0xe6c0, 0xe6e0,
98 0xe700, 0xe720, 0xe740, 0xe760, 0xe780, 0xe7a0, 0xe7c0, 0xe7e0,
99 0xe800, 0xe820, 0xe840, 0xe860, 0xe880, 0xe8a0, 0xe8c0, 0xe8e0,
100 0xe900, 0xe920, 0xe940, 0xe960, 0xe980, 0xe9a0, 0xe9c0, 0xe9e0,
101 0xea00, 0xea20, 0xea40, 0xea60, 0xea80, 0xeaa0, 0xeac0, 0xeae0,
102 0xeb00, 0xeb20, 0xeb40, 0xeb60, 0xeb80, 0xeba0, 0xebc0, 0xebe0,
103 0xec00, 0xec20, 0xec40, 0xec60, 0xec80, 0xeca0, 0xecc0, 0xece0,
104 0xed00, 0xed20, 0xed40, 0xed60, 0xed80, 0xeda0, 0xedc0, 0xede0,
105 0xee00, 0xee20, 0xee40, 0xee60, 0xee80, 0xeea0, 0xeec0, 0xeee0,
106 0xef00, 0xef20, 0xef40, 0xef60, 0xef80, 0xefa0, 0xefc0, 0xefe0,
107 0xeff0, 0xf010, 0xf020, 0xf030, 0xf040, 0xf050, 0xf060, 0xf070,
108 0xf080, 0xf090, 0xf0a0, 0xf0b0, 0xf0c0, 0xf0d0, 0xf0e0, 0xf0f0,
109 0xf100, 0xf110, 0xf120, 0xf130, 0xf140, 0xf150, 0xf160, 0xf170,
110 0xf180, 0xf190, 0xf1a0, 0xf1b0, 0xf1c0, 0xf1d0, 0xf1e0, 0xf1f0,
111 0xf200, 0xf210, 0xf220, 0xf230, 0xf240, 0xf250, 0xf260, 0xf270,
112 0xf280, 0xf290, 0xf2a0, 0xf2b0, 0xf2c0, 0xf2d0, 0xf2e0, 0xf2f0,
113 0xf300, 0xf310, 0xf320, 0xf330, 0xf340, 0xf350, 0xf360, 0xf370,
114 0xf380, 0xf390, 0xf3a0, 0xf3b0, 0xf3c0, 0xf3d0, 0xf3e0, 0xf3f0,
115 0xf400, 0xf410, 0xf420, 0xf430, 0xf440, 0xf450, 0xf460, 0xf470,
116 0xf480, 0xf490, 0xf4a0, 0xf4b0, 0xf4c0, 0xf4d0, 0xf4e0, 0xf4f0,
117 0xf500, 0xf510, 0xf520, 0xf530, 0xf540, 0xf550, 0xf560, 0xf570,
118 0xf580, 0xf590, 0xf5a0, 0xf5b0, 0xf5c0, 0xf5d0, 0xf5e0, 0xf5f0,
119 0xf600, 0xf610, 0xf620, 0xf630, 0xf640, 0xf650, 0xf660, 0xf670,
120 0xf680, 0xf690, 0xf6a0, 0xf6b0, 0xf6c0, 0xf6d0, 0xf6e0, 0xf6f0,
121 0xf700, 0xf710, 0xf720, 0xf730, 0xf740, 0xf750, 0xf760, 0xf770,
122 0xf780, 0xf790, 0xf7a0, 0xf7b0, 0xf7c0, 0xf7d0, 0xf7e0, 0xf7f0,
123 0xf800, 0xf810, 0xf820, 0xf830, 0xf840, 0xf850, 0xf860, 0xf870,
124 0xf880, 0xf890, 0xf8a0, 0xf8b0, 0xf8c0, 0xf8d0, 0xf8e0, 0xf8f0,
125 0xf900, 0xf910, 0xf920, 0xf930, 0xf940, 0xf950, 0xf960, 0xf970,
126 0xf980, 0xf990, 0xf9a0, 0xf9b0, 0xf9c0, 0xf9d0, 0xf9e0, 0xf9f0,
127 0xfa00, 0xfa10, 0xfa20, 0xfa30, 0xfa40, 0xfa50, 0xfa60, 0xfa70,
128 0xfa80, 0xfa90, 0xfaa0, 0xfab0, 0xfac0, 0xfad0, 0xfae0, 0xfaf0,
129 0xfb00, 0xfb10, 0xfb20, 0xfb30, 0xfb40, 0xfb50, 0xfb60, 0xfb70,
130 0xfb80, 0xfb90, 0xfba0, 0xfbb0, 0xfbc0, 0xfbd0, 0xfbe0, 0xfbf0,
131 0xfc00, 0xfc10, 0xfc20, 0xfc30, 0xfc40, 0xfc50, 0xfc60, 0xfc70,
132 0xfc80, 0xfc90, 0xfca0, 0xfcb0, 0xfcc0, 0xfcd0, 0xfce0, 0xfcf0,
133 0xfd00, 0xfd10, 0xfd20, 0xfd30, 0xfd40, 0xfd50, 0xfd60, 0xfd70,
134 0xfd80, 0xfd90, 0xfda0, 0xfdb0, 0xfdc0, 0xfdd0, 0xfde0, 0xfdf0,
135 0xfe00, 0xfe10, 0xfe20, 0xfe30, 0xfe40, 0xfe50, 0xfe60, 0xfe70,
136 0xfe80, 0xfe90, 0xfea0, 0xfeb0, 0xfec0, 0xfed0, 0xfee0, 0xfef0,
137 0xff00, 0xff10, 0xff20, 0xff30, 0xff40, 0xff50, 0xff60, 0xff70,
138 0xff80, 0xff90, 0xffa0, 0xffb0, 0xffc0, 0xffd0, 0xffe0, 0xfff0
141 /* Wait a bit for GUS before doing something
142 * Mark function as volatile: don't allow it to be inlined.
143 * It *should* be slow, no need to make it work faster :-)
145 #if !defined(__GNUC__) || (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ == 0)
146 # define _func_noinline volatile /* match original code */
147 # define _func_noclone
149 /* avoid warnings from newer gcc:
150 * "function definition has qualified void return type" and
151 * function return types not compatible due to 'volatile' */
152 # define _func_noinline __attribute__((__noinline__))
153 # if (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
154 # define _func_noclone
156 # define _func_noclone __attribute__((__noclone__))
163 inportb(GF1_MIX_CTRL);
164 inportb(GF1_MIX_CTRL);
165 inportb(GF1_MIX_CTRL);
166 inportb(GF1_MIX_CTRL);
167 inportb(GF1_MIX_CTRL);
168 inportb(GF1_MIX_CTRL);
169 inportb(GF1_MIX_CTRL);
170 inportb(GF1_MIX_CTRL);
173 static void __gus_stop_controller(unsigned char gf1reg)
175 register unsigned char value = __gus_inregb(gf1reg);
176 __gus_outregb(gf1reg, (value | GF1VC_STOPPED | GF1VC_STOP) &
177 ~(GF1VC_IRQ_PENDING | GF1VC_IRQ));
180 /* Returns 1 if volume is already at given position */
181 static boolean __gus_volume_ramp_to(unsigned short volume,
183 unsigned char vol_ctrl)
185 int svol = __gus_inregw(GF1R_VOLUME) & 0xfff0;
188 /* First of all, disable volume ramp */
189 __gus_stop_controller(GF1R_VOLUME_CONTROL);
191 /* If voice is stopped, set the volume to zero and return */
192 if (__gus_inregb(GF1R_VOICE_CONTROL) & GF1VC_STOPPED) {
193 __gus_outregw(GF1R_VOLUME, 0);
197 /* Avoid clicks when volume ramp goes too high or too low */
207 /* Adjust start/end positions */
209 unsigned short tmp = evol;
212 vol_ctrl |= GF1VL_BACKWARD;
215 /* If we already are (near) the target volume, quit */
216 if (evol - svol < 0x1000) {
217 __gus_outregw(GF1R_VOLUME, volume);
221 __gus_outregb(GF1R_VOLUME_START, svol >> 8);
222 __gus_outregb(GF1R_VOLUME_END, evol >> 8);
223 __gus_outregb(GF1R_VOLUME_RATE, rate);
224 __gus_outregb_slow(GF1R_VOLUME_CONTROL, vol_ctrl);
228 static inline void __gus_stop_voice()
230 __gus_stop_controller(GF1R_VOICE_CONTROL);
231 __gus_outregb_slow(GF1R_VOICE_CONTROL, GF1VC_STOPPED | GF1VC_STOP);
234 /* The GUS IRQ handler */
235 static void gf1_irq()
237 unsigned char irq_source; /* The contents of GF1_IRQ_STATUS register */
238 boolean timer_cb = 0; /* Call timer callback function */
242 while ((irq_source = inportb(GF1_IRQ_STATUS))) {
245 if (irq_source & GF1M_IRQ_DMA_COMPLETE) {
247 /* reset the IRQ pending bit */
248 __gus_inregb(GF1R_DMA_CONTROL);
251 if (gus.dma_callback)
255 if (irq_source & (GF1M_IRQ_WAVETABLE | GF1M_IRQ_ENVELOPE)) {
257 unsigned int done_mask = 0;
259 /* IRQ bits are inverse (i.e. 0 = IRQ pending) */
260 while ((vcirq = __gus_inregb(GF1R_IRQ_SOURCE) ^
261 (GF1IRQ_WAVE | GF1IRQ_VOLUME)) &
262 (GF1IRQ_WAVE | GF1IRQ_VOLUME)) {
263 unsigned long voice = (vcirq & 0x1f);
264 unsigned char voice_ctl, volume_ctl;
265 unsigned int voice_mask = (1 << voice);
267 /* Don't handle more than one IRQ from same voice */
268 if (done_mask & voice_mask)
271 done_mask |= voice_mask;
273 /* Read voice/volume selection registers */
274 __gus_select_voice(voice);
275 voice_ctl = __gus_inregb(GF1R_VOICE_CONTROL);
276 volume_ctl = __gus_inregb(GF1R_VOLUME_CONTROL);
278 if ((vcirq & GF1IRQ_WAVE) && (gus.wt_callback)
279 && !(gus.eow_ignore & voice_mask)) {
281 gus.wt_callback(voice, voice_ctl, volume_ctl);
284 if ((vcirq & GF1IRQ_VOLUME) && (gus.vl_callback)) {
286 gus.vl_callback(voice, voice_ctl, volume_ctl);
291 /* Reset timers that sent this IRQ */
292 if (irq_source & (GF1M_IRQ_TIMER1 | GF1M_IRQ_TIMER2)) {
293 unsigned char timer_ctl = gus.timer_ctl_reg;
295 if (irq_source & GF1M_IRQ_TIMER1)
296 timer_ctl &= ~GF1M_TIMER1;
298 if (irq_source & GF1M_IRQ_TIMER2)
299 timer_ctl &= ~GF1M_TIMER2;
301 __gus_outregb_slow(GF1R_TIMER_CONTROL, timer_ctl);
302 __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
305 if (irq_source & GF1M_IRQ_TIMER1)
306 if (--gus.t1_countdown == 0) {
307 gus.t1_countdown = gus.t1_multiple;
312 if (gus.t1_callback) {
318 if (irq_source & GF1M_IRQ_TIMER2)
319 if (--gus.t2_countdown == 0) {
320 gus.t2_countdown = gus.t2_multiple;
329 /* The following are not used and implemented yet */
330 if (irq_source & (GF1M_IRQ_MIDI_TX | GF1M_IRQ_MIDI_RX)) {
335 irq_ack(gus.gf1_irq);
337 if (timer_cb && gus.timer_callback)
338 gus.timer_callback();
341 static void gf1_irq_end()
345 static boolean __gus_detect()
347 /* A relatively relaxed autodetection;
348 We don't count on DRAM: GUS PnP could not have it
349 (although its anyway bad for us)
351 __gus_select_voice(0);
353 __gus_outregw(GF1R_FREQUENCY, 0x1234);
354 __gus_outregw(GF1R_VOLUME, 0x5670);
355 return ((__gus_inregw(GF1R_FREQUENCY) & 0xfffe) == 0x1234)
356 && ((__gus_inregw(GF1R_VOLUME) & 0xfff0) == 0x5670);
359 static void __gus_reset(boolean reset_io_dma)
361 static unsigned char irqctl[16] = { 0, 0, 1, 3, 0, 2, 0, 4, 0, 0, 0, 5, 6, 0, 0, 7 };
362 static unsigned char dmactl[8] = { 0, 1, 0, 2, 0, 3, 4, 5 };
363 unsigned char irqtmp, dmatmp;
365 /* Disable interrupts while resetting to avoid spurious IRQs */
366 int i, timer, old_ints = disable();
368 /* Stop the timer so that GUS IRQ won't clobber registers */
369 timer = (gus.timer_ctl_reg & GF1M_TIMER1);
375 __gus_outregb(GF1R_RESET, 0);
376 for (i = 0; i < 10; i++)
378 __gus_outregb(GF1R_RESET, GF1M_MASTER_RESET);
379 for (i = 0; i < 10; i++)
382 outportb(GF1_MIDI_CTRL, GF1M_MIDI_RESET);
383 for (i = 0; i < 10; i++)
385 outportb(GF1_MIDI_CTRL, 0);
387 /* Reset all IRQ sources */
388 __gus_outregb(GF1R_DMA_CONTROL, 0);
389 __gus_outregb(GF1R_TIMER_CONTROL, 0);
390 __gus_outregb(GF1R_SAMPLE_CONTROL, 0);
392 /* Reset all voices */
393 gus_reset(gus.voices, gus.dynmask);
395 /* Flush any pending IRQs */
396 inportb(GF1_IRQ_STATUS);
397 __gus_inregb(GF1R_DMA_CONTROL);
398 __gus_inregb(GF1R_SAMPLE_CONTROL);
399 __gus_inregb(GF1R_IRQ_SOURCE);
402 /* Now set up the GUS card to required IRQs and DMAs */
403 if (gus.irq[0] == gus.irq[1])
404 irqtmp = irqctl[gus.irq[0]] | GF1M_IRQ_EQUAL;
406 irqtmp = irqctl[gus.irq[0]] | (irqctl[gus.irq[1]] << 3);
408 if (gus.dma[0] == gus.dma[1])
409 dmatmp = dmactl[gus.dma[0]] | GF1M_DMA_EQUAL;
411 dmatmp = dmactl[gus.dma[0]] | (dmactl[gus.dma[1]] << 3);
413 /* Reset IRQs if possible */
415 GF1M_MIXER_NO_LINE_IN | GF1M_MIXER_NO_OUTPUT | GF1M_MIXER_GF1_IRQ;
416 if (gus.version >= GUS_CARD_VERSION_CLASSIC1) {
417 outportb(GF1_REG_CTRL, 0x05);
418 outportb(GF1_MIX_CTRL, gus.mixer);
419 outportb(GF1_IRQ_CTRL, 0x00); /* Reset IRQs */
420 outportb(GF1_REG_CTRL, 0x00);
423 /* Set up DMA channels: NEVER disable MIXER_GF1_IRQ in the future */
424 outportb(GF1_MIX_CTRL, gus.mixer);
425 outportb(GF1_IRQ_CTRL, dmatmp);
427 /* Set up IRQ channels */
428 outportb(GF1_MIX_CTRL, gus.mixer | GF1M_CONTROL_SELECT);
429 outportb(GF1_IRQ_CTRL, irqtmp);
432 __gus_outregb(GF1R_RESET, GF1M_MASTER_RESET | GF1M_OUTPUT_ENABLE | GF1M_MASTER_IRQ);
435 /* Flush IRQs again */
436 inportb(GF1_IRQ_STATUS);
437 __gus_inregb(GF1R_DMA_CONTROL);
438 __gus_inregb(GF1R_SAMPLE_CONTROL);
439 __gus_inregb(GF1R_IRQ_SOURCE);
441 _irq_ack(gus.irq[0]);
442 _irq_ack(gus.irq[1]);
445 gus_timer_continue();
451 __gus_mixer_output(1);
454 /* Transfer a block of data from GUS DRAM to main RAM through port I/O */
455 static void __gus_transfer_io_in(unsigned long address, unsigned char *source,
459 register unsigned int size64k;
461 size64k = 0x10000 - (address & 0xffff);
466 __gus_outregb(GF1R_DRAM_HIGH, address >> 16);
468 __gus_outregw(GF1R_DRAM_LOW, address++);
469 *source++ = inportb(GF1_DRAM);
474 /* Transfer a block of data into GUS DRAM through port I/O */
475 static void __gus_transfer_io(unsigned long address, unsigned char *source,
476 unsigned long size, int flags)
479 register unsigned int size64k;
481 size64k = 0x10000 - (address & 0xffff);
486 __gus_outregb(GF1R_DRAM_HIGH, address >> 16);
487 if (flags & GUS_WAVE_INVERT)
488 if (flags & GUS_WAVE_16BIT)
489 while (size64k-- && size64k--) {
490 __gus_outregw(GF1R_DRAM_LOW, address++);
491 outportb(GF1_DRAM, *source++);
492 __gus_outregw(GF1R_DRAM_LOW, address++);
493 outportb(GF1_DRAM, (*source++) ^ 0x80);
496 __gus_outregw(GF1R_DRAM_LOW, address++);
497 outportb(GF1_DRAM, (*source++) ^ 0x80);
500 __gus_outregw(GF1R_DRAM_LOW, address++);
501 outportb(GF1_DRAM, *source++);
506 /* Wait for DMA transfer to finish between 8-9 1/18sec timer ticks */
507 static int __gus_wait_dma()
511 timer = _farnspeekl(0x46c);
512 while (gus.dma_active)
513 if (_farnspeekl(0x46c) - timer > 8) {
514 /* Force DMA abort since something went wrong */
522 /* Transfer a block of data into GUS DRAM through DMA controller */
523 static void __gus_transfer_dma(unsigned long address, unsigned char *source,
524 unsigned long size, int flags)
526 unsigned char dma_control;
527 unsigned long bytes_left;
528 unsigned long cur_size;
529 unsigned long dest_addr;
531 if ((gus.dma[0] > 3) || (flags & GUS_WAVE_16BIT))
532 size = (size + 1) & ~1;
538 cur_size = gus.dma_buff->size;
539 if (cur_size > bytes_left)
540 cur_size = bytes_left;
541 bytes_left -= cur_size;
544 if (gus.dma_buff->linear != source)
545 memmove(gus.dma_buff->linear, source, cur_size);
549 /* Disable GUS -> DMA tie */
550 __gus_outregb(GF1R_DMA_CONTROL, 0);
554 dma_start(gus.dma_buff, cur_size, DMA_MODE_WRITE);
557 /* Reset the DMA IRQ pending bit if set */
558 __gus_inregb(GF1R_DMA_CONTROL);
560 /* The 16-bit DMA channels needs a slightly different approach */
561 dma_control = GF1M_DMAR_ENABLE | GF1M_DMAR_IRQ_ENABLE | gus.dma_rate;
562 if (gus.dma[0] > 3) {
563 dest_addr = __gus_convert_addr16(dest_addr);
564 dma_control |= GF1M_DMAR_CHAN16;
567 __gus_outregw(GF1R_DMA_ADDRESS, dest_addr >> 4);
569 if (flags & GUS_WAVE_16BIT)
570 dma_control |= GF1M_DMAR_DATA16;
571 if (flags & GUS_WAVE_INVERT)
572 dma_control |= GF1M_DMAR_TOGGLE_SIGN;
574 /* Tell GUS to start transfer */
575 __gus_outregb(GF1R_DMA_CONTROL, dma_control);
579 static void __gus_detect_version()
583 switch (gus.version = inportb(GF1_REVISION)) {
585 gus.version = GUS_CARD_VERSION_CLASSIC_ICS;
593 gus.version = GUS_CARD_VERSION_CLASSIC_ICS;
597 gus.version = GUS_CARD_VERSION_MAX;
601 gus.version = GUS_CARD_VERSION_MAX1;
605 gus.version = GUS_CARD_VERSION_ACE;
608 gus.version = GUS_CARD_VERSION_EXTREME;
612 outportb(GF1_REG_CTRL, 0x20);
613 tmp = inportb(GF1_REG_CTRL);
614 if ((tmp != 0xff) && (tmp & 0x06))
615 gus.version = GUS_CARD_VERSION_CLASSIC1;
617 gus.version = GUS_CARD_VERSION_CLASSIC;
620 /* Hmm... unknown revision. Assume a safe Classic model */
622 fprintf(stderr, "libgus: Unknown board revision (%02x)\n",
625 gus.version = GUS_CARD_VERSION_CLASSIC;
630 static void __gus_detect_transfer()
632 unsigned char *outbuff, *inbuff;
633 unsigned int i, j, seed = 0x13243546;
634 __gus_transfer_func func;
636 #define TRANSFER_SIZE 0x4000
638 outbuff = (unsigned char *) MikMod_malloc(TRANSFER_SIZE);
639 inbuff = (unsigned char *) MikMod_malloc(TRANSFER_SIZE);
641 /* Suppose we have an malfunctioning GUS */
644 for (i = (gus.dma_buff ? 0 : 4); i <= 4; i++) {
647 gus.dma_rate = GF1M_DMAR_RATE0;
648 func = __gus_transfer_dma;
651 gus.dma_rate = GF1M_DMAR_RATE1;
652 func = __gus_transfer_dma;
655 gus.dma_rate = GF1M_DMAR_RATE2;
656 func = __gus_transfer_dma;
659 gus.dma_rate = GF1M_DMAR_RATE3;
660 func = __gus_transfer_dma;
663 func = __gus_transfer_io;
667 /* Fill data array each time with pseudo-random values */
668 for (j = 0; j < TRANSFER_SIZE; j++)
669 outbuff[j] = seed, seed =
670 ((seed + 358979323) ^ (seed >> 16)) * 314159265;
672 /* Transfer the random array to GUS */
673 /* Poke a security fence around dest block */
674 __gus_poke(0x100 - 1, 0xAA);
675 __gus_poke(0x100 - 2, 0x55);
676 __gus_poke(0x100 + TRANSFER_SIZE + 0, 0xAA);
677 __gus_poke(0x100 + TRANSFER_SIZE + 1, 0x55);
679 func(0x100, outbuff, TRANSFER_SIZE, 0);
681 if (__gus_wait_dma() == 0) {
682 /* Check if the security fence was not damaged */
683 if ((__gus_peek(0x100 - 1) != 0xAA)
684 || (__gus_peek(0x100 - 2) != 0x55)
685 || (__gus_peek(0x100 + TRANSFER_SIZE + 0) != 0xAA)
686 || (__gus_peek(0x100 + TRANSFER_SIZE + 1) != 0x55))
689 /* Now check if GUS DRAM really data that we expects to be transferred */
690 __gus_transfer_io_in(0x100, inbuff, TRANSFER_SIZE);
691 if (memcmp(outbuff, inbuff, TRANSFER_SIZE) == 0) {
701 MikMod_free(outbuff);
704 static void __gus_detect_memory()
707 for (size = 0; size < 1024; size += 256) {
708 __gus_poke(size * 1024, 0xaa);
709 if (__gus_peek(size * 1024) != 0xaa)
711 __gus_poke(size * 1024, 0x55);
712 if (__gus_peek(size * 1024) != 0x55)
718 static void __gus_init()
720 char *gusenv = getenv("ULTRASND");
722 memset((void *)&gus, 0, sizeof(gus));
728 sscanf(gusenv, "%x,%d,%d,%d,%d", &gus.port, &gus.dma[0], &gus.dma[1],
729 &gus.irq[0], &gus.irq[1]);
731 /* A relaxed sanity check */
732 if ((gus.port < 0x100) || (gus.port > 0x1000)
733 || (gus.irq[0] < 2) || (gus.irq[0] > 15)
734 || (gus.irq[1] < 2) || (gus.irq[1] > 15)
735 || (gus.dma[0] < 0) || (gus.dma[0] > 7)
736 || (gus.dma[1] < 0) || (gus.dma[1] > 7))
740 gus.timer_ctl = GF1M_MASK_TIMER1 | GF1M_MASK_TIMER2;
742 /* Detect if the card is really there */
743 if (__gus_detect() == 0)
746 /* Detect the version of Gravis Ultrasound */
747 __gus_detect_version();
752 /* Detect the amount of on-board memory */
753 __gus_detect_memory();
758 static void __gus_kick(gus_wave_t * wave, unsigned int wave_offset)
763 if (wave->format & GUS_WAVE_16BIT)
765 if (wave->format & GUS_WAVE_BACKWARD)
766 vc |= GF1VC_BACKWARD;
767 if (wave->format & GUS_WAVE_LOOP) {
768 vc |= GF1VC_LOOP_ENABLE;
769 if (wave->format & GUS_WAVE_BIDIR)
772 __gus_set_loop_start(vc, (wave->begin.memory << 4) + wave->loop_start);
773 if (wave->format & GUS_WAVE_LOOP)
774 __gus_set_loop_end(vc, (wave->begin.memory << 4) + wave->loop_end);
776 __gus_set_loop_end(vc, (wave->begin.memory + wave->size) << 4);
777 __gus_set_current(vc, (wave->begin.memory << 4) + wave_offset + 100);
778 __gus_outregb_slow(GF1R_VOICE_CONTROL, vc);
781 /* Timer 1 callback function (updates voices) */
782 static void __gus_timer_update()
785 unsigned long wave_offset;
786 unsigned char *src, *top;
787 unsigned int vmask = (1 << gus.cur_voice);
789 if (!gus.cmd_pool_ready)
792 __gus_select_voice(gus.cur_voice);
795 top = gus.cmd_pool + gus.cmd_pool_top;
798 #define GET_W *((unsigned short *)src)
799 #define GET_L *((unsigned long *)src)
805 __gus_select_voice(gus.cur_voice = GET_B++);
806 vmask = (1 << gus.cur_voice);
809 /* __gus_outregw(GF1R_FREQUENCY, GET_W++);*/
810 __gus_outregw(GF1R_FREQUENCY, *(unsigned short *)src);
814 __gus_outregb(GF1R_BALANCE, GET_B++);
817 __gus_volume_ramp_to(gus.cur_vol[gus.cur_voice] =
818 /* GET_W++, GUS_VOLCHANGE_RAMP, GF1VL_IRQ);*/
819 *(unsigned short *)src, GUS_VOLCHANGE_RAMP, GF1VL_IRQ);
822 case PCMD_VOLUME_PREPARE:
823 /* gus.cur_vol[gus.cur_voice] = GET_W++;*/
824 gus.cur_vol[gus.cur_voice] = *(unsigned short *)src;
828 /* wave_offset = GET_L++;*/
829 wave_offset = *(unsigned long *)src;
833 /* wave = (gus_wave_t *) GET_L++;*/
834 wave = (gus_wave_t *) *(unsigned long *)src;
836 gus.cur_wave[gus.cur_voice] = wave;
837 gus.kick_offs[gus.cur_voice] = wave_offset;
838 if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ)) {
839 __gus_kick(wave, wave_offset);
840 __gus_volume_ramp_to(gus.cur_vol[gus.cur_voice],
841 GUS_VOLCHANGE_RAMP, GF1VL_IRQ);
843 gus.voice_kick[gus.cur_voice] = 1;
845 gus.eow_ignore |= vmask;
848 /* If volume is close to nothing, abort immediately instead of
850 gus.cur_vol[gus.cur_voice] = 0;
851 gus.cur_wave[gus.cur_voice] = NULL;
852 if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ))
856 __gus_outregb_slow(GF1R_VOICE_CONTROL,
857 (__gus_inregb(GF1R_VOICE_CONTROL) | GF1VC_IRQ)
858 & ~GF1VC_LOOP_ENABLE);
859 __gus_outregb_slow(GF1R_VOLUME_CONTROL,
860 __gus_inregb(GF1R_VOLUME_CONTROL) &
864 /* Alarm! Break out immediately */
874 gus.cmd_pool_ready = 0;
875 gus.cmd_pool_top = 0;
878 static void __gus_wavetable_update(unsigned int voice, unsigned int voice_ctl,
879 unsigned int volume_ctl)
881 gus_wave_t *wave = gus.cur_wave[voice];
883 if (!wave || !(wave->format & GUS_WAVE_LOOP)) {
885 gus.cur_wave[voice] = NULL;
886 gus.cur_vol[voice] = 0;
887 if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ))
892 static void __gus_volume_update(unsigned int voice, unsigned int voice_ctl,
893 unsigned int volume_ctl)
895 __gus_volume_ramp_to(gus.cur_vol[voice], GUS_VOLCHANGE_RAMP, GF1VL_IRQ);
896 if (!gus.cur_wave[voice])
898 else if (gus.voice_kick[voice])
899 __gus_kick(gus.cur_wave[voice], gus.kick_offs[voice]);
900 gus.voice_kick[voice] = 0;
903 /***************************************************** GUS memory manager *****/
905 /* Mark all GUS memory as available */
906 static void __gus_mem_clear()
908 __gus_mcb *cur = gus.mcb;
911 __gus_mcb *next = cur->next;
918 gus.mcb = (__gus_mcb *) MikMod_malloc(sizeof(__gus_mcb));
920 gus.mcb->next = gus.mcb->prev = NULL;
922 gus.mcb->size = gus.ram * 1024;
926 /* Return amount of free memory */
927 static unsigned int __gus_mem_get_free()
929 __gus_mcb *cur = gus.mcb;
930 unsigned int size = 0;
933 return gus.ram * 1024;
944 /* Return largest size for a 8-bit sample */
945 static unsigned int __gus_mem_get_free_8()
947 __gus_mcb *cur = gus.mcb;
948 unsigned int size = 0;
954 if (cur->free && (cur->size > size))
962 /* Return largest size for a 16-bit sample */
963 static unsigned int __gus_mem_get_free_16()
965 __gus_mcb *cur = gus.mcb;
966 unsigned int size = 0;
973 unsigned int size16 = cur->size;
975 /* 16-bit samples cannot cross 256K boundaries */
976 tmp = 0x40000 - (cur->addr & 0x3ffff);
979 /* 16-bit samples should be aligned on a 32-byte boundary */
980 size16 -= (32 - cur->addr) & 0x1f;
985 /* Now try vice versa: skip a portion of aligned memory */
987 (cur->addr + cur->size) - ((cur->addr + 0x3ffff) & ~0x3ffff);
988 if ((size16 < 0x7fffffff) && (size16 > size))
997 /* Allocate a segment of GUS DRAM for a sample with given bits per sample.
998 * The algorithm tries to find the smallest free block that fits requested
999 * size; but if found free block is larger by some (large) delta than
1000 * requested block size, the largest possible block is preffered.
1002 static unsigned int __gus_mem_alloc(unsigned int size, int bits16)
1004 __gus_mcb *cur = gus.mcb;
1005 __gus_mcb *best_max = NULL, *best_min = NULL;
1006 unsigned int best_max_delta = 0, best_min_delta = 0xffffffff;
1007 unsigned int best_max_prefix = 0, best_min_prefix = 0;
1008 unsigned int memaddr, memsize;
1010 if (!gus.open || !size || (bits16 && size > 0x40000))
1013 /* Round block size up to nearest acceptable DMA bound */
1015 size = (size + 0x1f) & ~0x1f;
1017 size = (size + 0x0f) & ~0x0f;
1021 unsigned char fits = 0;
1023 memsize = cur->size;
1024 memaddr = cur->addr;
1027 /* 16-bit samples cannot cross 256K boundaries */
1028 unsigned int tmp = 256 * 1024 - (memaddr & 0x3ffff);
1031 /* 16-bit samples should be aligned on a 32-byte boundary */
1032 memsize -= (32 - memaddr) & 0x1f;
1033 memaddr = (memaddr + 0x1f) & ~0x1f;
1036 /* If block fits, analyze it */
1037 if (size <= memsize)
1039 /* Look if we still can complete the request by creating a free
1041 else if (size <= cur->size) {
1042 /* Align start address to next 256k boundary */
1043 unsigned int endaddr = cur->addr + cur->size;
1044 memaddr = (cur->addr + 0x3ffff) & ~0x3ffff;
1045 /* Can we split current block by inserting a free block at the
1047 if ((memaddr < endaddr) && (memaddr + size <= endaddr))
1052 unsigned int size_delta = cur->size - size;
1053 unsigned int size_prefix = memaddr - cur->addr;
1054 if (size_delta < best_min_delta)
1055 best_min = cur, best_min_delta =
1056 size_delta, best_min_prefix = size_prefix;
1057 if (size_delta > best_max_delta)
1058 best_max = cur, best_max_delta =
1059 size_delta, best_max_prefix = size_prefix;
1069 /* If minimal block that fits is too large, use largest block that fits */
1070 /* But if using the maximal block is going to create a small hole, forget
1072 if ((best_max_prefix == 0)
1073 || (best_max_prefix >= DRAM_HOLE_THRESHOLD)
1074 || (best_min_prefix != 0))
1076 ((best_min_delta < DRAM_HOLE_THRESHOLD) &&
1077 (best_max_delta >= DRAM_HOLE_THRESHOLD)) ||
1078 ((best_min_prefix > 0) && (best_min_prefix < DRAM_HOLE_THRESHOLD)
1079 && ((best_max_prefix == 0) ||
1080 (best_max_prefix > best_min_prefix))) ||
1081 ((best_min_prefix != 0) && (best_max_prefix == 0))) {
1082 best_min = best_max;
1083 best_min_delta = best_max_delta;
1084 best_min_prefix = best_max_prefix;
1087 /* Compute the DRAM address to return */
1088 memaddr = best_min->addr + best_min_prefix;
1090 memaddr = (memaddr + 0x1f) & ~0x1f;
1092 memaddr = (memaddr + 0x0f) & ~0x0f;
1094 /* If we have a considerable hole at the beginning of sample,
1095 create a free node describing the hole */
1096 if (memaddr - best_min->addr >= DRAM_SPLIT_THRESHOLD) {
1097 __gus_mcb *newmcb = (__gus_mcb *) MikMod_malloc(sizeof(__gus_mcb));
1098 newmcb->prev = best_min->prev;
1099 newmcb->next = best_min;
1100 newmcb->addr = best_min->addr;
1101 newmcb->size = memaddr - best_min->addr;
1103 best_min->addr = memaddr;
1104 best_min->size -= newmcb->size;
1105 best_min->prev = newmcb;
1107 newmcb->prev->next = newmcb;
1110 /* Compute the size of hole at the end of block */
1111 memsize = (best_min->addr + best_min->size) - (memaddr + size);
1113 /* Split the block if the block is larger than requested amount */
1114 if (memsize > DRAM_SPLIT_THRESHOLD) {
1115 /* The next node cannot be free since free blocks are always glued
1117 __gus_mcb *newmcb = (__gus_mcb *) MikMod_malloc(sizeof(__gus_mcb));
1118 best_min->size -= memsize;
1119 newmcb->prev = best_min;
1120 newmcb->next = best_min->next;
1121 newmcb->addr = best_min->addr + best_min->size;
1122 newmcb->size = memsize;
1125 best_min->next->prev = newmcb;
1126 best_min->next = newmcb;
1133 static void __gus_mem_free(unsigned int addr)
1135 __gus_mcb *cur = gus.mcb;
1137 if (!cur->free && (cur->addr <= addr) &&
1138 (cur->addr + cur->size > addr)) {
1141 /* If next block is free as well, link them together */
1142 if (cur->next && cur->next->free) {
1143 __gus_mcb *next = cur->next;
1144 cur->size += next->size;
1145 cur->next = next->next;
1147 next->next->prev = cur;
1151 /* If previous block is free, link current block with it */
1152 if (cur->prev && cur->prev->free) {
1153 cur->prev->size += cur->size;
1154 cur->prev->next = cur->next;
1156 cur->next->prev = cur->prev;
1165 static void __gus_mem_pack()
1171 /* Debug dump of GUS DRAM heap */
1172 void __gus_mem_dump()
1174 __gus_mcb *cur = gus.mcb;
1175 fprintf(stderr, "/-- Offset --+-- Prev --+-- Size --+-- Free --\\\n");
1177 fprintf(stderr, "| %08X | %08X | %6d | %s |\n",
1178 cur->addr, cur->prev ? cur->prev->addr : -1, cur->size,
1179 cur->free ? "yes" : " no");
1182 fprintf(stderr, "\\------------+----------+----------+----------/\n");
1187 /************************************************** Middle-level routines *****/
1189 static int __gus_instrument_free(gus_instrument_t * instrument)
1191 gus_instrument_t **cur_instr;
1192 gus_layer_t *cur_layer;
1193 gus_wave_t *cur_wave, *wave_head;
1195 /* Remove the instrument from the list of registered instruments */
1196 cur_instr = (gus_instrument_t **) & gus.instr;
1197 while (*cur_instr) {
1198 if (*cur_instr == instrument) {
1199 *cur_instr = instrument->next;
1202 cur_instr = &(*cur_instr)->next;
1208 for (cur_layer = instrument->info.layer; cur_layer;
1209 cur_layer = cur_layer->next)
1210 /* Free all waves */
1211 for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next) {
1213 wave_head = cur_wave;
1214 if (cur_wave->begin.memory != (unsigned int)-1)
1215 __gus_mem_free(cur_wave->begin.memory);
1218 MikMod_free(wave_head);
1220 MikMod_free(instrument->info.layer);
1221 if (instrument->name)
1222 MikMod_free(instrument->name);
1223 MikMod_free(instrument);
1227 static gus_instrument_t *__gus_instrument_get(int program)
1229 gus_instrument_t *cur_instr = (gus_instrument_t *) gus.instr;
1231 if (cur_instr->number.instrument == program)
1233 cur_instr = cur_instr->next;
1238 static gus_instrument_t *__gus_instrument_copy(gus_instrument_t * instrument)
1240 gus_instrument_t **cur_instr, *instr;
1241 gus_layer_t *cur_layer, *dest_layer;
1242 gus_wave_t *cur_wave, *dest_wave;
1243 unsigned int waves, layers;
1245 if (!instrument || !instrument->info.layer || !gus.open)
1248 if (__gus_instrument_get(instrument->number.instrument))
1251 instr = (gus_instrument_t *) MikMod_malloc(sizeof(gus_instrument_t));
1252 *instr = *instrument;
1254 if (instrument->name)
1255 instr->name = MikMod_strdup(instrument->name);
1257 /* Make a copy of all layers at once */
1258 for (layers = 0, cur_layer = instrument->info.layer; cur_layer; layers++)
1259 cur_layer = cur_layer->next;
1261 if (!(dest_layer = instr->info.layer = (gus_layer_t *) MikMod_malloc(sizeof(gus_layer_t) * layers))) {
1263 MikMod_free(instr->name);
1267 for (waves = 0, cur_layer = instrument->info.layer; cur_layer;
1268 cur_layer = cur_layer->next) {
1269 *dest_layer = *cur_layer;
1270 dest_layer->wave = NULL;
1271 /* Count the total number of waves */
1272 for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next)
1274 if (cur_layer->next)
1275 dest_layer->next = dest_layer + 1;
1277 dest_layer->next = NULL;
1281 /* Allocate memory for waves */
1282 if (!(dest_wave = (gus_wave_t *) MikMod_malloc(sizeof(gus_wave_t) * waves))) {
1283 MikMod_free(instr->info.layer);
1285 MikMod_free(instr->name);
1289 for (cur_layer = instrument->info.layer, dest_layer = instr->info.layer;
1290 cur_layer; cur_layer = cur_layer->next, dest_layer = dest_layer->next)
1291 /* Copy all waves */
1292 for (cur_wave = cur_layer->wave; cur_wave; cur_wave = cur_wave->next) {
1293 if (!dest_layer->wave)
1294 dest_layer->wave = dest_wave;
1296 *dest_wave = *cur_wave;
1297 /* Mark DRAM address as unallocated */
1298 dest_wave->begin.memory = -1;
1301 dest_wave->next = (dest_wave + 1);
1303 dest_wave->next = NULL;
1307 /* Insert the instrument into list of registered instruments */
1308 cur_instr = (gus_instrument_t **) & gus.instr;
1310 cur_instr = &(*cur_instr)->next;
1316 static void __gus_instruments_clear()
1318 gus_instrument_t *next_instr, *cur_instr = (gus_instrument_t *) gus.instr;
1320 next_instr = cur_instr->next;
1321 __gus_instrument_free(cur_instr);
1322 cur_instr = next_instr;
1326 /******************************************************* libGUS interface *****/
1328 /* return value: number of GUS cards installed in system */
1333 return gus.ok ? 1 : 0;
1336 int gus_info(gus_info_t * info, int reread)
1343 strcpy((char *)info->id, "gus0");
1344 info->flags = (gus.ram ? GUS_STRU_INFO_F_PCM : 0);
1345 info->version = gus.version;
1346 info->port = gus.port;
1347 info->irq = gus.irq[0];
1348 info->dma1 = gus.dma[0];
1349 info->dma2 = gus.dma[1];
1351 info->mixing_freq = gus.freq;
1353 info->memory_size = gus.ram * 1024;
1354 info->memory_free = __gus_mem_get_free();
1355 info->memory_block_8 = __gus_mem_get_free_8();
1356 info->memory_block_16 = __gus_mem_get_free_16();
1360 int gus_open(int card, size_t queue_buffer_size, int non_block)
1362 __dpmi_meminfo struct_info, pool_info;
1367 if (!gus.ok || gus.open || card != 0)
1370 /* Now lock the gus structure in memory */
1371 struct_info.address = __djgpp_base_address + (unsigned long)&gus;
1372 struct_info.size = sizeof(gus);
1373 if (__dpmi_lock_linear_region(&struct_info))
1376 /* And hook the GF1 interrupt */
1377 __irq_stack_count = 4;
1379 irq_hook(gus.irq[0], gf1_irq, (long)gf1_irq_end - (long)gf1_irq);
1380 __irq_stack_count = 1;
1382 __dpmi_unlock_linear_region(&struct_info);
1386 /* Enable the interrupt */
1387 irq_enable(gus.gf1_irq);
1391 /* Allocate a DMA buffer: if we fail, we just use I/O so don't fail */
1392 if ((gus.transfer == NULL) || (gus.transfer == __gus_transfer_dma))
1393 gus.dma_buff = dma_allocate(gus.dma[0], GF1_DMA_BUFFER_SIZE);
1395 gus.dma_buff = NULL;
1397 /* Detect the best available RAM -> DRAM transfer function */
1398 if (!gus.transfer) {
1399 __gus_detect_transfer();
1400 if (gus.transfer != __gus_transfer_dma || !gus.transfer)
1401 dma_free(gus.dma_buff), gus.dma_buff = NULL;
1403 /* If no transfer function worked, fail */
1404 if (!gus.transfer) {
1406 dma_free(gus.dma_buff);
1407 gus.dma_buff = NULL;
1409 __dpmi_unlock_linear_region(&struct_info);
1410 irq_unhook(gus.gf1_irq);
1416 /* Allocate and lock command pool buffer */
1417 if (queue_buffer_size < 64)
1418 queue_buffer_size = 64;
1419 if (queue_buffer_size > 16384)
1420 queue_buffer_size = 16384;
1421 gus.cmd_pool = (unsigned char *) MikMod_malloc(queue_buffer_size);
1422 pool_info.address = __djgpp_base_address + (unsigned long)&gus.cmd_pool;
1423 pool_info.size = sizeof(queue_buffer_size);
1424 if (__dpmi_lock_linear_region(&pool_info)) {
1426 dma_free(gus.dma_buff);
1427 gus.dma_buff = NULL;
1429 __dpmi_unlock_linear_region(&struct_info);
1430 irq_unhook(gus.gf1_irq);
1438 gus.t1_callback = __gus_timer_update;
1439 gus.wt_callback = __gus_wavetable_update;
1440 gus.vl_callback = __gus_volume_update;
1441 gus_do_tempo(60); /* Default is 60 Hz */
1446 int gus_close(int card)
1448 __dpmi_meminfo struct_info;
1450 if (!gus.open || card != 0)
1453 /* First reset the card: disable any operation it can currently perform */
1458 /* Stop the timer */
1461 /* Free DMA buffer if used */
1463 dma_free(gus.dma_buff);
1464 gus.dma_buff = NULL;
1467 /* And unhook the GF1 interrupt */
1468 irq_unhook(gus.gf1_irq);
1471 /* Unlock the gus structure */
1472 struct_info.address = __djgpp_base_address + (unsigned long)&gus;
1473 struct_info.size = sizeof(gus);
1474 __dpmi_unlock_linear_region(&struct_info);
1477 __gus_instruments_clear();
1482 int gus_select(int card)
1484 if (!gus.open || (card != 0))
1490 /* return value: same as gus_reset function
1491 note: this command doesn't change number of active voices and doesn't do
1493 int gus_reset_engine_only()
1495 gus.timer_base = 100;
1499 int gus_reset(int voices, unsigned int channel_voices)
1501 static unsigned short freq_table[32 - 14 + 1] = {
1502 44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843,
1503 25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293
1508 /* No support for dynamically allocated voices for now */
1509 gus.dynmask = channel_voices;
1516 /* Stop the timer so that GUS IRQ won't clobber registers */
1517 timer = (gus.timer_ctl_reg & GF1M_TIMER1);
1521 /* Stop all voices */
1522 for (voice = 0; voice < 32; voice++) {
1523 __gus_select_voice(voice);
1525 gus.cur_wave[voice] = NULL;
1526 gus.cur_vol[voice] = 0;
1530 /* Reset voice parameters to reasonable values */
1531 __gus_set_current(0, 0);
1532 __gus_set_loop_start(0, 0);
1533 __gus_set_loop_end(0, 0);
1534 __gus_outregw(GF1R_VOLUME, 0);
1535 __gus_outregb(GF1R_VOLUME_RATE, 0);
1536 __gus_outregb(GF1R_VOLUME_START, 0);
1537 __gus_outregb(GF1R_VOLUME_END, 0);
1538 __gus_outregb(GF1R_BALANCE, 0x7);
1541 voice = (__gus_inregb(GF1R_VOICES) & 0x1f) + 1;
1543 if (voice != voices) {
1544 int reset = __gus_inregb(GF1R_RESET);
1545 __gus_outregb(GF1R_RESET, reset & ~GF1M_OUTPUT_ENABLE);
1547 __gus_outregb(GF1R_VOICES, 0xc0 | (voices - 1));
1549 __gus_outregb(GF1R_RESET, reset);
1552 /* Compute the discretization frequence */
1553 gus.voices = voices;
1557 gus.freq = freq_table[voices - 14];
1559 gus_reset_engine_only();
1562 gus_timer_continue();
1569 DEBUG_PRINT(("gus_do_flush: top = %d\n", gus.cmd_pool_top))
1570 gus.cmd_pool_ready = 1;
1575 void gus_do_tempo(unsigned int tempo)
1577 DEBUG_PRINT(("gus_do_tempo (%d)\n", tempo))
1578 gus_timer_tempo(tempo);
1582 /* set voice frequency in Hz */
1583 void gus_do_voice_frequency(unsigned char voice, unsigned int freq)
1585 DEBUG_PRINT(("gus_do_voice_frequency (%d, %d)\n", voice, freq))
1586 __pool_select_voice(voice);
1587 __pool_command_w(PCMD_FREQ,
1588 (((freq << 9) + (gus.freq >> 1)) / gus.freq) << 1);
1591 /* set voice pan (0-16384) (full left - full right) */
1592 void gus_do_voice_pan(unsigned char voice, unsigned short pan)
1594 DEBUG_PRINT(("gus_do_voice_pan (%d, %d)\n", voice, pan))
1598 __pool_select_voice(voice);
1599 __pool_command_b(PCMD_PAN, pan);
1602 /* set voice volume level 0-16384 (linear) */
1603 void gus_do_voice_volume(unsigned char voice, unsigned short vol)
1605 DEBUG_PRINT(("gus_do_voice_volume (%d, %d)\n", voice, vol))
1608 __pool_select_voice(voice);
1609 __pool_command_w(PCMD_VOLUME, __gus_volume_table[vol >> 5]);
1614 * program : program # or ~0 = current
1615 * freq : frequency in Hz
1616 * volume : volume level (0-16384) or ~0 = current
1617 * pan : pan level (0-16384) or ~0 = current
1619 void gus_do_voice_start(unsigned char voice, unsigned int program,
1620 unsigned int freq, unsigned short volume,
1623 gus_do_voice_start_position(voice, program, freq, volume, pan, 0);
1628 * program : program # or ~0 = current
1629 * freq : frequency in Hz
1630 * volume : volume level (0-16384) or ~0 = current
1631 * pan : pan level (0-16384) or ~0 = current
1632 * position : offset to wave in bytes * 16 (lowest 4 bits - fraction)
1634 void gus_do_voice_start_position(unsigned char voice, unsigned int program,
1635 unsigned int freq, unsigned short volume,
1636 unsigned short pan, unsigned int position)
1638 gus_instrument_t *instrument;
1642 ("gus_do_voice_start_position (%d, %d, pos: %d)\n", voice,
1645 instrument = __gus_instrument_get(program);
1648 || !instrument->info.layer
1649 || !instrument->info.layer->wave
1650 || instrument->flags == GUS_INSTR_F_NOT_FOUND
1651 || instrument->flags == GUS_INSTR_F_NOT_LOADED) return;
1653 gus_do_voice_frequency(voice, freq);
1654 gus_do_voice_pan(voice, pan);
1656 /* We have to set volume different way, to avoid unneeded work in handler */
1657 if (volume > 0x3fff)
1659 __pool_command_w(PCMD_VOLUME_PREPARE, __gus_volume_table[volume >> 5]);
1661 switch (instrument->mode) {
1662 case GUS_INSTR_SIMPLE:
1663 wave = instrument->info.layer->wave;
1665 __pool_command_l(PCMD_OFFSET, position);
1666 __pool_command_l(PCMD_START, (unsigned long)wave);
1672 * mode = 0 : stop voice now
1673 * mode = 1 : disable wave loop and finish it
1675 void gus_do_voice_stop(unsigned char voice, unsigned char mode)
1677 __pool_select_voice(voice);
1679 __pool_command(PCMD_STOP_LOOP);
1681 __pool_command(PCMD_STOP);
1684 /* wait x ticks - this command is block separator
1685 all commands between blocks are interpreted in the begining of one tick */
1686 void gus_do_wait(unsigned int ticks)
1688 DEBUG_PRINT(("gus_do_wait (%d)\n", ticks))
1690 ticks += gus.t1_ticks;
1691 while ((int)(ticks - gus.t1_ticks) > 0);
1694 int gus_get_voice_status(int voice)
1696 __gus_select_voice(voice);
1697 return __gus_inregb(GF1R_VOICE_CONTROL) & GF1VC_STOPPED ? 0 : 1;
1700 /* return value: file handle (descriptor) for /dev/gus */
1701 int gus_get_handle()
1703 /* Return stdout handle so that select() will "work" with it */
1707 /* return value: zero if instrument was successfully allocated */
1708 int gus_memory_alloc(gus_instrument_t * instrument)
1710 gus_instrument_t *instr = __gus_instrument_copy(instrument);
1711 gus_layer_t *cur_layer;
1712 gus_wave_t *cur_wave;
1714 DEBUG_PRINT(("gus_memory_alloc (%d)\n", instrument->number.instrument))
1719 for (cur_layer = instr->info.layer; cur_layer;
1720 cur_layer = cur_layer->next) for (cur_wave = cur_layer->wave;
1722 cur_wave = cur_wave->next) {
1723 if (cur_layer->mode == GUS_INSTR_SIMPLE) {
1724 cur_wave->begin.memory = __gus_mem_alloc(cur_wave->size,
1727 if (cur_wave->begin.memory == (unsigned int)-1) {
1728 __gus_instrument_free(instr);
1731 gus.transfer(cur_wave->begin.memory, cur_wave->begin.ptr,
1732 cur_wave->size, cur_wave->format);
1733 } else if (cur_layer->mode == GUS_INSTR_PATCH)
1734 /* not supported yet */ ;
1740 /* return value: zero if instrument was successfully removed */
1741 int gus_memory_free(gus_instrument_t * instrument)
1743 gus_instrument_t *cur_instr = gus.instr;
1745 DEBUG_PRINT(("gus_memory_free (%d)\n", instrument->number.instrument))
1747 for (; cur_instr; cur_instr = cur_instr->next)
1748 if (cur_instr->number.instrument == instrument->number.instrument)
1749 return __gus_instrument_free(cur_instr);
1754 /* return value: unused gus memory in bytes */
1755 int gus_memory_free_size()
1757 return __gus_mem_get_free();
1760 /* return value: zero if success */
1761 int gus_memory_pack()
1767 /* return value: gus memory size in bytes */
1768 int gus_memory_size()
1770 return gus.ram * 1024;
1773 /* return value: current largest free block for 8-bit or 16-bit wave */
1774 int gus_memory_free_block(int w_16bit)
1776 return w_16bit ? __gus_mem_get_free_16() : __gus_mem_get_free_8();
1779 /* input value: see to GUS_DOWNLOAD_MODE_XXXX constants (gus.h)
1780 return value: zero if samples & instruments was successfully removed from
1781 GF1 memory manager */
1782 int gus_memory_reset(int mode)
1785 __gus_instruments_clear();
1789 /* return value: zero if command queue was successfully flushed */
1790 int gus_queue_flush()
1795 /* input value: echo buffer size in items (if 0 - erase echo buffer) */
1796 int gus_queue_read_set_size(int items)
1801 /* input value: write queue size in items (each item have 8 bytes) */
1802 int gus_queue_write_set_size(int items)
1807 /* return value: zero if successfull */
1808 int gus_timer_start()
1810 gus.timer_ctl_reg |= GF1M_TIMER1;
1811 __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
1813 gus.timer_ctl = gus.timer_ctl & ~GF1M_MASK_TIMER1;
1814 outportb(GF1_TIMER_CTRL, 0x04);
1815 outportb(GF1_TIMER_DATA, gus.timer_ctl | GF1M_START_TIMER1);
1819 /* return value: zero if timer was stoped */
1820 int gus_timer_stop()
1822 gus.timer_ctl_reg &= ~GF1M_TIMER1;
1823 __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
1825 gus.timer_ctl = gus.timer_ctl | GF1M_MASK_TIMER1;
1826 outportb(GF1_TIMER_CTRL, 0x04);
1827 outportb(GF1_TIMER_DATA, gus.timer_ctl);
1831 /* return value: zero if setup was success */
1832 int gus_timer_tempo(int ticks)
1834 unsigned int counter;
1836 /* Limit ticks per second to 1..1000 range */
1842 /* GF1 timer1 period is 80 usecs, 12500 times per second */
1843 counter = 1250000 / (ticks * gus.timer_base);
1844 gus.t1_multiple = 1;
1845 while (counter > 255) {
1847 gus.t1_multiple <<= 1;
1849 gus.t1_countdown = gus.t1_multiple;
1850 __gus_outregb(GF1R_TIMER1, 256 - counter);
1854 /* return value: zero if timer will be continue */
1855 int gus_timer_continue()
1857 return gus_timer_start();
1860 /* return value: zero if setup was success (default timebase = 100) */
1861 int gus_timer_base(int base)
1863 gus.timer_base = base;
1867 void gus_timer_callback(void (*timer_callback) ())
1869 gus.timer_callback = timer_callback;
1872 void gus_convert_delta(unsigned int type, unsigned char *dest,
1873 unsigned char *src, size_t size)
1875 if (!(type & GUS_WAVE_DELTA))
1878 /* This doesn't depend much on wave signedness, since addition/subtraction
1879 do not depend on operand signedness */
1880 if (type & GUS_WAVE_16BIT) {
1881 unsigned short delta = type & GUS_WAVE_UNSIGNED ? 0x8000 : 0;
1883 delta = *(unsigned short *)dest = *(unsigned short *)src + delta;
1884 src += sizeof(unsigned short);
1885 dest += sizeof(unsigned short);
1888 unsigned char delta = type & GUS_WAVE_UNSIGNED ? 0x80 : 0;
1890 delta = *(unsigned char *)dest = *(unsigned char *)src + delta;
1897 int gus_dma_usage (int use)
1901 gus.transfer = __gus_transfer_io;
1905 #endif /* DRV_ULTRA */