SNDSCAPE.C 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662
  1. /*
  2. Copyright (C) 1994-1995 Apogee Software, Ltd.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. /**********************************************************************
  16. module: SNDSCAPE.C
  17. author: James R. Dose
  18. date: October 25, 1994
  19. Low level routines to support the Ensoniq Soundscape.
  20. (c) Copyright 1994 James R. Dose. All Rights Reserved.
  21. **********************************************************************/
  22. #include <dos.h>
  23. #include <conio.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <ctype.h>
  28. #include <time.h>
  29. #include "interrup.h"
  30. #include "dpmi.h"
  31. #include "dma.h"
  32. #include "irq.h"
  33. #include "sndscape.h"
  34. #include "_sndscap.h"
  35. const int SOUNDSCAPE_Interrupts[ SOUNDSCAPE_MaxIrq + 1 ] =
  36. {
  37. INVALID, INVALID, 0xa, INVALID,
  38. INVALID, 0xd, INVALID, 0xf,
  39. INVALID, INVALID, 0x72, INVALID,
  40. INVALID, INVALID, INVALID, INVALID
  41. };
  42. const int SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MaxMixMode + 1 ] =
  43. {
  44. MONO_8BIT_SAMPLE_SIZE, STEREO_8BIT_SAMPLE_SIZE,
  45. MONO_16BIT_SAMPLE_SIZE, STEREO_16BIT_SAMPLE_SIZE
  46. };
  47. static void ( __interrupt __far *SOUNDSCAPE_OldInt )( void );
  48. static int SOUNDSCAPE_Installed = FALSE;
  49. static int SOUNDSCAPE_FoundCard = FALSE;
  50. static char *SOUNDSCAPE_DMABuffer;
  51. static char *SOUNDSCAPE_DMABufferEnd;
  52. static char *SOUNDSCAPE_CurrentDMABuffer;
  53. static int SOUNDSCAPE_TotalDMABufferSize;
  54. static int SOUNDSCAPE_TransferLength = 0;
  55. static int SOUNDSCAPE_MixMode = SOUNDSCAPE_DefaultMixMode;
  56. static int SOUNDSCAPE_SamplePacketSize = MONO_16BIT_SAMPLE_SIZE;
  57. static unsigned SOUNDSCAPE_SampleRate = SOUNDSCAPE_DefaultSampleRate;
  58. volatile int SOUNDSCAPE_SoundPlaying;
  59. void ( *SOUNDSCAPE_CallBack )( void );
  60. static int SOUNDSCAPE_IntController1Mask;
  61. static int SOUNDSCAPE_IntController2Mask;
  62. // some globals for chip type, ports, DMA, IRQs ... and stuff
  63. static struct
  64. {
  65. int BasePort; // base address of the Ensoniq gate-array chip
  66. int WavePort; // the AD-1848 base address
  67. int DMAChan; // the DMA channel used for PCM
  68. int WaveIRQ; // the PCM IRQ
  69. int MIDIIRQ; // the MPU-401 IRQ
  70. int ChipID; // the Ensoniq chip type
  71. int SBEmul; // SoundBlaster emulation flag
  72. int CDROM; // CD-ROM flag
  73. int IRQIndx; // the Wave IRQ index - for hardware regs
  74. int OldIRQs; // Old IRQs flag to support older HW
  75. } SOUNDSCAPE_Config;
  76. // adequate stack size
  77. #define kStackSize 2048
  78. static unsigned short StackSelector = NULL;
  79. static unsigned long StackPointer;
  80. static unsigned short oldStackSelector;
  81. static unsigned long oldStackPointer;
  82. // These declarations are necessary to use the inline assembly pragmas.
  83. extern void GetStack(unsigned short *selptr,unsigned long *stackptr);
  84. extern void SetStack(unsigned short selector,unsigned long stackptr);
  85. // This function will get the current stack selector and pointer and save
  86. // them off.
  87. #pragma aux GetStack = \
  88. "mov [edi],esp" \
  89. "mov ax,ss" \
  90. "mov [esi],ax" \
  91. parm [esi] [edi] \
  92. modify [eax esi edi];
  93. // This function will set the stack selector and pointer to the specified
  94. // values.
  95. #pragma aux SetStack = \
  96. "mov ss,ax" \
  97. "mov esp,edx" \
  98. parm [ax] [edx] \
  99. modify [eax edx];
  100. int SOUNDSCAPE_DMAChannel = -1;
  101. int SOUNDSCAPE_ErrorCode = SOUNDSCAPE_Ok;
  102. #define SOUNDSCAPE_SetErrorCode( status ) \
  103. SOUNDSCAPE_ErrorCode = ( status );
  104. /*---------------------------------------------------------------------
  105. Function: SOUNDSCAPE_ErrorString
  106. Returns a pointer to the error message associated with an error
  107. number. A -1 returns a pointer the current error.
  108. ---------------------------------------------------------------------*/
  109. char *SOUNDSCAPE_ErrorString
  110. (
  111. int ErrorNumber
  112. )
  113. {
  114. char *ErrorString;
  115. switch( ErrorNumber )
  116. {
  117. case SOUNDSCAPE_Warning :
  118. case SOUNDSCAPE_Error :
  119. ErrorString = SOUNDSCAPE_ErrorString( SOUNDSCAPE_ErrorCode );
  120. break;
  121. case SOUNDSCAPE_Ok :
  122. ErrorString = "SoundScape ok.";
  123. break;
  124. case SOUNDSCAPE_EnvNotFound :
  125. ErrorString = "SNDSCAPE environment variable not set. This is used to locate \n"
  126. "SNDSCAPE.INI which is used to describe your sound card setup.";
  127. break;
  128. case SOUNDSCAPE_InitFileNotFound :
  129. ErrorString = "Missing SNDSCAPE.INI file for SoundScape. This file should be \n"
  130. "located in the directory indicated by the SNDSCAPE environment \n"
  131. "variable or in 'C:\SNDSCAPE' if SNDSCAPE is not set.";
  132. break;
  133. case SOUNDSCAPE_MissingProductInfo :
  134. ErrorString = "Missing 'Product' field in SNDSCAPE.INI file for SoundScape.";
  135. break;
  136. case SOUNDSCAPE_MissingPortInfo :
  137. ErrorString = "Missing 'Port' field in SNDSCAPE.INI file for SoundScape.";
  138. break;
  139. case SOUNDSCAPE_MissingDMAInfo :
  140. ErrorString = "Missing 'DMA' field in SNDSCAPE.INI file for SoundScape.";
  141. break;
  142. case SOUNDSCAPE_MissingIRQInfo :
  143. ErrorString = "Missing 'IRQ' field in SNDSCAPE.INI file for SoundScape.";
  144. break;
  145. case SOUNDSCAPE_MissingSBIRQInfo :
  146. ErrorString = "Missing 'SBIRQ' field in SNDSCAPE.INI file for SoundScape.";
  147. break;
  148. case SOUNDSCAPE_MissingSBENABLEInfo :
  149. ErrorString = "Missing 'SBEnable' field in SNDSCAPE.INI file for SoundScape.";
  150. break;
  151. case SOUNDSCAPE_MissingWavePortInfo :
  152. ErrorString = "Missing 'WavePort' field in SNDSCAPE.INI file for SoundScape.";
  153. break;
  154. case SOUNDSCAPE_HardwareError :
  155. ErrorString = "Could not detect SoundScape. Make sure your SNDSCAPE.INI file \n"
  156. "contains correct information about your hardware setup.";
  157. break;
  158. case SOUNDSCAPE_NoSoundPlaying :
  159. ErrorString = "No sound playing on SoundScape.";
  160. break;
  161. case SOUNDSCAPE_InvalidSBIrq :
  162. ErrorString = "Invalid SoundScape Irq in SBIRQ field of SNDSCAPE.INI.";
  163. break;
  164. case SOUNDSCAPE_UnableToSetIrq :
  165. ErrorString = "Unable to set SoundScape IRQ. Try selecting an IRQ of 7 or below.";
  166. break;
  167. case SOUNDSCAPE_DmaError :
  168. ErrorString = DMA_ErrorString( DMA_Error );
  169. break;
  170. case SOUNDSCAPE_DPMI_Error :
  171. ErrorString = "DPMI Error in SoundScape.";
  172. break;
  173. case SOUNDSCAPE_OutOfMemory :
  174. ErrorString = "Out of conventional memory in SoundScape.";
  175. break;
  176. default :
  177. ErrorString = "Unknown SoundScape error code.";
  178. break;
  179. }
  180. return( ErrorString );
  181. }
  182. /**********************************************************************
  183. Memory locked functions:
  184. **********************************************************************/
  185. #define SOUNDSCAPE_LockStart SOUNDSCAPE_EnableInterrupt
  186. /*---------------------------------------------------------------------
  187. Function: SOUNDSCAPE_EnableInterrupt
  188. Enables the triggering of the sound card interrupt.
  189. ---------------------------------------------------------------------*/
  190. static void SOUNDSCAPE_EnableInterrupt
  191. (
  192. void
  193. )
  194. {
  195. int mask;
  196. // Unmask system interrupt
  197. if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
  198. {
  199. mask = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
  200. outp( 0x21, mask );
  201. }
  202. else
  203. {
  204. mask = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
  205. outp( 0xA1, mask );
  206. mask = inp( 0x21 ) & ~( 1 << 2 );
  207. outp( 0x21, mask );
  208. }
  209. }
  210. /*---------------------------------------------------------------------
  211. Function: SOUNDSCAPE_DisableInterrupt
  212. Disables the triggering of the sound card interrupt.
  213. ---------------------------------------------------------------------*/
  214. static void SOUNDSCAPE_DisableInterrupt
  215. (
  216. void
  217. )
  218. {
  219. int mask;
  220. // Restore interrupt mask
  221. if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
  222. {
  223. mask = inp( 0x21 ) & ~( 1 << SOUNDSCAPE_Config.WaveIRQ );
  224. mask |= SOUNDSCAPE_IntController1Mask & ( 1 << SOUNDSCAPE_Config.WaveIRQ );
  225. outp( 0x21, mask );
  226. }
  227. else
  228. {
  229. mask = inp( 0x21 ) & ~( 1 << 2 );
  230. mask |= SOUNDSCAPE_IntController1Mask & ( 1 << 2 );
  231. outp( 0x21, mask );
  232. mask = inp( 0xA1 ) & ~( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
  233. mask |= SOUNDSCAPE_IntController2Mask & ( 1 << ( SOUNDSCAPE_Config.WaveIRQ - 8 ) );
  234. outp( 0xA1, mask );
  235. }
  236. }
  237. /*---------------------------------------------------------------------
  238. Function: SOUNDSCAPE_ServiceInterrupt
  239. Handles interrupt generated by sound card at the end of a voice
  240. transfer. Calls the user supplied callback function.
  241. ---------------------------------------------------------------------*/
  242. static void __interrupt __far SOUNDSCAPE_ServiceInterrupt
  243. (
  244. void
  245. )
  246. {
  247. // save stack
  248. GetStack( &oldStackSelector, &oldStackPointer );
  249. // set our stack
  250. SetStack( StackSelector, StackPointer );
  251. if ( !( inp( SOUNDSCAPE_Config.WavePort + AD_STATUS ) & 0x01 ) )
  252. {
  253. // restore stack
  254. SetStack( oldStackSelector, oldStackPointer );
  255. // Wasn't our interrupt. Call the old one.
  256. _chain_intr( SOUNDSCAPE_OldInt );
  257. }
  258. // clear the AD-1848 interrupt
  259. outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
  260. // Keep track of current buffer
  261. SOUNDSCAPE_CurrentDMABuffer += SOUNDSCAPE_TransferLength;
  262. if ( SOUNDSCAPE_CurrentDMABuffer >= SOUNDSCAPE_DMABufferEnd )
  263. {
  264. SOUNDSCAPE_CurrentDMABuffer = SOUNDSCAPE_DMABuffer;
  265. }
  266. // Call the caller's callback function
  267. if ( SOUNDSCAPE_CallBack != NULL )
  268. {
  269. SOUNDSCAPE_CallBack();
  270. }
  271. // restore stack
  272. SetStack( oldStackSelector, oldStackPointer );
  273. // send EOI to Interrupt Controller
  274. if ( SOUNDSCAPE_Config.WaveIRQ > 7 )
  275. {
  276. outp( 0xA0, 0x20 );
  277. }
  278. outp( 0x20, 0x20 );
  279. }
  280. /*---------------------------------------------------------------------
  281. Function: ga_read
  282. Reads Ensoniq indirect registers.
  283. ---------------------------------------------------------------------*/
  284. static int ga_read
  285. (
  286. int rnum
  287. )
  288. {
  289. int data;
  290. outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
  291. data = inp( SOUNDSCAPE_Config.BasePort + GA_REGDATA );
  292. return( data );
  293. }
  294. /*---------------------------------------------------------------------
  295. Function: ga_write
  296. Writes to Ensoniq indirect registers.
  297. ---------------------------------------------------------------------*/
  298. static void ga_write
  299. (
  300. int rnum,
  301. int value
  302. )
  303. {
  304. outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, rnum );
  305. outp( SOUNDSCAPE_Config.BasePort + GA_REGDATA, value );
  306. }
  307. /*---------------------------------------------------------------------
  308. Function: ad_read
  309. Reads the AD-1848 indirect registers. This function should not be
  310. used while the AD-1848 mode change is enabled
  311. ---------------------------------------------------------------------*/
  312. static int ad_read
  313. (
  314. int rnum
  315. )
  316. {
  317. int data;
  318. outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
  319. data = inp( SOUNDSCAPE_Config.WavePort + AD_REGDATA );
  320. return( data );
  321. }
  322. /*---------------------------------------------------------------------
  323. Function: ad_write
  324. Writes to the AD-1848 indirect registers. This function should
  325. not be used while the AD-1848 mode change is enabled.
  326. ---------------------------------------------------------------------*/
  327. static void ad_write
  328. (
  329. int rnum,
  330. int value
  331. )
  332. {
  333. outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, rnum );
  334. outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, value );
  335. }
  336. /*---------------------------------------------------------------------
  337. Function: tdelay
  338. Delay function - 250ms - for AD-1848 re-synch and autocalibration.
  339. ---------------------------------------------------------------------*/
  340. static void tdelay
  341. (
  342. void
  343. )
  344. {
  345. long time;
  346. unsigned flags;
  347. flags = DisableInterrupts();
  348. _enable();
  349. time = clock() + CLOCKS_PER_SEC/4;
  350. while(clock() < time)
  351. ;
  352. RestoreInterrupts( flags );
  353. }
  354. /*---------------------------------------------------------------------
  355. Function: pcm_format
  356. Sets the PCM data format.
  357. ---------------------------------------------------------------------*/
  358. static void pcm_format
  359. (
  360. void
  361. )
  362. {
  363. int format;
  364. // build the register value based on format
  365. format = 0;
  366. switch( SOUNDSCAPE_SampleRate )
  367. {
  368. case 11025:
  369. format = 0x03;
  370. break;
  371. case 22050:
  372. format = 0x07;
  373. break;
  374. case 44100:
  375. format = 0x0b;
  376. break;
  377. default:
  378. // Set it to 11025 hz
  379. format = 0x03;
  380. break;
  381. }
  382. // set other format bits and format globals
  383. if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
  384. {
  385. format |= 0x40;
  386. }
  387. if ( SOUNDSCAPE_MixMode & STEREO )
  388. {
  389. format |= 0x10;
  390. }
  391. // enable mode change, point to format reg
  392. outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_FORMAT );
  393. // write the format
  394. outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, format );
  395. // delay for internal re-synch
  396. tdelay();
  397. // exit mode change state
  398. outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
  399. // delay for autocalibration
  400. tdelay();
  401. }
  402. /*---------------------------------------------------------------------
  403. Function: SOUNDSCAPE_SetPlaybackRate
  404. Sets the rate at which the digitized sound will be played in
  405. hertz.
  406. ---------------------------------------------------------------------*/
  407. void SOUNDSCAPE_SetPlaybackRate
  408. (
  409. unsigned rate
  410. )
  411. {
  412. if ( rate < 20000 )
  413. {
  414. rate = 11025;
  415. }
  416. else if ( rate < 30000 )
  417. {
  418. rate = 22050;
  419. }
  420. else
  421. {
  422. rate = 44100;
  423. }
  424. SOUNDSCAPE_SampleRate = rate;
  425. // Set the rate
  426. pcm_format();
  427. }
  428. /*---------------------------------------------------------------------
  429. Function: SOUNDSCAPE_GetPlaybackRate
  430. Returns the rate at which the digitized sound will be played in
  431. hertz.
  432. ---------------------------------------------------------------------*/
  433. unsigned SOUNDSCAPE_GetPlaybackRate
  434. (
  435. void
  436. )
  437. {
  438. return( SOUNDSCAPE_SampleRate );
  439. }
  440. /*---------------------------------------------------------------------
  441. Function: SOUNDSCAPE_SetMixMode
  442. Sets the sound card to play samples in mono or stereo.
  443. ---------------------------------------------------------------------*/
  444. int SOUNDSCAPE_SetMixMode
  445. (
  446. int mode
  447. )
  448. {
  449. SOUNDSCAPE_MixMode = mode & SOUNDSCAPE_MaxMixMode;
  450. SOUNDSCAPE_SamplePacketSize = SOUNDSCAPE_SampleSize[ SOUNDSCAPE_MixMode ];
  451. // Set the mixmode
  452. pcm_format();
  453. return( mode );
  454. }
  455. /*---------------------------------------------------------------------
  456. Function: SOUNDSCAPE_StopPlayback
  457. Ends the DMA transfer of digitized sound to the sound card.
  458. ---------------------------------------------------------------------*/
  459. void SOUNDSCAPE_StopPlayback
  460. (
  461. void
  462. )
  463. {
  464. // Don't allow anymore interrupts
  465. SOUNDSCAPE_DisableInterrupt();
  466. /* stop the AD-1848 */
  467. ad_write( AD_CONFIG, 0x00 );
  468. /* let it finish it's cycles */
  469. tdelay();
  470. // Disable the DMA channel
  471. DMA_EndTransfer( SOUNDSCAPE_Config.DMAChan );
  472. SOUNDSCAPE_SoundPlaying = FALSE;
  473. SOUNDSCAPE_DMABuffer = NULL;
  474. }
  475. /*---------------------------------------------------------------------
  476. Function: SOUNDSCAPE_SetupDMABuffer
  477. Programs the DMAC for sound transfer.
  478. ---------------------------------------------------------------------*/
  479. static int SOUNDSCAPE_SetupDMABuffer
  480. (
  481. char *BufferPtr,
  482. int BufferSize,
  483. int mode
  484. )
  485. {
  486. int DmaStatus;
  487. DmaStatus = DMA_SetupTransfer( SOUNDSCAPE_Config.DMAChan, BufferPtr, BufferSize, mode );
  488. if ( DmaStatus == DMA_Error )
  489. {
  490. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
  491. return( SOUNDSCAPE_Error );
  492. }
  493. SOUNDSCAPE_DMAChannel = SOUNDSCAPE_Config.DMAChan;
  494. SOUNDSCAPE_DMABuffer = BufferPtr;
  495. SOUNDSCAPE_CurrentDMABuffer = BufferPtr;
  496. SOUNDSCAPE_TotalDMABufferSize = BufferSize;
  497. SOUNDSCAPE_DMABufferEnd = BufferPtr + BufferSize;
  498. return( SOUNDSCAPE_Ok );
  499. }
  500. /*---------------------------------------------------------------------
  501. Function: SOUNDSCAPE_GetCurrentPos
  502. Returns the offset within the current sound being played.
  503. ---------------------------------------------------------------------*/
  504. int SOUNDSCAPE_GetCurrentPos
  505. (
  506. void
  507. )
  508. {
  509. char *CurrentAddr;
  510. int offset;
  511. if ( !SOUNDSCAPE_SoundPlaying )
  512. {
  513. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_NoSoundPlaying );
  514. return( SOUNDSCAPE_Error );
  515. }
  516. CurrentAddr = DMA_GetCurrentPos( SOUNDSCAPE_Config.DMAChan );
  517. offset = ( int )( ( ( unsigned long )CurrentAddr ) -
  518. ( ( unsigned long )SOUNDSCAPE_CurrentDMABuffer ) );
  519. if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
  520. {
  521. offset >>= 1;
  522. }
  523. if ( SOUNDSCAPE_MixMode & STEREO )
  524. {
  525. offset >>= 1;
  526. }
  527. return( offset );
  528. }
  529. /*---------------------------------------------------------------------
  530. Function: SOUNDSCAPE_BeginPlayback
  531. Starts playback of digitized sound.
  532. ---------------------------------------------------------------------*/
  533. static int SOUNDSCAPE_BeginPlayback
  534. (
  535. int length
  536. )
  537. {
  538. int SampleLength;
  539. int LoByte;
  540. int HiByte;
  541. if ( SOUNDSCAPE_MixMode & SIXTEEN_BIT )
  542. {
  543. SampleLength = length / 2;
  544. }
  545. else
  546. {
  547. SampleLength = length;
  548. }
  549. if ( SOUNDSCAPE_MixMode & STEREO )
  550. {
  551. SampleLength >>= 1;
  552. }
  553. SampleLength--;
  554. // setup the AD-1848 interrupt count
  555. // set the interrupt count value based on the format.
  556. // count will decrement every sample period and generate
  557. // an interrupt when in rolls over. we want this always
  558. // to be at every 1/2 buffer, regardless of the data format,
  559. // so the count must be adjusted accordingly.
  560. HiByte = hibyte( SampleLength );
  561. LoByte = lobyte( SampleLength );
  562. ad_write( AD_LCOUNT, LoByte );
  563. ad_write( AD_UCOUNT, HiByte );
  564. /* unmask the host DMA controller */
  565. SOUNDSCAPE_EnableInterrupt();
  566. /* start the AD-1848 */
  567. ad_write(AD_CONFIG, 0x01);
  568. SOUNDSCAPE_SoundPlaying = TRUE;
  569. return( SOUNDSCAPE_Ok );
  570. }
  571. /*---------------------------------------------------------------------
  572. Function: SOUNDSCAPE_BeginBufferedPlayback
  573. Begins multibuffered playback of digitized sound on the sound card.
  574. ---------------------------------------------------------------------*/
  575. int SOUNDSCAPE_BeginBufferedPlayback
  576. (
  577. char *BufferStart,
  578. int BufferSize,
  579. int NumDivisions,
  580. unsigned SampleRate,
  581. int MixMode,
  582. void ( *CallBackFunc )( void )
  583. )
  584. {
  585. int DmaStatus;
  586. int TransferLength;
  587. if ( SOUNDSCAPE_SoundPlaying )
  588. {
  589. SOUNDSCAPE_StopPlayback();
  590. }
  591. SOUNDSCAPE_SetMixMode( MixMode );
  592. DmaStatus = SOUNDSCAPE_SetupDMABuffer( BufferStart, BufferSize,
  593. DMA_AutoInitRead );
  594. if ( DmaStatus == SOUNDSCAPE_Error )
  595. {
  596. return( SOUNDSCAPE_Error );
  597. }
  598. SOUNDSCAPE_SetPlaybackRate( SampleRate );
  599. SOUNDSCAPE_SetCallBack( CallBackFunc );
  600. SOUNDSCAPE_EnableInterrupt();
  601. TransferLength = BufferSize / NumDivisions;
  602. SOUNDSCAPE_TransferLength = TransferLength;
  603. SOUNDSCAPE_BeginPlayback( TransferLength );
  604. return( SOUNDSCAPE_Ok );
  605. }
  606. /*---------------------------------------------------------------------
  607. Function: SOUNDSCAPE_GetCardInfo
  608. Returns the maximum number of bits that can represent a sample
  609. (8 or 16) and the number of channels (1 for mono, 2 for stereo).
  610. ---------------------------------------------------------------------*/
  611. int SOUNDSCAPE_GetCardInfo
  612. (
  613. int *MaxSampleBits,
  614. int *MaxChannels
  615. )
  616. {
  617. int status;
  618. status = SOUNDSCAPE_FindCard();
  619. if ( status == SOUNDSCAPE_Ok )
  620. {
  621. *MaxChannels = 2;
  622. *MaxSampleBits = 16;
  623. return( SOUNDSCAPE_Ok );
  624. }
  625. return( status );
  626. }
  627. /*---------------------------------------------------------------------
  628. Function: SOUNDSCAPE_SetCallBack
  629. Specifies the user function to call at the end of a sound transfer.
  630. ---------------------------------------------------------------------*/
  631. void SOUNDSCAPE_SetCallBack
  632. (
  633. void ( *func )( void )
  634. )
  635. {
  636. SOUNDSCAPE_CallBack = func;
  637. }
  638. /*---------------------------------------------------------------------
  639. Function: SOUNDSCAPE_LockEnd
  640. Used for determining the length of the functions to lock in memory.
  641. ---------------------------------------------------------------------*/
  642. static void SOUNDSCAPE_LockEnd
  643. (
  644. void
  645. )
  646. {
  647. }
  648. /*---------------------------------------------------------------------
  649. Function: SOUNDSCAPE_UnlockMemory
  650. Unlocks all neccessary data.
  651. ---------------------------------------------------------------------*/
  652. static void SOUNDSCAPE_UnlockMemory
  653. (
  654. void
  655. )
  656. {
  657. DPMI_UnlockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
  658. DPMI_Unlock( SOUNDSCAPE_Config );
  659. DPMI_Unlock( SOUNDSCAPE_OldInt );
  660. DPMI_Unlock( SOUNDSCAPE_Installed );
  661. DPMI_Unlock( SOUNDSCAPE_DMABuffer );
  662. DPMI_Unlock( SOUNDSCAPE_DMABufferEnd );
  663. DPMI_Unlock( SOUNDSCAPE_CurrentDMABuffer );
  664. DPMI_Unlock( SOUNDSCAPE_TotalDMABufferSize );
  665. DPMI_Unlock( SOUNDSCAPE_TransferLength );
  666. DPMI_Unlock( SOUNDSCAPE_MixMode );
  667. DPMI_Unlock( SOUNDSCAPE_SamplePacketSize );
  668. DPMI_Unlock( SOUNDSCAPE_SampleRate );
  669. DPMI_Unlock( SOUNDSCAPE_SoundPlaying );
  670. DPMI_Unlock( SOUNDSCAPE_CallBack );
  671. DPMI_Unlock( SOUNDSCAPE_IntController1Mask );
  672. DPMI_Unlock( SOUNDSCAPE_IntController2Mask );
  673. }
  674. /*---------------------------------------------------------------------
  675. Function: SOUNDSCAPE_LockMemory
  676. Locks all neccessary data.
  677. ---------------------------------------------------------------------*/
  678. static int SOUNDSCAPE_LockMemory
  679. (
  680. void
  681. )
  682. {
  683. int status;
  684. status = DPMI_LockMemoryRegion( SOUNDSCAPE_LockStart, SOUNDSCAPE_LockEnd );
  685. status |= DPMI_Lock( SOUNDSCAPE_Config );
  686. status |= DPMI_Lock( SOUNDSCAPE_OldInt );
  687. status |= DPMI_Lock( SOUNDSCAPE_Installed );
  688. status |= DPMI_Lock( SOUNDSCAPE_DMABuffer );
  689. status |= DPMI_Lock( SOUNDSCAPE_DMABufferEnd );
  690. status |= DPMI_Lock( SOUNDSCAPE_CurrentDMABuffer );
  691. status |= DPMI_Lock( SOUNDSCAPE_TotalDMABufferSize );
  692. status |= DPMI_Lock( SOUNDSCAPE_TransferLength );
  693. status |= DPMI_Lock( SOUNDSCAPE_MixMode );
  694. status |= DPMI_Lock( SOUNDSCAPE_SamplePacketSize );
  695. status |= DPMI_Lock( SOUNDSCAPE_SampleRate );
  696. status |= DPMI_Lock( SOUNDSCAPE_SoundPlaying );
  697. status |= DPMI_Lock( SOUNDSCAPE_CallBack );
  698. status |= DPMI_Lock( SOUNDSCAPE_IntController1Mask );
  699. status |= DPMI_Lock( SOUNDSCAPE_IntController2Mask );
  700. if ( status != DPMI_Ok )
  701. {
  702. SOUNDSCAPE_UnlockMemory();
  703. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DPMI_Error );
  704. return( SOUNDSCAPE_Error );
  705. }
  706. return( SOUNDSCAPE_Ok );
  707. }
  708. /*---------------------------------------------------------------------
  709. Function: allocateTimerStack
  710. Allocate a block of memory from conventional (low) memory and return
  711. the selector (which can go directly into a segment register) of the
  712. memory block or 0 if an error occured.
  713. ---------------------------------------------------------------------*/
  714. static unsigned short allocateTimerStack
  715. (
  716. unsigned short size
  717. )
  718. {
  719. union REGS regs;
  720. // clear all registers
  721. memset( &regs, 0, sizeof( regs ) );
  722. // DPMI allocate conventional memory
  723. regs.w.ax = 0x100;
  724. // size in paragraphs
  725. regs.w.bx = ( size + 15 ) / 16;
  726. int386( 0x31, &regs, &regs );
  727. if (!regs.w.cflag)
  728. {
  729. // DPMI call returns selector in dx
  730. // (ax contains real mode segment
  731. // which is ignored here)
  732. return( regs.w.dx );
  733. }
  734. // Couldn't allocate memory.
  735. return( NULL );
  736. }
  737. /*---------------------------------------------------------------------
  738. Function: deallocateTimerStack
  739. Deallocate a block of conventional (low) memory given a selector to
  740. it. Assumes the block was allocated with DPMI function 0x100.
  741. ---------------------------------------------------------------------*/
  742. static void deallocateTimerStack
  743. (
  744. unsigned short selector
  745. )
  746. {
  747. union REGS regs;
  748. if ( selector != NULL )
  749. {
  750. // clear all registers
  751. memset( &regs, 0, sizeof( regs ) );
  752. regs.w.ax = 0x101;
  753. regs.w.dx = selector;
  754. int386( 0x31, &regs, &regs );
  755. }
  756. }
  757. /*---------------------------------------------------------------------
  758. Function: parse
  759. Parses for the right hand string of an .INI file equate.
  760. ---------------------------------------------------------------------*/
  761. static int parse
  762. (
  763. char *val,
  764. char *str,
  765. FILE *p1
  766. )
  767. {
  768. int i;
  769. int j;
  770. char tmpstr[ 81 ];
  771. rewind( p1 );
  772. while( !feof( p1 ) )
  773. {
  774. // get a new string
  775. fgets( tmpstr, 81, p1 );
  776. if( ( tmpstr[ 0 ] == '[' ) || ( tmpstr[ 0 ] == ';' ) ||
  777. ( tmpstr[ 0 ] == '\n' ) )
  778. {
  779. continue;
  780. }
  781. // parse up to the '='
  782. i = 0;
  783. while( ( tmpstr[ i ] != '=' ) && ( tmpstr[ i ] != '\n' ) )
  784. {
  785. i++;
  786. }
  787. if( tmpstr[ i ] != '=' )
  788. {
  789. continue;
  790. }
  791. tmpstr[ i ] = '\0';
  792. // see if it's the one we want
  793. if ( strcmp( tmpstr, str ) )
  794. {
  795. continue;
  796. }
  797. // copy the right hand value to the destination string
  798. i++;
  799. for( j = 0; j < 32; j++ )
  800. {
  801. if ( ( tmpstr[ i ] == ' ' ) || ( tmpstr[ i ] == '\t' ) ||
  802. ( tmpstr[ i ] == ',' ) || ( tmpstr[ i ] == '\n' ) )
  803. {
  804. break;
  805. }
  806. val[ j ] = tmpstr[ i ];
  807. i++;
  808. }
  809. val[j] = '\0';
  810. return( TRUE );
  811. }
  812. return( FALSE );
  813. }
  814. /*---------------------------------------------------------------------
  815. Function: SOUNDSCAPE_FindCard
  816. Determines if a SoundScape is present and where it is located.
  817. ---------------------------------------------------------------------*/
  818. static int SOUNDSCAPE_FindCard
  819. (
  820. void
  821. )
  822. {
  823. int found;
  824. int status;
  825. int tmp;
  826. char *cp;
  827. char str[ 33 ];
  828. FILE *fp;
  829. if ( SOUNDSCAPE_FoundCard )
  830. {
  831. return( SOUNDSCAPE_Ok );
  832. }
  833. cp = getenv( "SNDSCAPE" );
  834. if ( cp == NULL )
  835. {
  836. strcpy( str, "C:\\SNDSCAPE" );
  837. }
  838. else
  839. {
  840. strcpy( str, cp );
  841. }
  842. strcat(str, "\\SNDSCAPE.INI");
  843. fp = fopen( str, "r" );
  844. if ( fp == NULL )
  845. {
  846. if ( cp == NULL )
  847. {
  848. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_EnvNotFound );
  849. return( SOUNDSCAPE_Error );
  850. }
  851. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InitFileNotFound );
  852. return( SOUNDSCAPE_Error );
  853. }
  854. found = parse( str, "Product", fp );
  855. if ( !found )
  856. {
  857. fclose( fp );
  858. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingProductInfo );
  859. return( SOUNDSCAPE_Error );
  860. }
  861. if( strstr( str, "SoundFX" ) == NULL )
  862. {
  863. SOUNDSCAPE_Config.OldIRQs = FALSE;
  864. }
  865. else
  866. {
  867. SOUNDSCAPE_Config.OldIRQs = TRUE;
  868. }
  869. found = parse( str, "Port", fp );
  870. if ( !found )
  871. {
  872. fclose( fp );
  873. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingPortInfo );
  874. return( SOUNDSCAPE_Error );
  875. }
  876. SOUNDSCAPE_Config.BasePort = strtol( str, ( char ** )0, 16);
  877. found = parse( str, "DMA", fp );
  878. if ( !found )
  879. {
  880. fclose( fp );
  881. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingDMAInfo );
  882. return( SOUNDSCAPE_Error );
  883. }
  884. SOUNDSCAPE_Config.DMAChan = ( int )strtol( str, ( char ** )0, 10 );
  885. status = DMA_VerifyChannel( SOUNDSCAPE_Config.DMAChan );
  886. if ( status == DMA_Error )
  887. {
  888. fclose( fp );
  889. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_DmaError );
  890. return( SOUNDSCAPE_Error );
  891. }
  892. found = parse( str, "IRQ", fp );
  893. if ( !found )
  894. {
  895. fclose( fp );
  896. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingIRQInfo );
  897. return( SOUNDSCAPE_Error );
  898. }
  899. SOUNDSCAPE_Config.MIDIIRQ = ( int )strtol( str, ( char ** )0, 10 );
  900. if ( SOUNDSCAPE_Config.MIDIIRQ == 2 )
  901. {
  902. SOUNDSCAPE_Config.MIDIIRQ = 9;
  903. }
  904. found = parse( str, "SBIRQ", fp );
  905. if ( !found )
  906. {
  907. fclose( fp );
  908. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBIRQInfo );
  909. return( SOUNDSCAPE_Error );
  910. }
  911. SOUNDSCAPE_Config.WaveIRQ = ( int )strtol( str, ( char ** )0, 10 );
  912. if ( SOUNDSCAPE_Config.WaveIRQ == 2 )
  913. {
  914. SOUNDSCAPE_Config.WaveIRQ = 9;
  915. }
  916. if ( !VALID_IRQ( SOUNDSCAPE_Config.WaveIRQ ) )
  917. {
  918. fclose( fp );
  919. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
  920. return( SOUNDSCAPE_Error );
  921. }
  922. if ( SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ] == INVALID )
  923. {
  924. fclose( fp );
  925. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_InvalidSBIrq );
  926. return( SOUNDSCAPE_Error );
  927. }
  928. found = parse( str, "SBEnable", fp );
  929. if ( !found )
  930. {
  931. fclose( fp );
  932. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingSBENABLEInfo );
  933. return( SOUNDSCAPE_Error );
  934. }
  935. if( !strcmp( str, "false" ) )
  936. {
  937. SOUNDSCAPE_Config.SBEmul = FALSE;
  938. }
  939. else
  940. {
  941. SOUNDSCAPE_Config.SBEmul = TRUE;
  942. }
  943. // do a hardware test
  944. outp( SOUNDSCAPE_Config.BasePort + GA_REGADDR, 0x00f5 );
  945. tmp = inp( SOUNDSCAPE_Config.BasePort + GA_REGADDR );
  946. if ( ( tmp & 0x000f ) != 0x0005 )
  947. {
  948. fclose( fp );
  949. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
  950. return( SOUNDSCAPE_Error );
  951. }
  952. if( ( tmp & 0x00f0 ) == 0x00f0 )
  953. {
  954. fclose( fp );
  955. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_HardwareError );
  956. return( SOUNDSCAPE_Error );
  957. }
  958. // formulate the chip ID
  959. tmp >>= 4;
  960. if( tmp == 0 )
  961. {
  962. SOUNDSCAPE_Config.ChipID = ODIE;
  963. }
  964. else if ( !( tmp & 0x0008 ) )
  965. {
  966. SOUNDSCAPE_Config.ChipID = OPUS;
  967. }
  968. else
  969. {
  970. SOUNDSCAPE_Config.ChipID = MMIC;
  971. }
  972. // parse for the AD-1848 address if necessary
  973. if( SOUNDSCAPE_Config.ChipID == ODIE )
  974. {
  975. found = parse( str, "WavePort", fp );
  976. if ( !found )
  977. {
  978. fclose( fp );
  979. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_MissingWavePortInfo );
  980. return( SOUNDSCAPE_Error );
  981. }
  982. SOUNDSCAPE_Config.WavePort = strtol( str, ( char ** )0, 16 );
  983. }
  984. else
  985. {
  986. // otherwise, the base address is fixed
  987. SOUNDSCAPE_Config.WavePort = SOUNDSCAPE_Config.BasePort + AD_OFFSET;
  988. }
  989. // we're done with the file
  990. fclose( fp );
  991. // if it's an ODIE board, note CD-ROM decode enable
  992. if ( SOUNDSCAPE_Config.ChipID == ODIE )
  993. {
  994. SOUNDSCAPE_Config.CDROM = ga_read( GA_CDCFG ) & 0x80;
  995. }
  996. // build the Wave IRQ index value
  997. if( !SOUNDSCAPE_Config.OldIRQs )
  998. {
  999. switch( SOUNDSCAPE_Config.WaveIRQ )
  1000. {
  1001. case 9 :
  1002. SOUNDSCAPE_Config.IRQIndx = 0;
  1003. break;
  1004. case 5 :
  1005. SOUNDSCAPE_Config.IRQIndx = 1;
  1006. break;
  1007. case 7 :
  1008. SOUNDSCAPE_Config.IRQIndx = 2;
  1009. break;
  1010. default :
  1011. SOUNDSCAPE_Config.IRQIndx = 3;
  1012. break;
  1013. }
  1014. }
  1015. else
  1016. {
  1017. switch( SOUNDSCAPE_Config.WaveIRQ )
  1018. {
  1019. case 9 :
  1020. SOUNDSCAPE_Config.IRQIndx = 0;
  1021. break;
  1022. case 5 :
  1023. SOUNDSCAPE_Config.IRQIndx = 2;
  1024. break;
  1025. case 7 :
  1026. SOUNDSCAPE_Config.IRQIndx = 1;
  1027. break;
  1028. default :
  1029. SOUNDSCAPE_Config.IRQIndx = 3;
  1030. break;
  1031. }
  1032. }
  1033. SOUNDSCAPE_FoundCard = TRUE;
  1034. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
  1035. return( SOUNDSCAPE_Ok );
  1036. }
  1037. /*---------------------------------------------------------------------
  1038. Function: SOUNDSCAPE_Setup
  1039. Setup the Soundscape card for native mode PCM.
  1040. ---------------------------------------------------------------------*/
  1041. static int SOUNDSCAPE_Setup
  1042. (
  1043. void
  1044. )
  1045. {
  1046. int tmp;
  1047. int Interrupt;
  1048. int status;
  1049. // if necessary, clear any pending SB ints
  1050. if ( SOUNDSCAPE_Config.SBEmul )
  1051. {
  1052. inp( SB_IACK );
  1053. }
  1054. SOUNDSCAPE_DisableInterrupt();
  1055. // make sure the AD-1848 is not running
  1056. if ( ad_read( AD_CONFIG ) & 0x01 )
  1057. {
  1058. SOUNDSCAPE_StopPlayback();
  1059. }
  1060. // if necessary, do some signal re-routing
  1061. if( SOUNDSCAPE_Config.ChipID != MMIC )
  1062. {
  1063. // get the gate-array off of the DMA channel
  1064. ga_write( GA_DMACHB, 0x20 );
  1065. if ( !SOUNDSCAPE_Config.OldIRQs )
  1066. {
  1067. switch( SOUNDSCAPE_Config.MIDIIRQ )
  1068. {
  1069. case 5 :
  1070. tmp = 1;
  1071. break;
  1072. case 7 :
  1073. tmp = 2;
  1074. break;
  1075. case 9 :
  1076. tmp = 0;
  1077. break;
  1078. default :
  1079. tmp = 3;
  1080. break;
  1081. }
  1082. }
  1083. else
  1084. {
  1085. switch( SOUNDSCAPE_Config.MIDIIRQ )
  1086. {
  1087. case 5 :
  1088. tmp = 2;
  1089. break;
  1090. case 7 :
  1091. tmp = 1;
  1092. break;
  1093. case 9 :
  1094. tmp = 0;
  1095. break;
  1096. default :
  1097. tmp = 3;
  1098. break;
  1099. }
  1100. }
  1101. // set HostIRQ to MIDIIRQ for now
  1102. ga_write( GA_INTCFG, 0xf0 | ( tmp << 2 ) | tmp );
  1103. // now, route the AD-1848 stuff ...
  1104. if ( SOUNDSCAPE_Config.ChipID == OPUS )
  1105. {
  1106. // set the AD-1848 chip decode
  1107. ga_write( GA_HMCTL, ( ga_read( GA_HMCTL ) & 0xcf ) | 0x10 );
  1108. }
  1109. // setup the DMA polarity
  1110. ga_write( GA_DMACFG, 0x50 );
  1111. // init the CD-ROM (AD-1848) config register
  1112. ga_write( GA_CDCFG, 0x89 | ( SOUNDSCAPE_Config.DMAChan << 4 ) | ( SOUNDSCAPE_Config.IRQIndx << 1 ) );
  1113. // enable mode change, point to config reg
  1114. outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x40 | AD_CONFIG );
  1115. // set interf cnfg reg for DMA mode, single chan, autocal on
  1116. outp( SOUNDSCAPE_Config.WavePort + AD_REGDATA, 0x0c );
  1117. // exit mode change state
  1118. outp( SOUNDSCAPE_Config.WavePort + AD_REGADDR, 0x00 );
  1119. // delay for autocalibration
  1120. tdelay();
  1121. }
  1122. // Install our interrupt handler
  1123. Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
  1124. SOUNDSCAPE_OldInt = _dos_getvect( Interrupt );
  1125. if ( SOUNDSCAPE_Config.WaveIRQ < 8 )
  1126. {
  1127. _dos_setvect( Interrupt, SOUNDSCAPE_ServiceInterrupt );
  1128. }
  1129. else
  1130. {
  1131. status = IRQ_SetVector( Interrupt, SOUNDSCAPE_ServiceInterrupt );
  1132. if ( status != IRQ_Ok )
  1133. {
  1134. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_UnableToSetIrq );
  1135. return( SOUNDSCAPE_Error );
  1136. }
  1137. }
  1138. // max left and right volumes
  1139. ad_write( AD_LEFTOUT, 0 );
  1140. ad_write( AD_RIGHTOUT, 0 );
  1141. // clear any pending interrupt condition
  1142. outp( SOUNDSCAPE_Config.WavePort + AD_STATUS, 0x00 );
  1143. // enable the interrupt pin
  1144. ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) | 0x02 );
  1145. SOUNDSCAPE_EnableInterrupt();
  1146. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
  1147. return( SOUNDSCAPE_Ok );
  1148. }
  1149. /*---------------------------------------------------------------------
  1150. Function: SOUNDSCAPE_GetMIDIPort
  1151. Gets the address of the SoundScape MIDI port.
  1152. ---------------------------------------------------------------------*/
  1153. int SOUNDSCAPE_GetMIDIPort
  1154. (
  1155. void
  1156. )
  1157. {
  1158. int status;
  1159. status = SOUNDSCAPE_FindCard();
  1160. if ( status != SOUNDSCAPE_Ok )
  1161. {
  1162. return( status );
  1163. }
  1164. return( SOUNDSCAPE_Config.BasePort );
  1165. }
  1166. /*---------------------------------------------------------------------
  1167. Function: SOUNDSCAPE_Init
  1168. Initializes the sound card and prepares the module to play
  1169. digitized sounds.
  1170. ---------------------------------------------------------------------*/
  1171. int SOUNDSCAPE_Init
  1172. (
  1173. void
  1174. )
  1175. {
  1176. int status;
  1177. if ( SOUNDSCAPE_Installed )
  1178. {
  1179. SOUNDSCAPE_Shutdown();
  1180. }
  1181. // Save the interrupt masks
  1182. SOUNDSCAPE_IntController1Mask = inp( 0x21 );
  1183. SOUNDSCAPE_IntController2Mask = inp( 0xA1 );
  1184. SOUNDSCAPE_SoundPlaying = FALSE;
  1185. SOUNDSCAPE_SetCallBack( NULL );
  1186. SOUNDSCAPE_DMABuffer = NULL;
  1187. status = SOUNDSCAPE_FindCard();
  1188. if ( status != SOUNDSCAPE_Ok )
  1189. {
  1190. return( status );
  1191. }
  1192. status = SOUNDSCAPE_LockMemory();
  1193. if ( status != SOUNDSCAPE_Ok )
  1194. {
  1195. SOUNDSCAPE_UnlockMemory();
  1196. return( status );
  1197. }
  1198. StackSelector = allocateTimerStack( kStackSize );
  1199. if ( StackSelector == NULL )
  1200. {
  1201. SOUNDSCAPE_UnlockMemory();
  1202. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_OutOfMemory );
  1203. return( SOUNDSCAPE_Error );
  1204. }
  1205. // Leave a little room at top of stack just for the hell of it...
  1206. StackPointer = kStackSize - sizeof( long );
  1207. SOUNDSCAPE_Installed = TRUE;
  1208. status = SOUNDSCAPE_Setup();
  1209. if ( status != SOUNDSCAPE_Ok )
  1210. {
  1211. SOUNDSCAPE_Shutdown();
  1212. return( status );
  1213. }
  1214. // printf("Testing DMA and IRQ ...\n");
  1215. // if( test_dma_irq() )
  1216. // {
  1217. // printf("\t\007Hardware Not Responding\n\n");
  1218. // close_soundscape();
  1219. // return( SOUNDSCAPE_Error );
  1220. // }
  1221. SOUNDSCAPE_SetPlaybackRate( SOUNDSCAPE_DefaultSampleRate );
  1222. SOUNDSCAPE_SetMixMode( SOUNDSCAPE_DefaultMixMode );
  1223. SOUNDSCAPE_SetErrorCode( SOUNDSCAPE_Ok );
  1224. return( SOUNDSCAPE_Ok );
  1225. }
  1226. /*---------------------------------------------------------------------
  1227. Function: SOUNDSCAPE_Shutdown
  1228. Ends transfer of sound data to the sound card and restores the
  1229. system resources used by the card.
  1230. ---------------------------------------------------------------------*/
  1231. void SOUNDSCAPE_Shutdown
  1232. (
  1233. void
  1234. )
  1235. {
  1236. int Interrupt;
  1237. // Halt the DMA transfer
  1238. SOUNDSCAPE_StopPlayback();
  1239. // disable the AD-1848 interrupt pin
  1240. ad_write( AD_PINCTRL, ad_read( AD_PINCTRL ) & 0xfd );
  1241. // if necessary, do some signal re-routing
  1242. if ( SOUNDSCAPE_Config.ChipID != MMIC )
  1243. {
  1244. // re-init the CD-ROM (AD-1848) config register as needed.
  1245. // this will disable the AD-1848 interface.
  1246. if ( SOUNDSCAPE_Config.ChipID == ODIE )
  1247. {
  1248. ga_write( GA_CDCFG, SOUNDSCAPE_Config.CDROM );
  1249. }
  1250. else
  1251. {
  1252. ga_write( GA_CDCFG, ga_read( GA_CDCFG ) & 0x7f);
  1253. }
  1254. // if necessary, reset the SoundBlaster IRQ
  1255. if ( SOUNDSCAPE_Config.SBEmul )
  1256. {
  1257. ga_write( GA_INTCFG, ( ga_read( GA_INTCFG ) & 0xf3 ) |
  1258. ( SOUNDSCAPE_Config.IRQIndx << 2 ) );
  1259. }
  1260. // re-assign the gate-array DMA channel
  1261. ga_write( GA_DMACHB, 0x80 | ( SOUNDSCAPE_Config.DMAChan << 4 ) );
  1262. }
  1263. // Restore the original interrupt
  1264. Interrupt = SOUNDSCAPE_Interrupts[ SOUNDSCAPE_Config.WaveIRQ ];
  1265. if ( SOUNDSCAPE_Config.WaveIRQ >= 8 )
  1266. {
  1267. IRQ_RestoreVector( Interrupt );
  1268. }
  1269. _dos_setvect( Interrupt, SOUNDSCAPE_OldInt );
  1270. SOUNDSCAPE_SoundPlaying = FALSE;
  1271. SOUNDSCAPE_DMABuffer = NULL;
  1272. SOUNDSCAPE_SetCallBack( NULL );
  1273. SOUNDSCAPE_UnlockMemory();
  1274. if ( StackSelector != NULL )
  1275. {
  1276. deallocateTimerStack( StackSelector );
  1277. StackSelector = NULL;
  1278. }
  1279. SOUNDSCAPE_Installed = FALSE;
  1280. }