initial import
[dosrtxon] / libs / mikmod / drivers / dos / dosgus.c
1 /*      MikMod sound library
2         (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
3         complete list.
4
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.
9
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.
14
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
18         02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23   Driver for GUS cards under DOS
24   Written by Andrew Zabolotny <bit@eltech.ru>
25
26 ==============================================================================*/
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #ifdef DRV_ULTRA
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <dos.h>
37 #include <dpmi.h>
38 #include <sys/farptr.h>
39 #include <sys/nearptr.h>
40 #include <go32.h>
41 #include <string.h>
42
43 #include "dosgus.h"
44 #include "mikmod.h" /* for MikMod_malloc() & co */
45
46 /********************************************* Private variables/routines *****/
47
48 /* The Gravis Ultrasound state/info */
49 __gus_state gus;
50
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
57
58 /* Debug macro: useful to change screen locations when some event occurs */
59 #ifdef MIKMOD_DEBUG
60 #  define DEBUG_PRINT(x) printf x;
61 #  define DEBUG_OFS(addr, attr)                 \
62    {                                            \
63      unsigned short x;                          \
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);     \
68    }
69 #else
70 #  define DEBUG_PRINT(x)
71 #  define DEBUG_OFS(addr, attr)
72 #endif
73
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
139 };
140
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 :-)
144  */
145 #if !defined(__GNUC__) || (__GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ == 0)
146 # define _func_noinline volatile /* match original code */
147 # define _func_noclone
148 #else
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
155 # else
156 #  define _func_noclone __attribute__((__noclone__))
157 # endif
158 #endif
159 _func_noinline
160 _func_noclone
161  void __gus_delay()
162 {
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);
171 }
172
173 static void __gus_stop_controller(unsigned char gf1reg)
174 {
175         register unsigned char value = __gus_inregb(gf1reg);
176         __gus_outregb(gf1reg, (value | GF1VC_STOPPED | GF1VC_STOP) &
177                       ~(GF1VC_IRQ_PENDING | GF1VC_IRQ));
178 }
179
180 /* Returns 1 if volume is already at given position */
181 static boolean __gus_volume_ramp_to(unsigned short volume,
182                                     unsigned char rate,
183                                     unsigned char vol_ctrl)
184 {
185         int svol = __gus_inregw(GF1R_VOLUME) & 0xfff0;
186         int evol = volume;
187
188         /* First of all, disable volume ramp */
189         __gus_stop_controller(GF1R_VOLUME_CONTROL);
190
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);
194                 return 1;
195         }
196
197         /* Avoid clicks when volume ramp goes too high or too low */
198         if (svol < 0x0400)
199                 svol = 0x0400;
200         if (svol > 0xfc00)
201                 svol = 0xfc00;
202         if (evol < 0x0400)
203                 evol = 0x0400;
204         if (evol > 0xfc00)
205                 evol = 0xfc00;
206
207         /* Adjust start/end positions */
208         if (svol > evol) {
209                 unsigned short tmp = evol;
210                 evol = svol;
211                 svol = tmp;
212                 vol_ctrl |= GF1VL_BACKWARD;
213         }
214
215         /* If we already are (near) the target volume, quit */
216         if (evol - svol < 0x1000) {
217                 __gus_outregw(GF1R_VOLUME, volume);
218                 return 1;
219         }
220
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);
225         return 0;
226 }
227
228 static inline void __gus_stop_voice()
229 {
230         __gus_stop_controller(GF1R_VOICE_CONTROL);
231         __gus_outregb_slow(GF1R_VOICE_CONTROL, GF1VC_STOPPED | GF1VC_STOP);
232 }
233
234 /* The GUS IRQ handler */
235 static void gf1_irq()
236 {
237         unsigned char irq_source;       /* The contents of GF1_IRQ_STATUS register */
238         boolean timer_cb = 0;           /* Call timer callback function */
239
240         DEBUG_OFS(0, 0xCE)
241         gus.eow_ignore = 0;
242         while ((irq_source = inportb(GF1_IRQ_STATUS))) {
243                 DEBUG_OFS(1, 0xCE)
244
245                   if (irq_source & GF1M_IRQ_DMA_COMPLETE) {
246                         DEBUG_OFS(4, 0x9F)
247                           /* reset the IRQ pending bit */
248                           __gus_inregb(GF1R_DMA_CONTROL);
249                         gus.dma_active = 0;
250
251                         if (gus.dma_callback)
252                                 gus.dma_callback();
253                 }
254
255                 if (irq_source & (GF1M_IRQ_WAVETABLE | GF1M_IRQ_ENVELOPE)) {
256                         unsigned char vcirq;
257                         unsigned int done_mask = 0;
258
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);
266
267                                 /* Don't handle more than one IRQ from same voice */
268                                 if (done_mask & voice_mask)
269                                         continue;
270
271                                 done_mask |= voice_mask;
272
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);
277
278                                 if ((vcirq & GF1IRQ_WAVE) && (gus.wt_callback)
279                                         && !(gus.eow_ignore & voice_mask)) {
280                                         DEBUG_OFS(5, 0xAF)
281                                         gus.wt_callback(voice, voice_ctl, volume_ctl);
282                                 }
283
284                                 if ((vcirq & GF1IRQ_VOLUME) && (gus.vl_callback)) {
285                                         DEBUG_OFS(6, 0xAF)
286                                         gus.vl_callback(voice, voice_ctl, volume_ctl);
287                                 }
288                         }
289                 }
290
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;
294
295                         if (irq_source & GF1M_IRQ_TIMER1)
296                                 timer_ctl &= ~GF1M_TIMER1;
297
298                         if (irq_source & GF1M_IRQ_TIMER2)
299                                 timer_ctl &= ~GF1M_TIMER2;
300
301                         __gus_outregb_slow(GF1R_TIMER_CONTROL, timer_ctl);
302                         __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
303                 }
304
305                 if (irq_source & GF1M_IRQ_TIMER1)
306                         if (--gus.t1_countdown == 0) {
307                                 gus.t1_countdown = gus.t1_multiple;
308                                 gus.t1_ticks++;
309
310                                 DEBUG_OFS(2, 0xCF)
311
312                                 if (gus.t1_callback) {
313                                         timer_cb = 1;
314                                         gus.t1_callback();
315                                 }
316                         }
317
318                 if (irq_source & GF1M_IRQ_TIMER2)
319                         if (--gus.t2_countdown == 0) {
320                                 gus.t2_countdown = gus.t2_multiple;
321                                 gus.t2_ticks++;
322
323                                 DEBUG_OFS(3, 0xCF)
324
325                                 if (gus.t2_callback)
326                                         gus.t2_callback();
327                         }
328 #if 0
329                 /* The following are not used and implemented yet */
330                 if (irq_source & (GF1M_IRQ_MIDI_TX | GF1M_IRQ_MIDI_RX)) {
331                 }
332 #endif
333         }
334
335         irq_ack(gus.gf1_irq);
336
337         if (timer_cb && gus.timer_callback)
338                 gus.timer_callback();
339 }
340
341 static void gf1_irq_end()
342 {
343 }
344
345 static boolean __gus_detect()
346 {
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)
350          */
351         __gus_select_voice(0);
352         __gus_stop_voice();
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);
357 }
358
359 static void __gus_reset(boolean reset_io_dma)
360 {
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;
364
365         /* Disable interrupts while resetting to avoid spurious IRQs */
366         int i, timer, old_ints = disable();
367
368         /* Stop the timer so that GUS IRQ won't clobber registers */
369         timer = (gus.timer_ctl_reg & GF1M_TIMER1);
370         if (timer)
371                 gus_timer_stop();
372
373         gus.dma_active = 0;
374
375         __gus_outregb(GF1R_RESET, 0);
376         for (i = 0; i < 10; i++)
377                 __gus_delay();
378         __gus_outregb(GF1R_RESET, GF1M_MASTER_RESET);
379         for (i = 0; i < 10; i++)
380                 __gus_delay();
381
382         outportb(GF1_MIDI_CTRL, GF1M_MIDI_RESET);
383         for (i = 0; i < 10; i++)
384                 __gus_delay();
385         outportb(GF1_MIDI_CTRL, 0);
386
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);
391
392         /* Reset all voices */
393         gus_reset(gus.voices, gus.dynmask);
394
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);
400
401         if (reset_io_dma) {
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;
405                 else
406                         irqtmp = irqctl[gus.irq[0]] | (irqctl[gus.irq[1]] << 3);
407
408                 if (gus.dma[0] == gus.dma[1])
409                         dmatmp = dmactl[gus.dma[0]] | GF1M_DMA_EQUAL;
410                 else
411                         dmatmp = dmactl[gus.dma[0]] | (dmactl[gus.dma[1]] << 3);
412
413                 /* Reset IRQs if possible */
414                 gus.mixer =
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);
421                 }
422
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);
426
427                 /* Set up IRQ channels */
428                 outportb(GF1_MIX_CTRL, gus.mixer | GF1M_CONTROL_SELECT);
429                 outportb(GF1_IRQ_CTRL, irqtmp);
430         }
431
432         __gus_outregb(GF1R_RESET, GF1M_MASTER_RESET | GF1M_OUTPUT_ENABLE | GF1M_MASTER_IRQ);
433         __gus_delay();
434
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);
440
441         _irq_ack(gus.irq[0]);
442         _irq_ack(gus.irq[1]);
443
444         if (timer)
445                 gus_timer_continue();
446
447         if (old_ints)
448                 enable();
449
450         /* Enable output */
451         __gus_mixer_output(1);
452 }
453
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,
456                                  unsigned long size)
457 {
458         while (size) {
459                 register unsigned int size64k;
460
461                 size64k = 0x10000 - (address & 0xffff);
462                 if (size64k > size)
463                         size64k = size;
464                 size -= size64k;
465
466                 __gus_outregb(GF1R_DRAM_HIGH, address >> 16);
467                 while (size64k--) {
468                         __gus_outregw(GF1R_DRAM_LOW, address++);
469                         *source++ = inportb(GF1_DRAM);
470                 }
471         }
472 }
473
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)
477 {
478         while (size) {
479                 register unsigned int size64k;
480
481                 size64k = 0x10000 - (address & 0xffff);
482                 if (size64k > size)
483                         size64k = size;
484                 size -= size64k;
485
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);
494                         } else
495                                 while (size64k--) {
496                                         __gus_outregw(GF1R_DRAM_LOW, address++);
497                                         outportb(GF1_DRAM, (*source++) ^ 0x80);
498                 } else
499                         while (size64k--) {
500                                 __gus_outregw(GF1R_DRAM_LOW, address++);
501                                 outportb(GF1_DRAM, *source++);
502                         }
503         }
504 }
505
506 /* Wait for DMA transfer to finish between 8-9 1/18sec timer ticks */
507 static int __gus_wait_dma()
508 {
509         unsigned long timer;
510         _farsetsel(_dos_ds);
511         timer = _farnspeekl(0x46c);
512         while (gus.dma_active)
513                 if (_farnspeekl(0x46c) - timer > 8) {
514                         /* Force DMA abort since something went wrong */
515                         __gus_reset(0);
516                         return -1;
517                 }
518
519         return 0;
520 }
521
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)
525 {
526         unsigned char dma_control;
527         unsigned long bytes_left;
528         unsigned long cur_size;
529         unsigned long dest_addr;
530
531         if ((gus.dma[0] > 3) || (flags & GUS_WAVE_16BIT))
532                 size = (size + 1) & ~1;
533
534         bytes_left = size;
535         while (bytes_left) {
536                 __gus_wait_dma();
537
538                 cur_size = gus.dma_buff->size;
539                 if (cur_size > bytes_left)
540                         cur_size = bytes_left;
541                 bytes_left -= cur_size;
542                 dest_addr = address;
543
544                 if (gus.dma_buff->linear != source)
545                         memmove(gus.dma_buff->linear, source, cur_size);
546                 source += cur_size;
547                 address += cur_size;
548
549                 /* Disable GUS -> DMA tie */
550                 __gus_outregb(GF1R_DMA_CONTROL, 0);
551                 __gus_delay();
552
553                 /* Set up the DMA */
554                 dma_start(gus.dma_buff, cur_size, DMA_MODE_WRITE);
555                 gus.dma_active = 1;
556
557                 /* Reset the DMA IRQ pending bit if set */
558                 __gus_inregb(GF1R_DMA_CONTROL);
559
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;
565                 }
566
567                 __gus_outregw(GF1R_DMA_ADDRESS, dest_addr >> 4);
568
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;
573
574                 /* Tell GUS to start transfer */
575                 __gus_outregb(GF1R_DMA_CONTROL, dma_control);
576         }
577 }
578
579 static void __gus_detect_version()
580 {
581         unsigned char tmp;
582
583         switch (gus.version = inportb(GF1_REVISION)) {
584           case 5:
585                 gus.version = GUS_CARD_VERSION_CLASSIC_ICS;
586                 gus.ics = 1;
587                 gus.ics_flipped = 1;
588                 break;
589           case 6:
590           case 7:
591           case 8:
592           case 9:
593                 gus.version = GUS_CARD_VERSION_CLASSIC_ICS;
594                 gus.ics = 1;
595                 break;
596           case 10:
597                 gus.version = GUS_CARD_VERSION_MAX;
598                 gus.codec = 1;
599                 break;
600           case 11:
601                 gus.version = GUS_CARD_VERSION_MAX1;
602                 gus.codec = 1;
603                 break;
604           case 0x30:
605                 gus.version = GUS_CARD_VERSION_ACE;
606                 break;
607           case 0x50:
608                 gus.version = GUS_CARD_VERSION_EXTREME;
609                 break;
610           case 0xff:
611                 /* Pre-3.7 board */
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;
616                 else
617                         gus.version = GUS_CARD_VERSION_CLASSIC;
618                 break;
619           default:
620                 /* Hmm... unknown revision. Assume a safe Classic model */
621 #ifdef MIKMOD_DEBUG
622                 fprintf(stderr, "libgus: Unknown board revision (%02x)\n",
623                                 gus.version);
624 #endif
625                 gus.version = GUS_CARD_VERSION_CLASSIC;
626                 break;
627         }
628 }
629
630 static void __gus_detect_transfer()
631 {
632         unsigned char *outbuff, *inbuff;
633         unsigned int i, j, seed = 0x13243546;
634         __gus_transfer_func func;
635
636 #define TRANSFER_SIZE   0x4000
637
638         outbuff = (unsigned char *) MikMod_malloc(TRANSFER_SIZE);
639         inbuff = (unsigned char *) MikMod_malloc(TRANSFER_SIZE);
640
641         /* Suppose we have an malfunctioning GUS */
642         gus.transfer = NULL;
643
644         for (i = (gus.dma_buff ? 0 : 4); i <= 4; i++) {
645                 switch (i) {
646                   case 0:
647                         gus.dma_rate = GF1M_DMAR_RATE0;
648                         func = __gus_transfer_dma;
649                         break;
650                   case 1:
651                         gus.dma_rate = GF1M_DMAR_RATE1;
652                         func = __gus_transfer_dma;
653                         break;
654                   case 2:
655                         gus.dma_rate = GF1M_DMAR_RATE2;
656                         func = __gus_transfer_dma;
657                         break;
658                   case 3:
659                         gus.dma_rate = GF1M_DMAR_RATE3;
660                         func = __gus_transfer_dma;
661                         break;
662                   case 4:
663                         func = __gus_transfer_io;
664                         break;
665                 }
666
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;
671
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);
678
679                 func(0x100, outbuff, TRANSFER_SIZE, 0);
680
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))
687                                 continue;
688
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) {
692                                 gus.transfer = func;
693                                 break;
694                         }
695                 }
696         }
697
698 #undef TRANSFER_SIZE
699
700         MikMod_free(inbuff);
701         MikMod_free(outbuff);
702 }
703
704 static void __gus_detect_memory()
705 {
706         unsigned int size;
707         for (size = 0; size < 1024; size += 256) {
708                 __gus_poke(size * 1024, 0xaa);
709                 if (__gus_peek(size * 1024) != 0xaa)
710                         break;
711                 __gus_poke(size * 1024, 0x55);
712                 if (__gus_peek(size * 1024) != 0x55)
713                         break;
714         }
715         gus.ram = size;
716 }
717
718 static void __gus_init()
719 {
720         char *gusenv = getenv("ULTRASND");
721
722         memset((void *)&gus, 0, sizeof(gus));
723         gus.cmd_voice = -1;
724
725         if (!gusenv)
726                 return;
727
728         sscanf(gusenv, "%x,%d,%d,%d,%d", &gus.port, &gus.dma[0], &gus.dma[1],
729                    &gus.irq[0], &gus.irq[1]);
730
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))
737                 return;
738
739         gus.voices = 32;
740         gus.timer_ctl = GF1M_MASK_TIMER1 | GF1M_MASK_TIMER2;
741
742         /* Detect if the card is really there */
743         if (__gus_detect() == 0)
744                 return;
745
746         /* Detect the version of Gravis Ultrasound */
747         __gus_detect_version();
748
749         /* Reset the card */
750         __gus_reset(1);
751
752         /* Detect the amount of on-board memory */
753         __gus_detect_memory();
754
755         gus.ok = 1;
756 }
757
758 static void __gus_kick(gus_wave_t * wave, unsigned int wave_offset)
759 {
760         unsigned char vc;
761
762         vc = GF1VC_IRQ;
763         if (wave->format & GUS_WAVE_16BIT)
764                 vc |= GF1VC_DATA16;
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)
770                         vc |= GF1VC_BI_LOOP;
771         }
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);
775         else
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);
779 }
780
781 /* Timer 1 callback function (updates voices) */
782 static void __gus_timer_update()
783 {
784         gus_wave_t *wave;
785         unsigned long wave_offset;
786         unsigned char *src, *top;
787         unsigned int vmask = (1 << gus.cur_voice);
788
789         if (!gus.cmd_pool_ready)
790                 return;
791
792         __gus_select_voice(gus.cur_voice);
793         wave_offset = 0;
794         src = gus.cmd_pool;
795         top = gus.cmd_pool + gus.cmd_pool_top;
796
797 #define GET_B   *src
798 #define GET_W   *((unsigned short *)src)
799 #define GET_L   *((unsigned long *)src)
800
801         while (src < top) {
802                 __gus_delay();
803                 switch (GET_B++) {
804                   case PCMD_VOICE:
805                         __gus_select_voice(gus.cur_voice = GET_B++);
806                         vmask = (1 << gus.cur_voice);
807                         break;
808                   case PCMD_FREQ:
809                 /*      __gus_outregw(GF1R_FREQUENCY, GET_W++);*/
810                         __gus_outregw(GF1R_FREQUENCY, *(unsigned short *)src);
811                         src += 2;
812                         break;
813                   case PCMD_PAN:
814                         __gus_outregb(GF1R_BALANCE, GET_B++);
815                         break;
816                   case PCMD_VOLUME:
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);
820                                                                 src += 2;
821                         break;
822                   case PCMD_VOLUME_PREPARE:
823                 /*      gus.cur_vol[gus.cur_voice] = GET_W++;*/
824                         gus.cur_vol[gus.cur_voice] = *(unsigned short *)src;
825                         src += 2;
826                         break;
827                   case PCMD_OFFSET:
828                 /*      wave_offset = GET_L++;*/
829                         wave_offset = *(unsigned long *)src;
830                         src += 4;
831                         break;
832                   case PCMD_START:
833                 /*      wave = (gus_wave_t *) GET_L++;*/
834                         wave = (gus_wave_t *) *(unsigned long *)src;
835                         src += 4;
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);
842                         } else
843                                 gus.voice_kick[gus.cur_voice] = 1;
844                         wave_offset = 0;
845                         gus.eow_ignore |= vmask;
846                         break;
847                   case PCMD_STOP:
848                         /* If volume is close to nothing, abort immediately instead of
849                            ramping */
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))
853                                 __gus_stop_voice();
854                         break;
855                   case PCMD_STOP_LOOP:
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) &
861                                                            ~GF1VL_ROLLOVER);
862                         break;
863                   default:
864                         /* Alarm! Break out immediately */
865                         src = top;
866                         break;
867                 }
868         }
869
870 #undef GET_B
871 #undef GET_W
872 #undef GET_L
873
874         gus.cmd_pool_ready = 0;
875         gus.cmd_pool_top = 0;
876 }
877
878 static void __gus_wavetable_update(unsigned int voice, unsigned int voice_ctl,
879                                                                    unsigned int volume_ctl)
880 {
881         gus_wave_t *wave = gus.cur_wave[voice];
882
883         if (!wave || !(wave->format & GUS_WAVE_LOOP)) {
884                 __gus_stop_voice();
885                 gus.cur_wave[voice] = NULL;
886                 gus.cur_vol[voice] = 0;
887                 if (__gus_volume_ramp_to(0, GUS_VOLCHANGE_RAMP, GF1VL_IRQ))
888                         __gus_stop_voice();
889         }
890 }
891
892 static void __gus_volume_update(unsigned int voice, unsigned int voice_ctl,
893                                                                 unsigned int volume_ctl)
894 {
895         __gus_volume_ramp_to(gus.cur_vol[voice], GUS_VOLCHANGE_RAMP, GF1VL_IRQ);
896         if (!gus.cur_wave[voice])
897                 __gus_stop_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;
901 }
902
903 /***************************************************** GUS memory manager *****/
904
905 /* Mark all GUS memory as available */
906 static void __gus_mem_clear()
907 {
908         __gus_mcb *cur = gus.mcb;
909
910         while (cur) {
911                 __gus_mcb *next = cur->next;
912                 if (cur != gus.mcb)
913                         MikMod_free(cur);
914                 cur = next;
915         }
916
917         if (!gus.mcb)
918                 gus.mcb = (__gus_mcb *) MikMod_malloc(sizeof(__gus_mcb));
919
920         gus.mcb->next = gus.mcb->prev = NULL;
921         gus.mcb->addr = 0;
922         gus.mcb->size = gus.ram * 1024;
923         gus.mcb->free = 1;
924 }
925
926 /* Return amount of free memory */
927 static unsigned int __gus_mem_get_free()
928 {
929         __gus_mcb *cur = gus.mcb;
930         unsigned int size = 0;
931
932         if (!gus.open)
933                 return gus.ram * 1024;
934
935         while (cur) {
936                 if (cur->free)
937                         size += cur->size;
938                 cur = cur->next;
939         }
940
941         return size;
942 }
943
944 /* Return largest size for a 8-bit sample */
945 static unsigned int __gus_mem_get_free_8()
946 {
947         __gus_mcb *cur = gus.mcb;
948         unsigned int size = 0;
949
950         if (!gus.open)
951                 return 0;
952
953         while (cur) {
954                 if (cur->free && (cur->size > size))
955                         size = cur->size;
956                 cur = cur->next;
957         }
958
959         return size;
960 }
961
962 /* Return largest size for a 16-bit sample */
963 static unsigned int __gus_mem_get_free_16()
964 {
965         __gus_mcb *cur = gus.mcb;
966         unsigned int size = 0;
967
968         if (!gus.open)
969                 return 0;
970
971         while (cur) {
972                 if (cur->free) {
973                         unsigned int size16 = cur->size;
974                         unsigned int tmp;
975                         /* 16-bit samples cannot cross 256K boundaries */
976                         tmp = 0x40000 - (cur->addr & 0x3ffff);
977                         if (size16 > tmp)
978                                 size16 = tmp;
979                         /* 16-bit samples should be aligned on a 32-byte boundary */
980                         size16 -= (32 - cur->addr) & 0x1f;
981
982                         if (size16 > size)
983                                 size = size16;
984
985                         /* Now try vice versa: skip a portion of aligned memory */
986                         size16 =
987                           (cur->addr + cur->size) - ((cur->addr + 0x3ffff) & ~0x3ffff);
988                         if ((size16 < 0x7fffffff) && (size16 > size))
989                                 size = size16;
990                 }
991                 cur = cur->next;
992         }
993
994         return size;
995 }
996
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.
1001  */
1002 static unsigned int __gus_mem_alloc(unsigned int size, int bits16)
1003 {
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;
1009
1010         if (!gus.open || !size || (bits16 && size > 0x40000))
1011                 return -1;
1012
1013         /* Round block size up to nearest acceptable DMA bound */
1014         if (bits16)
1015                 size = (size + 0x1f) & ~0x1f;
1016         else
1017                 size = (size + 0x0f) & ~0x0f;
1018
1019         while (cur) {
1020                 if (cur->free) {
1021                         unsigned char fits = 0;
1022
1023                         memsize = cur->size;
1024                         memaddr = cur->addr;
1025
1026                         if (bits16) {
1027                                 /* 16-bit samples cannot cross 256K boundaries */
1028                                 unsigned int tmp = 256 * 1024 - (memaddr & 0x3ffff);
1029                                 if (memsize > tmp)
1030                                         memsize = tmp;
1031                                 /* 16-bit samples should be aligned on a 32-byte boundary */
1032                                 memsize -= (32 - memaddr) & 0x1f;
1033                                 memaddr = (memaddr + 0x1f) & ~0x1f;
1034                         }
1035
1036                         /* If block fits, analyze it */
1037                         if (size <= memsize)
1038                                 fits = 1;
1039                         /* Look if we still can complete the request by creating a free
1040                            block */
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
1046                                    beginning? */
1047                                 if ((memaddr < endaddr) && (memaddr + size <= endaddr))
1048                                         fits = 1;
1049                         }
1050
1051                         if (fits) {
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;
1060                         }
1061                 }
1062
1063                 cur = cur->next;
1064         }
1065
1066         if (!best_min)
1067                 return -1;
1068
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
1071            it */
1072         if ((best_max_prefix == 0)
1073                 || (best_max_prefix >= DRAM_HOLE_THRESHOLD)
1074                 || (best_min_prefix != 0))
1075                 if (
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;
1085                 }
1086
1087         /* Compute the DRAM address to return */
1088         memaddr = best_min->addr + best_min_prefix;
1089         if (bits16)
1090                 memaddr = (memaddr + 0x1f) & ~0x1f;
1091         else
1092                 memaddr = (memaddr + 0x0f) & ~0x0f;
1093
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;
1102                 newmcb->free = 1;
1103                 best_min->addr = memaddr;
1104                 best_min->size -= newmcb->size;
1105                 best_min->prev = newmcb;
1106                 if (newmcb->prev)
1107                         newmcb->prev->next = newmcb;
1108         }
1109
1110         /* Compute the size of hole at the end of block */
1111         memsize = (best_min->addr + best_min->size) - (memaddr + size);
1112
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
1116                    together */
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;
1123                 newmcb->free = 1;
1124                 if (best_min->next)
1125                         best_min->next->prev = newmcb;
1126                 best_min->next = newmcb;
1127         }
1128         best_min->free = 0;
1129
1130         return memaddr;
1131 }
1132
1133 static void __gus_mem_free(unsigned int addr)
1134 {
1135         __gus_mcb *cur = gus.mcb;
1136         while (cur) {
1137                 if (!cur->free && (cur->addr <= addr) &&
1138                         (cur->addr + cur->size > addr)) {
1139                         cur->free = 1;
1140
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;
1146                                 if (next->next)
1147                                         next->next->prev = cur;
1148                                 MikMod_free(next);
1149                         }
1150
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;
1155                                 if (cur->next)
1156                                         cur->next->prev = cur->prev;
1157                                 MikMod_free(cur);
1158                         }
1159                         return;
1160                 }
1161                 cur = cur->next;
1162         }
1163 }
1164
1165 static void __gus_mem_pack()
1166 {
1167 }
1168
1169 #ifdef MIKMOD_DEBUG
1170
1171 /* Debug dump of GUS DRAM heap */
1172 void __gus_mem_dump()
1173 {
1174         __gus_mcb *cur = gus.mcb;
1175         fprintf(stderr, "/-- Offset --+-- Prev --+-- Size --+-- Free --\\\n");
1176         while (cur) {
1177                 fprintf(stderr, "|  %08X  | %08X |  %6d  |   %s    |\n",
1178                                 cur->addr, cur->prev ? cur->prev->addr : -1, cur->size,
1179                                 cur->free ? "yes" : " no");
1180                 cur = cur->next;
1181         }
1182         fprintf(stderr, "\\------------+----------+----------+----------/\n");
1183 }
1184
1185 #endif
1186
1187 /************************************************** Middle-level routines *****/
1188
1189 static int __gus_instrument_free(gus_instrument_t * instrument)
1190 {
1191         gus_instrument_t **cur_instr;
1192         gus_layer_t *cur_layer;
1193         gus_wave_t *cur_wave, *wave_head;
1194
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;
1200                         goto instr_loaded;
1201                 }
1202                 cur_instr = &(*cur_instr)->next;
1203         }
1204         return -1;
1205
1206 instr_loaded:
1207         wave_head = NULL;
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) {
1212                         if (!wave_head)
1213                                 wave_head = cur_wave;
1214                         if (cur_wave->begin.memory != (unsigned int)-1)
1215                                 __gus_mem_free(cur_wave->begin.memory);
1216                 }
1217         if (wave_head)
1218                 MikMod_free(wave_head);
1219
1220         MikMod_free(instrument->info.layer);
1221         if (instrument->name)
1222                 MikMod_free(instrument->name);
1223         MikMod_free(instrument);
1224         return 0;
1225 }
1226
1227 static gus_instrument_t *__gus_instrument_get(int program)
1228 {
1229         gus_instrument_t *cur_instr = (gus_instrument_t *) gus.instr;
1230         while (cur_instr) {
1231                 if (cur_instr->number.instrument == program)
1232                         return cur_instr;
1233                 cur_instr = cur_instr->next;
1234         }
1235         return NULL;
1236 }
1237
1238 static gus_instrument_t *__gus_instrument_copy(gus_instrument_t * instrument)
1239 {
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;
1244
1245         if (!instrument || !instrument->info.layer || !gus.open)
1246                 return NULL;
1247
1248         if (__gus_instrument_get(instrument->number.instrument))
1249                 return NULL;
1250
1251         instr = (gus_instrument_t *) MikMod_malloc(sizeof(gus_instrument_t));
1252         *instr = *instrument;
1253
1254         if (instrument->name)
1255                 instr->name = MikMod_strdup(instrument->name);
1256
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;
1260
1261         if (!(dest_layer = instr->info.layer = (gus_layer_t *) MikMod_malloc(sizeof(gus_layer_t) * layers))) {
1262                 if (instr->name)
1263                         MikMod_free(instr->name);
1264                 MikMod_free(instr);
1265                 return NULL;
1266         }
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)
1273                         waves++;
1274                 if (cur_layer->next)
1275                         dest_layer->next = dest_layer + 1;
1276                 else
1277                         dest_layer->next = NULL;
1278                 dest_layer++;
1279         }
1280
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);
1284                 if (instr->name)
1285                         MikMod_free(instr->name);
1286                 MikMod_free(instr);
1287                 return NULL;
1288         }
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;
1295
1296                         *dest_wave = *cur_wave;
1297                         /* Mark DRAM address as unallocated */
1298                         dest_wave->begin.memory = -1;
1299
1300                         if (cur_wave->next)
1301                                 dest_wave->next = (dest_wave + 1);
1302                         else
1303                                 dest_wave->next = NULL;
1304                         dest_wave++;
1305                 }
1306
1307         /* Insert the instrument into list of registered instruments */
1308         cur_instr = (gus_instrument_t **) & gus.instr;
1309         while (*cur_instr)
1310                 cur_instr = &(*cur_instr)->next;
1311         *cur_instr = instr;
1312
1313         return instr;
1314 }
1315
1316 static void __gus_instruments_clear()
1317 {
1318         gus_instrument_t *next_instr, *cur_instr = (gus_instrument_t *) gus.instr;
1319         while (cur_instr) {
1320                 next_instr = cur_instr->next;
1321                 __gus_instrument_free(cur_instr);
1322                 cur_instr = next_instr;
1323         }
1324 }
1325
1326 /******************************************************* libGUS interface *****/
1327
1328 /* return value: number of GUS cards installed in system */
1329 int gus_cards()
1330 {
1331         if (!gus.ok)
1332                 __gus_init();
1333         return gus.ok ? 1 : 0;
1334 }
1335
1336 int gus_info(gus_info_t * info, int reread)
1337 {
1338         if (!gus.ok)
1339                 __gus_init();
1340         if (!gus.ok)
1341                 return -1;
1342
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];
1350
1351         info->mixing_freq = gus.freq;
1352
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();
1357         return 0;
1358 }
1359
1360 int gus_open(int card, size_t queue_buffer_size, int non_block)
1361 {
1362         __dpmi_meminfo struct_info, pool_info;
1363
1364         if (!gus.ok)
1365                 __gus_init();
1366
1367         if (!gus.ok || gus.open || card != 0)
1368                 return -1;
1369
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))
1374                 return -1;
1375
1376         /* And hook the GF1 interrupt */
1377         __irq_stack_count = 4;
1378         gus.gf1_irq =
1379           irq_hook(gus.irq[0], gf1_irq, (long)gf1_irq_end - (long)gf1_irq);
1380         __irq_stack_count = 1;
1381         if (!gus.gf1_irq) {
1382                 __dpmi_unlock_linear_region(&struct_info);
1383                 return -1;
1384         }
1385
1386         /* Enable the interrupt */
1387         irq_enable(gus.gf1_irq);
1388         if (gus.irq[0] > 7)
1389                 _irq_enable(2);
1390
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);
1394         else
1395                 gus.dma_buff = NULL;
1396
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;
1402
1403                 /* If no transfer function worked, fail */
1404                 if (!gus.transfer) {
1405                         if (gus.dma_buff) {
1406                                 dma_free(gus.dma_buff);
1407                                 gus.dma_buff = NULL;
1408                         }
1409                         __dpmi_unlock_linear_region(&struct_info);
1410                         irq_unhook(gus.gf1_irq);
1411                         gus.gf1_irq = NULL;
1412                         return -1;
1413                 }
1414         }
1415
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)) {
1425                 if (gus.dma_buff) {
1426                         dma_free(gus.dma_buff);
1427                         gus.dma_buff = NULL;
1428                 }
1429                 __dpmi_unlock_linear_region(&struct_info);
1430                 irq_unhook(gus.gf1_irq);
1431                 gus.gf1_irq = NULL;
1432                 return -1;
1433         }
1434
1435         gus.open++;
1436
1437         __gus_mem_clear();
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 */
1442
1443         return 0;
1444 }
1445
1446 int gus_close(int card)
1447 {
1448         __dpmi_meminfo struct_info;
1449
1450         if (!gus.open || card != 0)
1451                 return -1;
1452
1453         /* First reset the card: disable any operation it can currently perform */
1454         __gus_reset(0);
1455
1456         gus.open--;
1457
1458         /* Stop the timer */
1459         gus_timer_stop();
1460
1461         /* Free DMA buffer if used */
1462         if (gus.dma_buff) {
1463                 dma_free(gus.dma_buff);
1464                 gus.dma_buff = NULL;
1465         }
1466
1467         /* And unhook the GF1 interrupt */
1468         irq_unhook(gus.gf1_irq);
1469         gus.gf1_irq = NULL;
1470
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);
1475
1476         __gus_mem_clear();
1477         __gus_instruments_clear();
1478
1479         return 0;
1480 }
1481
1482 int gus_select(int card)
1483 {
1484         if (!gus.open || (card != 0))
1485                 return -1;
1486
1487         return 0;
1488 }
1489
1490 /* return value: same as gus_reset function
1491    note: this command doesn't change number of active voices and doesn't do
1492    hardware reset */
1493 int gus_reset_engine_only()
1494 {
1495         gus.timer_base = 100;
1496         return 0;
1497 }
1498
1499 int gus_reset(int voices, unsigned int channel_voices)
1500 {
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
1504         };
1505         int voice;
1506         int timer;
1507
1508         /* No support for dynamically allocated voices for now */
1509         gus.dynmask = channel_voices;
1510
1511         if (voices < 14)
1512                 voices = 14;
1513         if (voices > 32)
1514                 voices = 32;
1515
1516         /* Stop the timer so that GUS IRQ won't clobber registers */
1517         timer = (gus.timer_ctl_reg & GF1M_TIMER1);
1518         if (timer)
1519                 gus_timer_stop();
1520
1521         /* Stop all voices */
1522         for (voice = 0; voice < 32; voice++) {
1523                 __gus_select_voice(voice);
1524                 __gus_stop_voice();
1525                 gus.cur_wave[voice] = NULL;
1526                 gus.cur_vol[voice] = 0;
1527
1528                 __gus_delay();
1529
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);
1539         }
1540
1541         voice = (__gus_inregb(GF1R_VOICES) & 0x1f) + 1;
1542
1543         if (voice != voices) {
1544                 int reset = __gus_inregb(GF1R_RESET);
1545                 __gus_outregb(GF1R_RESET, reset & ~GF1M_OUTPUT_ENABLE);
1546                 __gus_delay();
1547                 __gus_outregb(GF1R_VOICES, 0xc0 | (voices - 1));
1548                 __gus_delay();
1549                 __gus_outregb(GF1R_RESET, reset);
1550         }
1551
1552         /* Compute the discretization frequence */
1553         gus.voices = voices;
1554         if (gus.interwave)
1555                 gus.freq = 44100;
1556         else
1557                 gus.freq = freq_table[voices - 14];
1558
1559         gus_reset_engine_only();
1560
1561         if (timer)
1562                 gus_timer_continue();
1563
1564         return gus.voices;
1565 }
1566
1567 int gus_do_flush()
1568 {
1569         DEBUG_PRINT(("gus_do_flush: top = %d\n", gus.cmd_pool_top))
1570           gus.cmd_pool_ready = 1;
1571         return 0;
1572 }
1573
1574 /* set new tempo */
1575 void gus_do_tempo(unsigned int tempo)
1576 {
1577         DEBUG_PRINT(("gus_do_tempo (%d)\n", tempo))
1578           gus_timer_tempo(tempo);
1579         gus_timer_start();
1580 }
1581
1582 /* set voice frequency in Hz */
1583 void gus_do_voice_frequency(unsigned char voice, unsigned int freq)
1584 {
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);
1589 }
1590
1591 /* set voice pan (0-16384) (full left - full right) */
1592 void gus_do_voice_pan(unsigned char voice, unsigned short pan)
1593 {
1594         DEBUG_PRINT(("gus_do_voice_pan (%d, %d)\n", voice, pan))
1595           pan >>= 10;
1596         if (pan > 15)
1597                 pan = 15;
1598         __pool_select_voice(voice);
1599         __pool_command_b(PCMD_PAN, pan);
1600 }
1601
1602 /* set voice volume level 0-16384 (linear) */
1603 void gus_do_voice_volume(unsigned char voice, unsigned short vol)
1604 {
1605         DEBUG_PRINT(("gus_do_voice_volume (%d, %d)\n", voice, vol))
1606           if (vol > 0x3fff)
1607                 vol = 0x3fff;
1608         __pool_select_voice(voice);
1609         __pool_command_w(PCMD_VOLUME, __gus_volume_table[vol >> 5]);
1610 }
1611
1612 /* start voice
1613  *   voice    : voice #
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
1618  */
1619 void gus_do_voice_start(unsigned char voice, unsigned int program,
1620                                                 unsigned int freq, unsigned short volume,
1621                                                 unsigned short pan)
1622 {
1623         gus_do_voice_start_position(voice, program, freq, volume, pan, 0);
1624 }
1625
1626 /* start voice
1627  *   voice    : voice #
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)
1633  */
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)
1637 {
1638         gus_instrument_t *instrument;
1639         gus_wave_t *wave;
1640
1641         DEBUG_PRINT(
1642                                 ("gus_do_voice_start_position (%d, %d, pos: %d)\n", voice,
1643                                  program, position))
1644
1645           instrument = __gus_instrument_get(program);
1646
1647         if (!instrument
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;
1652
1653         gus_do_voice_frequency(voice, freq);
1654         gus_do_voice_pan(voice, pan);
1655
1656         /* We have to set volume different way, to avoid unneeded work in handler */
1657         if (volume > 0x3fff)
1658                 volume = 0x3fff;
1659         __pool_command_w(PCMD_VOLUME_PREPARE, __gus_volume_table[volume >> 5]);
1660
1661         switch (instrument->mode) {
1662           case GUS_INSTR_SIMPLE:
1663                 wave = instrument->info.layer->wave;
1664                 if (position)
1665                         __pool_command_l(PCMD_OFFSET, position);
1666                 __pool_command_l(PCMD_START, (unsigned long)wave);
1667                 break;
1668         }
1669 }
1670
1671 /* stop voice
1672  *   mode = 0 : stop voice now
1673  *   mode = 1 : disable wave loop and finish it
1674  */
1675 void gus_do_voice_stop(unsigned char voice, unsigned char mode)
1676 {
1677         __pool_select_voice(voice);
1678         if (mode)
1679                 __pool_command(PCMD_STOP_LOOP);
1680         else
1681                 __pool_command(PCMD_STOP);
1682 }
1683
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)
1687 {
1688         DEBUG_PRINT(("gus_do_wait (%d)\n", ticks))
1689
1690           ticks += gus.t1_ticks;
1691         while ((int)(ticks - gus.t1_ticks) > 0);
1692 }
1693
1694 int gus_get_voice_status(int voice)
1695 {
1696         __gus_select_voice(voice);
1697         return __gus_inregb(GF1R_VOICE_CONTROL) & GF1VC_STOPPED ? 0 : 1;
1698 }
1699
1700 /* return value: file handle (descriptor) for /dev/gus */
1701 int gus_get_handle()
1702 {
1703         /* Return stdout handle so that select() will "work" with it */
1704         return 0;
1705 }
1706
1707 /* return value: zero if instrument was successfully allocated */
1708 int gus_memory_alloc(gus_instrument_t * instrument)
1709 {
1710         gus_instrument_t *instr = __gus_instrument_copy(instrument);
1711         gus_layer_t *cur_layer;
1712         gus_wave_t *cur_wave;
1713
1714         DEBUG_PRINT(("gus_memory_alloc (%d)\n", instrument->number.instrument))
1715
1716           if (!instr)
1717                 return -1;
1718
1719         for (cur_layer = instr->info.layer; cur_layer;
1720                  cur_layer = cur_layer->next) for (cur_wave = cur_layer->wave;
1721                                                                                    cur_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,
1725                                                                                                                  cur_wave->format &
1726                                                                                                                  GUS_WAVE_16BIT);
1727                                 if (cur_wave->begin.memory == (unsigned int)-1) {
1728                                         __gus_instrument_free(instr);
1729                                         return -1;
1730                                 }
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 */ ;
1735                 }
1736
1737         return 0;
1738 }
1739
1740 /* return value: zero if instrument was successfully removed */
1741 int gus_memory_free(gus_instrument_t * instrument)
1742 {
1743         gus_instrument_t *cur_instr = gus.instr;
1744
1745         DEBUG_PRINT(("gus_memory_free (%d)\n", instrument->number.instrument))
1746
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);
1750
1751         return -1;
1752 }
1753
1754 /* return value: unused gus memory in bytes */
1755 int gus_memory_free_size()
1756 {
1757         return __gus_mem_get_free();
1758 }
1759
1760 /* return value: zero if success */
1761 int gus_memory_pack()
1762 {
1763         __gus_mem_pack();
1764         return 0;
1765 }
1766
1767 /* return value: gus memory size in bytes */
1768 int gus_memory_size()
1769 {
1770         return gus.ram * 1024;
1771 }
1772
1773 /* return value: current largest free block for 8-bit or 16-bit wave */
1774 int gus_memory_free_block(int w_16bit)
1775 {
1776         return w_16bit ? __gus_mem_get_free_16() : __gus_mem_get_free_8();
1777 }
1778
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)
1783 {
1784         __gus_mem_clear();
1785         __gus_instruments_clear();
1786         return 0;
1787 }
1788
1789 /* return value: zero if command queue was successfully flushed */
1790 int gus_queue_flush()
1791 {
1792         return 0;
1793 }
1794
1795 /* input value: echo buffer size in items (if 0 - erase echo buffer) */
1796 int gus_queue_read_set_size(int items)
1797 {
1798         return 0;
1799 }
1800
1801 /* input value: write queue size in items (each item have 8 bytes) */
1802 int gus_queue_write_set_size(int items)
1803 {
1804         return 0;
1805 }
1806
1807 /* return value: zero if successfull */
1808 int gus_timer_start()
1809 {
1810         gus.timer_ctl_reg |= GF1M_TIMER1;
1811         __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
1812
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);
1816         return 0;
1817 }
1818
1819 /* return value: zero if timer was stoped */
1820 int gus_timer_stop()
1821 {
1822         gus.timer_ctl_reg &= ~GF1M_TIMER1;
1823         __gus_outregb_slow(GF1R_TIMER_CONTROL, gus.timer_ctl_reg);
1824
1825         gus.timer_ctl = gus.timer_ctl | GF1M_MASK_TIMER1;
1826         outportb(GF1_TIMER_CTRL, 0x04);
1827         outportb(GF1_TIMER_DATA, gus.timer_ctl);
1828         return 0;
1829 }
1830
1831 /* return value: zero if setup was success */
1832 int gus_timer_tempo(int ticks)
1833 {
1834         unsigned int counter;
1835
1836         /* Limit ticks per second to 1..1000 range */
1837         if (ticks < 1)
1838                 ticks = 1;
1839         if (ticks > 1000)
1840                 ticks = 1000;
1841
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) {
1846                 counter >>= 1;
1847                 gus.t1_multiple <<= 1;
1848         }
1849         gus.t1_countdown = gus.t1_multiple;
1850         __gus_outregb(GF1R_TIMER1, 256 - counter);
1851         return 0;
1852 }
1853
1854 /* return value: zero if timer will be continue */
1855 int gus_timer_continue()
1856 {
1857         return gus_timer_start();
1858 }
1859
1860 /* return value: zero if setup was success (default timebase = 100) */
1861 int gus_timer_base(int base)
1862 {
1863         gus.timer_base = base;
1864         return 0;
1865 }
1866
1867 void gus_timer_callback(void (*timer_callback) ())
1868 {
1869         gus.timer_callback = timer_callback;
1870 }
1871
1872 void gus_convert_delta(unsigned int type, unsigned char *dest,
1873                                            unsigned char *src, size_t size)
1874 {
1875         if (!(type & GUS_WAVE_DELTA))
1876                 return;
1877
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;
1882                 while (size--) {
1883                         delta = *(unsigned short *)dest = *(unsigned short *)src + delta;
1884                         src += sizeof(unsigned short);
1885                         dest += sizeof(unsigned short);
1886                 }
1887         } else {
1888                 unsigned char delta = type & GUS_WAVE_UNSIGNED ? 0x80 : 0;
1889                 while (size--) {
1890                         delta = *(unsigned char *)dest = *(unsigned char *)src + delta;
1891                         src++;
1892                         dest++;
1893                 }
1894         }
1895 }
1896
1897 int gus_dma_usage (int use)
1898 {
1899         if (gus.dma_buff)
1900                 return -1;
1901         gus.transfer = __gus_transfer_io;
1902         return 0;
1903 }
1904
1905 #endif /* DRV_ULTRA */
1906
1907 /* ex:set ts=4: */