Annotation of uae/src/od-dos/sound/sb.c, revision 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.