Annotation of uae/src/od-dos/sound/sb.c, revision 1.1.1.1

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * DOS Sound Blaster interface.
                      5:   *
                      6:   * (c) 1996 Peter Remmers, Gustavo Goedert
                      7:   *
                      8:   * Bugfixes by Michael Sontheimer
                      9:   */
                     10: 
                     11: #include "sysconfig.h"
                     12: #include "sysdeps.h"
                     13: 
                     14: #include <stdlib.h>
                     15: #include <stdio.h>
                     16: #include <string.h>
                     17: #include <ctype.h>
                     18: #include <dos.h>
                     19: #include <pc.h>
                     20: #include <sys/farptr.h>
                     21: #include <dpmi.h>
                     22: #include <go32.h>
                     23: 
                     24: #include "sound/sb.h"
                     25: #include "sound/dma.h"
                     26: 
                     27: /* some useful macros */
                     28: #define LOBYTE(x) ((UBYTE)(((UWORD)(x)) &  0xFF))
                     29: #define HIBYTE(x) ((UBYTE)(((UWORD)(x)) >> 8))
                     30: #define LOWORD(x) ((UWORD)(((ULONG)(x)) & 0xFFFF))
                     31: #define HIWORD(x) ((UWORD)(((ULONG)(x)) >> 16))
                     32: #define NUMPARAS(bytesize) (((bytesize)+15) >> 4)
                     33: 
                     34: #ifndef TRUE
                     35: #define TRUE 1
                     36: #endif
                     37: #ifndef FALSE
                     38: #define FALSE 0
                     39: #endif
                     40: 
                     41: /* Offsets relative to base I/O address. */
                     42: #define SB_MIXER_ADDRESS        0x04
                     43: #define SB_MIXER_DATA           0x05
                     44: #define SB_DSP_RESET            0x06
                     45: #define SB_DSP_READ_DATA        0x0A
                     46: #define SB_DSP_WRITE_DATA       0x0C
                     47: #define SB_DSP_WRITE_STATUS     0x0C
                     48: #define SB_DSP_DATA_AVAIL       0x0E
                     49: #define SB_DSP_INT_CLEAR        0x0F
                     50: 
                     51: /* DSP Commands */
                     52: #define CMD_PLAY_8BIT                0x14
                     53: #define CMD_SET_TIME_CONSTANT        0x40
                     54: #define CMD_DEFINE_SILENCE_BLOCK     0x80
                     55: #define CMD_PAUSE_8BIT_DMA           0xD0
                     56: #define CMD_CONTINUE_8BIT_DMA        0xD4
                     57: #define CMD_SPEAKER_ON               0xD1
                     58: #define CMD_SPEAKER_OFF              0xD3
                     59: #define CMD_GET_SPEAKER_SETTING      0xD8
                     60: #define CMD_DSP_VER                  0xE1
                     61: 
                     62: /* SbPro-only commands */
                     63: #define CMD_SET_BLOCK_SIZE           0x48
                     64: #define CMD_PLAY_8BIT_HISPEED        0x91
                     65: 
                     66: /* SB16-only commands */
                     67: #define CMD_SET_OUTPUT_RATE          0x41
                     68: #define CMD_PLAY_16BIT_SINGLE        0xB0
                     69: #define CMD_PLAY_16BIT_AUTOINIT      0xB6
                     70: #define CMD_PLAY_8BIT_SINGLE         0xC0
                     71: #define CMD_PLAY_8BIT_AUTOINIT       0xC6
                     72: #define CMD_PAUSE_16BIT_DMA          0xD5
                     73: #define CMD_CONTINUE_16BIT_DMA       0xD6
                     74: 
                     75: typedef void (*tPlayProc)(UWORD bytes);
                     76: 
                     77: typedef struct
                     78: {
                     79:   ULONG Data;
                     80:   _go32_dpmi_seginfo dma_mem; /* info for DMA memory */
                     81: }
                     82: tDMABuffer;
                     83: 
                     84: tSBType SB_Type;
                     85: 
                     86: UWORD SB_Base;      /* the Base Address  e.g. 220h                         */
                     87: UWORD SB_IRQ;       /* The IRQ           e.g. 5                            */
                     88: UWORD SB_DMAlo;     /* Low DMA channel   e.g. 1                            */
                     89: UWORD SB_DMAhi;     /* high DMA channel  e.g. 5                            */
                     90: UWORD SB_INT;       /* The Interrupt vector corresponding to IRQ e.g. 0Dh  */
                     91: UWORD SB_DMA;       /* The current DMA channel                             */
                     92:                    /* (depends on if we're playing 8Bit or 16Bit sound)   */
                     93: UBYTE SB_VersMaj;   /* Major DSP Version byte                              */
                     94: UBYTE SB_VersMin;   /* Minor DSP Version byte                              */
                     95: UBYTE SB_ModeByte;  /* Mode Byte for SB16 (Mono/Stereo, Signed/Unsigned )  */
                     96: UWORD SB_IntClearPort; /* SB Port to read from to acknoledge interrupt     */
                     97: 
                     98: tPlayProc SB_Play_Proc;        /* function */
                     99: tDMABuffer dma_buf[2];         /* the two DMA buffers */
                    100: 
                    101: BOOL  SB_16Bit;       /* we're playing in 16 Bits                          */
                    102: BOOL  SB_Stereo;      /* we're playing in stereo                           */
                    103: UWORD SB_Active_Rate; /* the active sampling rate                          */
                    104: 
                    105: volatile UBYTE IRQ_Detected;    /* the detected IRQ number                 */
                    106: 
                    107: _go32_dpmi_seginfo   old_pmint;  /* the old interrupt handler         */
                    108: _go32_dpmi_seginfo   pm_wrapper; /* the new interrupt handler         */
                    109: 
                    110: /* Reset SB at SB_Base, returns TRUE if it worked */
                    111: BOOL SB_Reset (void)
                    112: {
                    113:   outportb (SB_Base+SB_DSP_RESET, 1);
                    114:   delay(100);
                    115:   outportb (SB_Base+SB_DSP_RESET, 0);
                    116:   delay(100);
                    117:   return (inportb(SB_Base+SB_DSP_READ_DATA) == 0xAA);
                    118: }
                    119: 
                    120: /* Write a command to DSP chip */
                    121: inline void SB_WriteDSP (UBYTE value)
                    122: {
                    123:   while (inportb(SB_Base + SB_DSP_WRITE_STATUS) & 0x80);
                    124:   outportb (SB_Base + SB_DSP_WRITE_DATA, value);
                    125: }
                    126: 
                    127: /* read a byte from DSP chip */
                    128: inline UBYTE SB_ReadDSP (void)
                    129: {
                    130:   while (!(inportb (SB_Base + SB_DSP_DATA_AVAIL) & 0x80));
                    131:   return  (inportb (SB_Base + SB_DSP_READ_DATA));
                    132: }
                    133: 
                    134: /* write a value to the mixer chip */
                    135: inline void SB_WriteMixer (UBYTE reg, UBYTE data)
                    136: {
                    137:   outportb (SB_Base + SB_MIXER_ADDRESS, reg);
                    138:   outportb (SB_Base + SB_MIXER_DATA,    data);
                    139: }
                    140: 
                    141: /* read a value from the mixer chip */
                    142: inline UBYTE SB_ReadMixer (UBYTE reg)
                    143: {
                    144:   outportb (SB_Base + SB_MIXER_ADDRESS, reg);
                    145:   return (inportb (SB_Base + SB_MIXER_DATA));
                    146: }
                    147: 
                    148: /* try to detect, if SB has a mixer chip, returns TRUE if found */
                    149: BOOL SB_DetectMixer (void)
                    150: {
                    151:   UBYTE orgval;
                    152: 
                    153:   orgval = SB_ReadMixer (0x22);
                    154: 
                    155:   // Some SB-Pro-clones always set the bit 0 and 4, if reading
                    156:   // the volume (the bit 0 and 4 aren't used for setting the volume)
                    157: 
                    158:   SB_WriteMixer (0x22, 0);
                    159:   delay(200);
                    160:   if ((SB_ReadMixer (0x22)&(0xEE)) != 0)
                    161:     return (FALSE);
                    162: 
                    163:   SB_WriteMixer (0x22, 0xEE);
                    164:   delay(200);
                    165:   if ((SB_ReadMixer (0x22)&(0xEE)) != 0xEE)
                    166:     return (FALSE);
                    167: 
                    168: //  SB_WriteMixer (0x22, orgval);   // Why not setting the volume to maximum ?
                    169: 
                    170:   return (TRUE);
                    171: }
                    172: 
                    173: /* play a block in 8 Bits on a Standard SB */
                    174: void SB_Play_8Bit_Std (UWORD bytes)
                    175: {
                    176:   SB_WriteDSP (CMD_PLAY_8BIT);
                    177:   SB_WriteDSP (LOBYTE (bytes-1));
                    178:   SB_WriteDSP (HIBYTE (bytes-1));
                    179: }
                    180: 
                    181: /* Play a block in 8 Bits on an SB PRO */
                    182: void SB_Play_8Bit_SbPro (UWORD bytes)
                    183: {
                    184:   SB_WriteDSP (CMD_SET_BLOCK_SIZE);
                    185:   SB_WriteDSP (LOBYTE (bytes-1));
                    186:   SB_WriteDSP (HIBYTE (bytes-1));
                    187:   SB_WriteDSP (CMD_PLAY_8BIT_HISPEED);
                    188: }
                    189: 
                    190: /* play a block in 8 Bits on an SB 16 */
                    191: void SB_Play_8Bit_SB16 (UWORD bytes)
                    192: {
                    193:   SB_WriteDSP (CMD_PLAY_8BIT_SINGLE);
                    194:   SB_WriteDSP (SB_ModeByte);
                    195:   SB_WriteDSP (LOBYTE (bytes-1));
                    196:   SB_WriteDSP (HIBYTE (bytes-1));
                    197: }
                    198: 
                    199: /* play a block in 16 Bits on an SB 16 */
                    200: void SB_Play_16Bit (UWORD bytes)
                    201: {
                    202:   SB_WriteDSP (CMD_PLAY_16BIT_SINGLE);
                    203:   SB_WriteDSP (SB_ModeByte);
                    204:   SB_WriteDSP (LOBYTE ((bytes>>1) -1));
                    205:   SB_WriteDSP (HIBYTE ((bytes>>1) -1));
                    206: }
                    207: 
                    208: /* the main interrupt handler */
                    209: void SB_IntHandler (void)
                    210: {
                    211:   IsPlaying = FALSE;
                    212: 
                    213:   inportb (SB_IntClearPort);
                    214:   if (SB_IRQ > 7) outportb (0xA0, 0x20);
                    215: 
                    216:   outportb (0x20, 0x20);
                    217:   enable();
                    218: }
                    219: 
                    220: /* set sampling rate on a standard SB */
                    221: void SB_SetRate_LoSpeed (UWORD rate)
                    222: {
                    223:   SB_WriteDSP (CMD_SET_TIME_CONSTANT);
                    224:   SB_WriteDSP (0x100 - 1000000 / rate);
                    225: }
                    226: 
                    227: /* set sampling rate on a SB PRO */
                    228: void SB_SetRate_HiSpeed (UWORD rate)
                    229: {
                    230:   SB_WriteDSP (CMD_SET_TIME_CONSTANT);
                    231:   SB_WriteDSP (HIBYTE (0x10000 - 256000000 / rate));
                    232: }
                    233: 
                    234: /* set sampling rate on an SB 16 */
                    235: void SB_SetRate_SB16 (UWORD rate)
                    236: {
                    237:   SB_WriteDSP (CMD_SET_OUTPUT_RATE);
                    238:   SB_WriteDSP (HIBYTE (rate));
                    239:   SB_WriteDSP (LOBYTE (rate));
                    240: }
                    241: 
                    242: /* set the sampling rate */
                    243: int SB_SetRate (unsigned short rate)
                    244: {
                    245:   if (rate > 23000 && SB_Type < SB_Type_SbPro) return(FALSE);
                    246: 
                    247:   switch (SB_Type)
                    248:   {
                    249:   case SB_Type_StdSB: SB_SetRate_LoSpeed (rate); break;
                    250:   case SB_Type_SbPro: SB_SetRate_HiSpeed (rate); break;
                    251:   case SB_Type_SB16:  SB_SetRate_SB16    (rate); break;
                    252:   }
                    253: 
                    254:   SB_Active_Rate = rate;
                    255: 
                    256:   return (TRUE);
                    257: }
                    258: 
                    259: /* set the number of bits, i.e. 8 Bit / 16 Bit mode */
                    260: int SB_SetBits (unsigned char bits)
                    261: {
                    262:   if (bits==16 && SB_Type < SB_Type_SB16) return (FALSE);
                    263: 
                    264:   if (SB_Type == SB_Type_SB16)
                    265:   {
                    266:     if (bits==16)
                    267:     {
                    268:       SB_Play_Proc        = SB_Play_16Bit;
                    269:       SB_IntClearPort     = SB_Base + SB_DSP_INT_CLEAR;
                    270:       SB_DMA              = SB_DMAhi;
                    271:       SB_16Bit            = TRUE;
                    272:     }
                    273:     else
                    274:     {
                    275:       SB_Play_Proc        = SB_Play_8Bit_SB16;
                    276:       SB_IntClearPort     = SB_Base + SB_DSP_DATA_AVAIL;
                    277:       SB_DMA              = SB_DMAlo;
                    278:       SB_16Bit            = FALSE;
                    279:     }
                    280:   }
                    281: 
                    282:   return (TRUE);
                    283: }
                    284: 
                    285: /* set the number of channels, i.e. Mono / Stereo */
                    286: int SB_SetChannels (unsigned char channels)
                    287: {
                    288:   if (channels==2 && SB_Type < SB_Type_SbPro) return (FALSE);
                    289: 
                    290:   switch (SB_Type)
                    291:   {
                    292:   case SB_Type_StdSB: break;
                    293: 
                    294:   case SB_Type_SbPro:
                    295:     if (channels==2) SB_WriteMixer (0x0E, SB_ReadMixer (0x0E) | 0x02);
                    296:                else SB_WriteMixer (0x0E, SB_ReadMixer (0x0E) & 0xFD);
                    297:     break;
                    298: 
                    299:   case SB_Type_SB16:
                    300:     if (channels==2) SB_ModeByte |= 0x20;
                    301:                else SB_ModeByte &= 0xDF;
                    302:     break;
                    303:   }
                    304:   SB_Stereo = (channels==2);
                    305: 
                    306:   return (TRUE);
                    307: }
                    308: 
                    309: /* set Signed / Unsigned mode (only on SB 16) */
                    310: int SB_SetSigned (int sign)
                    311: {
                    312:   if (sign && SB_Type < SB_Type_SB16) return (FALSE);
                    313: 
                    314:   if (SB_Type == SB_Type_SB16)
                    315:   {
                    316:     if (sign) SB_ModeByte |= 0x10;
                    317:         else SB_ModeByte &= 0xEF;
                    318:   }
                    319:   return (TRUE);
                    320: }
                    321: 
                    322: /* turn speaker off (doesn't seem to work on SB 16) */
                    323: void SB_SpeakerOff(void)
                    324: {
                    325:   SB_WriteDSP(CMD_SPEAKER_OFF);
                    326: }
                    327: 
                    328: /* turn speaker on (doesn't seem to work on SB 16) */
                    329: void SB_SpeakerOn(void)
                    330: {
                    331:   SB_WriteDSP(CMD_SPEAKER_ON);
                    332: }
                    333: 
                    334: /* set sound blaster master volume, range from 0 to 7 */
                    335: void SB_SetVolume(UBYTE vol)
                    336: {
                    337: 
                    338:   /* no mixer on standard sb */
                    339:   if (SB_Type < SB_Type_SbPro)
                    340:       return;
                    341: 
                    342:   if (vol>7)
                    343:       vol = 7;
                    344:   vol = (vol<<1);
                    345:   if (SB_Type == SB_Type_SbPro)
                    346:       vol = vol | 1;
                    347:   vol = vol | (vol<<4);
                    348: 
                    349:   SB_WriteMixer (0x22, vol);
                    350: }
                    351: 
                    352: /* interrupt handler functions used for IRQ/DMA detection */
                    353: void irq2 (void)
                    354: {
                    355:   IRQ_Detected = 2;
                    356:   inportb (SB_IntClearPort);
                    357:   outportb (0x20, 0x20);
                    358: }
                    359: void irq5 (void)
                    360: {
                    361:   IRQ_Detected = 5;
                    362:   inportb (SB_IntClearPort);
                    363:   outportb (0x20, 0x20);
                    364: }
                    365: void irq7 (void)
                    366: {
                    367:   IRQ_Detected = 7;
                    368:   inportb (SB_IntClearPort);
                    369:   outportb (0x20, 0x20);
                    370: }
                    371: void irq10 (void)
                    372: {
                    373:   IRQ_Detected = 10;
                    374:   inportb (SB_IntClearPort);
                    375:   outportb (0xA0, 0x20);
                    376:   outportb (0x20, 0x20);
                    377: }
                    378: 
                    379: /* detect the sound blaster Base/IRQ/DMA settings (may hang computer) */
                    380: int SB_Detect (unsigned short *base, unsigned short *irq,
                    381:               unsigned short *dmalo, unsigned short *dmahi)
                    382: {
                    383: #define TESTBUFSIZE 0x80
                    384:   static const UBYTE lowdma[3]  = { 1,3,0 };
                    385:   static const UBYTE highdma[3] = { 5,6,7 };
                    386: 
                    387:   UBYTE old21,oldA1,old0F,oldDE;
                    388:   _go32_dpmi_seginfo oldirq2,oldirq5,oldirq7,oldirq10;
                    389:   _go32_dpmi_seginfo newirq2,newirq5,newirq7,newirq10;
                    390:   _go32_dpmi_seginfo testbuf_info;
                    391:   ULONG testbuf;
                    392:   int   ret1,ret2,ret3,ret4;
                    393:   UBYTE i;
                    394:   BOOL  found;
                    395: 
                    396:   found = FALSE;
                    397: 
                    398:   *base  = 0;
                    399:   *irq   = 0;
                    400:   *dmalo = 0;
                    401:   *dmahi = 0;
                    402: 
                    403:   SB_Base = 0x210;
                    404:   while (SB_Base != 0x290)
                    405:   {
                    406:     if (SB_Reset()) break;
                    407:     SB_Base += 0x10;
                    408:   }
                    409:   if (SB_Base == 0x290) return (FALSE);
                    410:   *base = SB_Base;
                    411: 
                    412:   /* install detection interrupt handlers */
                    413:   newirq2.pm_offset  = (int) irq2;
                    414:   newirq5.pm_offset  = (int) irq5;
                    415:   newirq7.pm_offset  = (int) irq7;
                    416:   newirq10.pm_offset = (int) irq10;
                    417: 
                    418:   ret1 = _go32_dpmi_allocate_iret_wrapper (&newirq2);
                    419:   ret2 = _go32_dpmi_allocate_iret_wrapper (&newirq5);
                    420:   ret3 = _go32_dpmi_allocate_iret_wrapper (&newirq7);
                    421:   ret4 = _go32_dpmi_allocate_iret_wrapper (&newirq10);
                    422: 
                    423:   if (ret1|ret2|ret3|ret4)
                    424:   {
                    425:     if (!ret1) _go32_dpmi_free_iret_wrapper (&newirq2);
                    426:     if (!ret2) _go32_dpmi_free_iret_wrapper (&newirq5);
                    427:     if (!ret3) _go32_dpmi_free_iret_wrapper (&newirq7);
                    428:     if (!ret4) _go32_dpmi_free_iret_wrapper (&newirq10);
                    429:     return (FALSE);
                    430:   }
                    431:   _go32_dpmi_lock_code (irq2, (int)SB_Detect - (int)irq2);
                    432:   _go32_dpmi_lock_data ((void*)&IRQ_Detected,    sizeof(IRQ_Detected));
                    433:   _go32_dpmi_lock_data (&SB_IntClearPort, sizeof(SB_IntClearPort));
                    434: 
                    435:   _go32_dpmi_get_protected_mode_interrupt_vector (0x0A, &oldirq2);
                    436:   _go32_dpmi_get_protected_mode_interrupt_vector (0x0D, &oldirq5);
                    437:   _go32_dpmi_get_protected_mode_interrupt_vector (0x0F, &oldirq7);
                    438:   _go32_dpmi_get_protected_mode_interrupt_vector (0x72, &oldirq10);
                    439: 
                    440:   _go32_dpmi_set_protected_mode_interrupt_vector (0x0A, &newirq2);
                    441:   _go32_dpmi_set_protected_mode_interrupt_vector (0x0D, &newirq5);
                    442:   _go32_dpmi_set_protected_mode_interrupt_vector (0x0F, &newirq7);
                    443:   _go32_dpmi_set_protected_mode_interrupt_vector (0x72, &newirq10);
                    444: 
                    445:   testbuf_info.size = NUMPARAS(TESTBUFSIZE);
                    446:   testbuf = DMA_AllocDMABuf (&testbuf_info);
                    447: 
                    448:   /* turn on interrupts 2,5,7 and 10 */
                    449:   old21 = inportb (0x21);
                    450:   oldA1 = inportb (0xA1);
                    451:   outportb (0x21, old21 & 0x5B);
                    452:   outportb (0xA1, oldA1 & 0xFB);
                    453: 
                    454:   /* turn off DMA 0,1,3,5,6 and 7 */
                    455:   old0F = inportb (0x0F);
                    456:   oldDE = inportb (0xDE);
                    457:   outportb (0x0F, old0F | 0x0B);
                    458:   outportb (0xDE, oldDE | 0x0E);
                    459: 
                    460:   /* fill testbuffer with silence */
                    461:   for (i=0; i<TESTBUFSIZE; i++) _farnspokeb (testbuf+i, 128);
                    462: 
                    463:   /* detect low DMA and IRQ */
                    464:   SB_IntClearPort = SB_Base + SB_DSP_DATA_AVAIL;
                    465:   SB_SetRate_LoSpeed (22050);
                    466:   /* program SB to play testbuffer, will start playing */
                    467:   /* when we hit the right DMA channel                 */
                    468:   SB_Play_8Bit_Std (TESTBUFSIZE);
                    469: 
                    470:   /* test all DMA channels */
                    471:   IRQ_Detected = 0;
                    472:   for (i=0; i<3; i++)
                    473:   {
                    474:     DMA_InitTransfer (lowdma[i], DMA_READ, testbuf, TESTBUFSIZE);
                    475:     delay (TESTBUFSIZE*2000 / 22050);
                    476:     if (IRQ_Detected)
                    477:     {
                    478:       *dmalo = lowdma[i];
                    479:       *irq   = IRQ_Detected;
                    480:       break;
                    481:     }
                    482:   }
                    483: 
                    484:   if (IRQ_Detected)
                    485:   {
                    486:     found = TRUE;
                    487: 
                    488:     SB_WriteDSP (CMD_DSP_VER);
                    489:     SB_VersMaj = SB_ReadDSP();
                    490:     SB_VersMin = SB_ReadDSP();
                    491: 
                    492:     /* if SoundBlaster is an SB16 then test high DMA channel */
                    493:     if (SB_VersMaj >= 4)
                    494:     {
                    495:       outportb (0x0F, old0F | 0x0B);
                    496:       outportb (0xDE, oldDE | 0x0E);
                    497: 
                    498:       for (i=0; i<TESTBUFSIZE; i+=2) _farnspokew (testbuf+i, 0x8000);
                    499: 
                    500:       SB_ModeByte = 0x00;
                    501:       SB_IntClearPort = SB_Base + SB_DSP_INT_CLEAR;
                    502:       SB_SetRate_SB16(44100);
                    503:       SB_Play_16Bit(TESTBUFSIZE);
                    504: 
                    505:       IRQ_Detected = 0;
                    506:       for (i=0; i<3; i++)
                    507:       {
                    508:        DMA_InitTransfer (highdma[i], DMA_READ, testbuf, TESTBUFSIZE);
                    509:        delay (TESTBUFSIZE*1000 / 44100);
                    510:        if (IRQ_Detected)
                    511:        {
                    512:          *dmahi = highdma[i];
                    513:          break;
                    514:        }
                    515:       }
                    516:       if (!IRQ_Detected) *dmahi = *dmalo;
                    517:     }
                    518:   }
                    519: 
                    520:   /* clean up */
                    521:   _go32_dpmi_free_dos_memory (&testbuf_info);
                    522: 
                    523:   outportb (0x0F, old0F);
                    524:   outportb (0xDE, oldDE);
                    525:   outportb (0x21, old21);
                    526:   outportb (0xA1, oldA1);
                    527: 
                    528:   _go32_dpmi_set_protected_mode_interrupt_vector (0x0A, &oldirq2);
                    529:   _go32_dpmi_set_protected_mode_interrupt_vector (0x0D, &oldirq5);
                    530:   _go32_dpmi_set_protected_mode_interrupt_vector (0x0F, &oldirq7);
                    531:   _go32_dpmi_set_protected_mode_interrupt_vector (0x72, &oldirq10);
                    532: 
                    533:   _go32_dpmi_free_iret_wrapper (&newirq2);
                    534:   _go32_dpmi_free_iret_wrapper (&newirq5);
                    535:   _go32_dpmi_free_iret_wrapper (&newirq7);
                    536:   _go32_dpmi_free_iret_wrapper (&newirq10);
                    537: 
                    538:   return (found);
                    539: }
                    540: 
                    541: int SB_InitBuffers(int bufsize)
                    542: {
                    543:   dma_buf[0].dma_mem.size = NUMPARAS(bufsize);
                    544:   dma_buf[0].Data = DMA_AllocDMABuf (&dma_buf[0].dma_mem);
                    545: 
                    546:   dma_buf[1].dma_mem.size = NUMPARAS(bufsize);
                    547:   dma_buf[1].Data = DMA_AllocDMABuf (&dma_buf[1].dma_mem);
                    548: 
                    549:   if ((dma_buf[0].Data == NULL) || (dma_buf[1].Data == NULL))
                    550:     return (FALSE);
                    551: 
                    552:   return (TRUE);
                    553: }
                    554: 
                    555: 
                    556: /* init Sound blaster using the given settings */
                    557: int SB_Init (unsigned short base, unsigned short irq,
                    558:             unsigned short dmalo, unsigned short dmahi)
                    559: {
                    560:   SB_Base  = base;
                    561:   SB_IRQ   = irq;
                    562:   SB_DMAlo = dmalo;
                    563:   SB_DMAhi = dmahi;
                    564: 
                    565:   if (SB_IRQ > 7) SB_INT = 0x68 + SB_IRQ;
                    566:             else SB_INT = 0x08 + SB_IRQ;
                    567: 
                    568:   if (!SB_Reset()) return (FALSE);
                    569: 
                    570:   pm_wrapper.pm_offset = (int) SB_IntHandler;
                    571:   if (_go32_dpmi_allocate_iret_wrapper (&pm_wrapper))
                    572:   {
                    573:     printf ("Cannot allocate protected mode wrapper for SB interrupt!\n");
                    574:     _go32_dpmi_free_dos_memory (&dma_buf[0].dma_mem);
                    575:     _go32_dpmi_free_dos_memory (&dma_buf[1].dma_mem);
                    576:     return (FALSE);
                    577:   }
                    578: 
                    579:   _go32_dpmi_lock_code (SB_WriteDSP, (ULONG)SB_WriteMixer - (ULONG)SB_WriteDSP);
                    580:   _go32_dpmi_lock_data (&SB_Base, (ULONG)&old_pmint - (ULONG)&SB_Base);
                    581: 
                    582:   _go32_dpmi_get_protected_mode_interrupt_vector (SB_INT, &old_pmint);
                    583:   _go32_dpmi_set_protected_mode_interrupt_vector (SB_INT, &pm_wrapper);
                    584: 
                    585:   if (SB_IRQ>7)
                    586:     outportb(0xA1, inportb(0xA1) & ~(1 << (SB_IRQ-8)));
                    587:   else
                    588:     outportb(0x21, inportb(0x21) & ~(1 << SB_IRQ));
                    589: 
                    590:   SB_Type = SB_Type_StdSB;
                    591: 
                    592:   if( SB_DetectMixer() != FALSE )
                    593:     SB_Type = SB_Type_SbPro;
                    594: 
                    595:   SB_WriteDSP (CMD_DSP_VER);
                    596:   SB_VersMaj = SB_ReadDSP ();
                    597:   SB_VersMin = SB_ReadDSP ();
                    598: 
                    599:   if (SB_VersMaj >= 4) SB_Type = SB_Type_SB16;
                    600: 
                    601: //  SB_Type = SB_Type_SbPro;  /* for testing */
                    602: 
                    603:   /* initialize SB to default 8Bit Mono 22050Hz */
                    604:   /* (available on all SoundBlaster Versions)   */
                    605:   switch (SB_Type)
                    606:   {
                    607:   case SB_Type_StdSB:
                    608:     SB_Play_Proc = SB_Play_8Bit_Std;
                    609:     SB_SetRate_LoSpeed(22050);
                    610:     break;
                    611:   case SB_Type_SbPro:
                    612:     SB_Play_Proc = SB_Play_8Bit_SbPro;
                    613:     SB_SetRate_HiSpeed(22050);
                    614:     break;
                    615:   case SB_Type_SB16:
                    616:     SB_Play_Proc = SB_Play_8Bit_SB16;
                    617:     SB_SetRate_SB16(22050);
                    618:     break;
                    619:   }
                    620:   SB_IntClearPort = SB_Base + SB_DSP_DATA_AVAIL;
                    621:   SB_DMA          = SB_DMAlo;
                    622:   IsPlaying       = FALSE;
                    623:   SB_16Bit        = FALSE;
                    624:   SB_Stereo       = FALSE;
                    625:   SB_Active_Rate  = 22050;
                    626:   SB_ModeByte     = 0x00;
                    627: 
                    628:   SB_SpeakerOn();
                    629:   SB_SetVolume(6);
                    630: 
                    631:   return (TRUE);
                    632: }
                    633: 
                    634: /* clean up Sound Blaster */
                    635: void SB_Done (void)
                    636: {
                    637:   SB_Reset ();
                    638:   if (SB_IRQ > 7)
                    639:     outportb (0xA1, inportb(0xA1) | (1 << (SB_IRQ-8)));
                    640:   else
                    641:     outportb (0x21, inportb(0x21) | (1 << SB_IRQ));
                    642: 
                    643:   _go32_dpmi_set_protected_mode_interrupt_vector (SB_INT, &old_pmint);
                    644:   _go32_dpmi_free_iret_wrapper (&pm_wrapper);
                    645:   _go32_dpmi_free_dos_memory (&dma_buf[0].dma_mem);
                    646:   _go32_dpmi_free_dos_memory (&dma_buf[1].dma_mem);
                    647: }
                    648: 
                    649: /* write sound data to be played to the fifo buffer */
                    650: void SB_DirectWrite(unsigned int size, int freq)
                    651: {
                    652:     DMA_InitTransfer (SB_DMA, DMA_READ, dma_buf[CurrentBuffer].Data, size);
                    653:     (*SB_Play_Proc) (size);
                    654:     IsPlaying  = TRUE;
                    655:     if (freq != SB_Active_Rate)
                    656:        SB_SetRate(freq);
                    657: }
                    658: 
                    659: /* return thee DSP chip version */
                    660: void SB_GetVersion (unsigned char *Maj, unsigned char *Min)
                    661: {
                    662:   *Maj = SB_VersMaj;
                    663:   *Min = SB_VersMin;
                    664: }
                    665: 
                    666: /* Detection Routine */
                    667: int SB_DetectInitSound(int *dspbits, int *dsprate, int *sndbufsize, unsigned int *direct_buffers, int *stereo_sound)
                    668: {
                    669:   UWORD base,irq,dmalo,dmahi;
                    670:   char *blaster;
                    671:   char *tok;
                    672:   int have_sound;
                    673:   extern void (*SND_DirectWrite)(unsigned int size, int freq);
                    674: 
                    675:   if ((*sndbufsize) > 65536)
                    676:       *sndbufsize = 65536;
                    677:   if ((*sndbufsize) < 4)
                    678:       *sndbufsize = 4;
                    679:   *sndbufsize = ((*sndbufsize)>>2)<<2;
                    680: 
                    681:   blaster = getenv ("BLASTER");
                    682:   if (blaster == NULL)
                    683:   {
                    684:     printf ("No BLASTER variable found!\n"
                    685:            "Detecting SoundBlaster Settings...."); fflush (stdout);
                    686:     have_sound = SB_Detect (&base, &irq, &dmalo, &dmahi);
                    687:     if (!have_sound)
                    688:     {
                    689:       printf ("Not found!!\n");
                    690:       return (0);
                    691:     }
                    692:     printf ("Found!  Base: %hx  IRQ: %hd  DMA: %hd,%hd\n",
                    693:                           base,     irq,    dmalo,dmahi);
                    694:   }
                    695:   else
                    696:   {
                    697:     base = 0; irq = 0; dmalo = 0; dmahi = 0;
                    698: 
                    699:     tok = strtok(blaster, " \t");
                    700:     while (tok != NULL)
                    701:     {
                    702:       switch (toupper(*tok))
                    703:       {
                    704:       case 'A': sscanf(tok+1, "%hx", &base);  break;
                    705:       case 'I': sscanf(tok+1, "%hd", &irq);   break;
                    706:       case 'D': sscanf(tok+1, "%hd", &dmalo); break;
                    707:       case 'H': sscanf(tok+1, "%hd", &dmahi); break;
                    708:       default: break;
                    709:       }
                    710:       tok = strtok (NULL, " \t");
                    711:     }
                    712:     printf ("SoundBlaster Settings taken from BLASTER variable:\n"
                    713:            "  Base: %hx  IRQ: %hd  DMA: %hd,%hd\n", base,irq,dmalo,dmahi);
                    714:   }
                    715: 
                    716:   if (!SB_InitBuffers(*sndbufsize))
                    717:   {
                    718:       fprintf(stderr, "Can't set sound buffers to %d!\n", *sndbufsize);
                    719:       return(0);
                    720:   }
                    721: 
                    722:   have_sound = SB_Init (base, irq, dmalo, dmahi);
                    723:   if (!have_sound)
                    724:   {
                    725:     printf ("Cannot Initialize Soundblaster!\n");
                    726:     return (0);
                    727:   }
                    728: 
                    729:   if (((*dspbits) == 16) && (SB_SetBits (16)))
                    730:     SB_SetSigned (1);
                    731:   else
                    732:     *dspbits = 8;
                    733: 
                    734:   if (*stereo_sound) {
                    735:      *stereo_sound = SB_SetChannels(2);
                    736:      if (!(*stereo_sound))
                    737:         fprintf(stderr, "Warning, stereo not suporeted!\n");
                    738:   }
                    739: 
                    740:   if (!SB_SetRate(*dsprate))
                    741:   {
                    742:       fprintf(stderr, "SoundBlaster%s can't use sample rate %d!\n",
                    743:               SB_Type==SB_Type_StdSB ? "" :
                    744:              (SB_Type==SB_Type_SbPro ? " PRO" : " 16"),
                    745:              *dsprate);
                    746:       return(0);
                    747:   }
                    748: 
                    749:   printf ("SoundBlaster%s found.\n",
                    750:           SB_Type==SB_Type_StdSB ? "" :
                    751:          (SB_Type==SB_Type_SbPro ? " PRO" : " 16"));
                    752: 
                    753:   SND_DirectWrite = SB_DirectWrite;
                    754:   direct_buffers[0] = dma_buf[0].Data;
                    755:   direct_buffers[1] = dma_buf[1].Data;
                    756: 
                    757:   atexit (SB_Done);
                    758: 
                    759:   return 1;
                    760: }
                    761: 
                    762: /* that's it... */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.