home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / ahisrc / device / header.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-03  |  13.0 KB  |  534 lines

  1. /* $Id: header.c,v 1.20 1999/10/04 00:06:34 lcs Exp $ */
  2.  
  3. /*
  4.      AHI - Hardware independent audio subsystem
  5.      Copyright (C) 1996-1999 Martin Blom <martin@blom.org>
  6.      
  7.      This library is free software; you can redistribute it and/or
  8.      modify it under the terms of the GNU Library General Public
  9.      License as published by the Free Software Foundation; either
  10.      version 2 of the License, or (at your option) any later version.
  11.      
  12.      This library is distributed in the hope that it will be useful,
  13.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.      Library General Public License for more details.
  16.      
  17.      You should have received a copy of the GNU Library General Public
  18.      License along with this library; if not, write to the
  19.      Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
  20.      MA 02139, USA.
  21. */
  22.  
  23. #include <config.h>
  24. #include <CompilerSpecific.h>
  25.  
  26. #include <exec/resident.h>
  27. #include <exec/alerts.h>
  28. #include <exec/execbase.h>
  29. #include <proto/exec.h>
  30. #include <proto/dos.h>
  31.  
  32. #include <powerup/ppclib/object.h>
  33. #include <powerup/ppclib/interface.h>
  34. #include <proto/ppc.h>
  35.  
  36. #include "ahi_def.h"
  37. #include "header.h"
  38. #include "device.h"
  39. #include "localize.h"
  40. #include "misc.h"
  41.  
  42. #include "version.h"
  43.  
  44. static BOOL
  45. OpenLibs ( void );
  46.  
  47. static void
  48. CloseLibs ( void );
  49.  
  50.  
  51. /******************************************************************************
  52. ** Device entry ***************************************************************
  53. ******************************************************************************/
  54.  
  55. int Start( void )
  56. {
  57.   return -1;
  58. }
  59.  
  60.  
  61. /******************************************************************************
  62. ** Device residend strcuture **************************************************
  63. ******************************************************************************/
  64.  
  65. extern void _etext;
  66. extern const char DevName[];
  67. extern const char IDString[];
  68. static const APTR InitTable[4];
  69.  
  70. static const struct Resident RomTag =
  71. {
  72.   RTC_MATCHWORD,
  73.   (struct Resident *) &RomTag,
  74.   (APTR) &_etext,
  75.   RTF_AUTOINIT,
  76.   VERSION,
  77.   NT_DEVICE,
  78.   0,                      /* priority */
  79.   (BYTE *) DevName,
  80.   (BYTE *) IDString,
  81.   (APTR) &InitTable
  82. };
  83.  
  84.  
  85. /******************************************************************************
  86. ** Globals ********************************************************************
  87. ******************************************************************************/
  88.  
  89. struct ExecBase           *SysBase        = NULL;
  90. struct AHIBase            *AHIBase        = NULL;
  91. struct DosLibrary         *DOSBase        = NULL;
  92. struct Library            *GadToolsBase   = NULL;
  93. struct GfxBase            *GfxBase        = NULL;
  94. struct Library            *IFFParseBase   = NULL;
  95. struct IntuitionBase      *IntuitionBase  = NULL;
  96. struct LocaleBase         *LocaleBase     = NULL;
  97. struct Device             *TimerBase      = NULL;
  98. struct UtilityBase        *UtilityBase    = NULL;
  99. struct Library            *PowerPCBase    = NULL;
  100. struct Library            *PPCLibBase     = NULL;
  101. void                      *PPCObject      = NULL;
  102.  
  103. /* linker can use symbol b for symbol a if a is not defined */
  104. #define ALIAS(a,b) asm(".stabs \"_" #a "\",11,0,0,0\n.stabs \"_" #b "\",1,0,0,0")
  105.  
  106. ALIAS( __UtilityBase, UtilityBase );
  107.  
  108. const ULONG                       DriverVersion  = 2;
  109. const ULONG                       Version        = VERSION;
  110. const ULONG                       Revision       = REVISION;
  111.  
  112. const char DevName[]   = AHINAME;
  113. const char IDString[]  = AHINAME " " VERS "\r\n";
  114.  
  115. static const char VersTag[] =
  116.  "$VER: " AHINAME " " VERS " ©1994-1999 Martin Blom. "
  117.  CPU 
  118.  "/PPC"
  119.  " version.\r\n";
  120.  
  121. enum MixBackend_t          MixBackend     = MB_NATIVE;
  122.  
  123. /******************************************************************************
  124. ** Device code ****************************************************************
  125. ******************************************************************************/
  126.  
  127. static struct AHIBase * ASMCALL
  128. initRoutine( REG( d0, struct AHIBase* device ),
  129.          REG( a0, APTR seglist ),
  130.          REG( a6, struct ExecBase* sysbase ) )
  131. {
  132.   SysBase = sysbase;
  133.   AHIBase = device;
  134.  
  135.   AHIBase->ahib_Library.lib_Node.ln_Type = NT_DEVICE;
  136.   AHIBase->ahib_Library.lib_Node.ln_Name = (STRPTR) DevName;
  137.   AHIBase->ahib_Library.lib_Flags        = LIBF_SUMUSED | LIBF_CHANGED;
  138.   AHIBase->ahib_Library.lib_Version      = VERSION;
  139.   AHIBase->ahib_Library.lib_Revision     = REVISION;
  140.   AHIBase->ahib_Library.lib_IdString     = (STRPTR) IDString;
  141.   AHIBase->ahib_SysLib  = sysbase;
  142.   AHIBase->ahib_SegList = (ULONG) seglist;
  143.  
  144. #ifdef MC68020_PLUS
  145.   if( ( SysBase->AttnFlags & AFF_68020 ) == 0 )
  146.   {
  147.     Alert( ( AN_Unknown | ACPU_InstErr ) & (~AT_DeadEnd) );
  148.     return NULL;
  149.   }
  150. #endif
  151.  
  152.   InitSemaphore( &AHIBase->ahib_Lock );
  153.  
  154.   if( !OpenLibs() )
  155.   {
  156.     return NULL;
  157.   }
  158.  
  159.   return AHIBase;
  160. }
  161.  
  162.  
  163. BPTR ASMCALL
  164. DevExpunge( REG( a6, struct AHIBase* device ) )
  165. {
  166.   BPTR seglist = 0;
  167.  
  168.   device->ahib_Library.lib_Flags |= LIBF_DELEXP;
  169.  
  170.   if( device->ahib_Library.lib_OpenCnt == 0)
  171.   {
  172.     seglist = device->ahib_SegList;
  173.  
  174.     Remove( (struct Node *) device );
  175.  
  176.     CloseLibs();
  177.  
  178.     FreeMem( (APTR) ( ( (char*) device ) - device->ahib_Library.lib_NegSize ),
  179.          device->ahib_Library.lib_NegSize + device->ahib_Library.lib_PosSize );
  180.   }
  181.  
  182.   return seglist;
  183. }
  184.  
  185.  
  186. int Null( void )
  187. {
  188.   return 0;
  189. }
  190.  
  191.  
  192. extern APTR DevOpen;
  193. extern APTR DevClose;
  194.  
  195. extern APTR DevBeginIO;
  196. extern APTR DevAbortIO;
  197.  
  198. extern APTR AllocAudioA;
  199. extern APTR FreeAudio;
  200. extern APTR KillAudio;
  201. extern APTR ControlAudioA;
  202. extern APTR SetVol;
  203. extern APTR SetFreq;
  204. extern APTR SetSound;
  205. extern APTR SetEffect;
  206. extern APTR LoadSound;
  207. extern APTR UnloadSound;
  208. extern APTR NextAudioID;
  209. extern APTR GetAudioAttrsA;
  210. extern APTR BestAudioIDA;
  211. extern APTR AllocAudioRequestA;
  212. extern APTR AudioRequestA;
  213. extern APTR FreeAudioRequest;
  214. extern APTR PlayA;
  215. extern APTR SampleFrameSize;
  216. extern APTR AddAudioMode;
  217. extern APTR RemoveAudioMode;
  218. extern APTR LoadModeFile;
  219.  
  220.  
  221. static const APTR funcTable[] =
  222. {
  223.   &DevOpen,
  224.   &DevClose,
  225.   &DevExpunge,
  226.   &Null,
  227.  
  228.   &DevBeginIO,
  229.   &DevAbortIO,
  230.  
  231.   &AllocAudioA,
  232.   &FreeAudio,
  233.   &KillAudio,
  234.   &ControlAudioA,
  235.   &SetVol,
  236.   &SetFreq,
  237.   &SetSound,
  238.   &SetEffect,
  239.   &LoadSound,
  240.   &UnloadSound,
  241.   &NextAudioID,
  242.   &GetAudioAttrsA,
  243.   &BestAudioIDA,
  244.   &AllocAudioRequestA,
  245.   &AudioRequestA,
  246.   &FreeAudioRequest,
  247.   &PlayA,
  248.   &SampleFrameSize,
  249.   &AddAudioMode,
  250.   &RemoveAudioMode,
  251.   &LoadModeFile,
  252.   (APTR) -1
  253. };
  254.  
  255.  
  256. static const APTR InitTable[4] =
  257. {
  258.   (APTR) sizeof( struct AHIBase ),
  259.   (APTR) &funcTable,
  260.   0,
  261.   (APTR) initRoutine
  262. };
  263.  
  264.  
  265. static struct timerequest *TimerIO        = NULL;
  266. static struct timeval     *timeval        = NULL;
  267.  
  268. /******************************************************************************
  269. ** OpenLibs *******************************************************************
  270. ******************************************************************************/
  271.  
  272. // This function is called by the device startup code when the device is
  273. // first loaded into memory.
  274.  
  275. static BOOL
  276. OpenLibs ( void )
  277. {
  278.   /* Intuition Library */
  279.  
  280.   IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", 37 );
  281.  
  282.   if( IntuitionBase == NULL)
  283.   {
  284.     Alert(AN_Unknown|AG_OpenLib|AO_Intuition);
  285.     return FALSE;
  286.   }
  287.  
  288.   /* DOS Library */
  289.  
  290.   DOSBase = (struct DosLibrary *) OpenLibrary( "dos.library", 37 );
  291.  
  292.   if( DOSBase == NULL)
  293.   {
  294.     Req( "Unable to open 'dos.library'." );
  295.     return FALSE;
  296.   }
  297.  
  298.   /* Graphics Library */
  299.  
  300.   GfxBase = (struct GfxBase *) OpenLibrary( "graphics.library", 37 );
  301.  
  302.   if( GfxBase == NULL)
  303.   {
  304.     Req( "Unable to open 'graphics.library'." );
  305.     return FALSE;
  306.   }
  307.  
  308.   /* GadTools Library */
  309.  
  310.   GadToolsBase = OpenLibrary( "gadtools.library", 37 );
  311.  
  312.   if( GadToolsBase == NULL)
  313.   {
  314.     Req( "Unable to open 'gadtools.library'." );
  315.     return FALSE;
  316.   }
  317.  
  318.   /* IFFParse Library */
  319.  
  320.   IFFParseBase = OpenLibrary( "iffparse.library", 37 );
  321.  
  322.   if( IFFParseBase == NULL)
  323.   {
  324.     Req( "Unable to open 'iffparse.library'." );
  325.     return FALSE;
  326.   }
  327.  
  328.   /* Locale Library */
  329.  
  330.   LocaleBase = (struct LocaleBase*) OpenLibrary( "locale.library", 38 );
  331.  
  332.   /* Timer Device */
  333.  
  334.   TimerIO = (struct timerequest *) AllocVec( sizeof(struct timerequest),
  335.                                              MEMF_PUBLIC | MEMF_CLEAR );
  336.  
  337.   if( TimerIO == NULL)
  338.   {
  339.     Req( "Out of memory." );
  340.     return FALSE;
  341.   }
  342.  
  343.   timeval = (struct timeval *) AllocVec( sizeof(struct timeval),
  344.                                          MEMF_PUBLIC | MEMF_CLEAR);
  345.  
  346.   if( timeval == NULL)
  347.   {
  348.     Req( "Out of memory." );
  349.     return FALSE;
  350.   }
  351.  
  352.   if( OpenDevice( "timer.device",
  353.                   UNIT_MICROHZ,
  354.                   (struct IORequest *)
  355.                   TimerIO,
  356.                   0) != 0 )
  357.   {
  358.     Req( "Unable to open 'timer.device'." );
  359.     return FALSE;
  360.   }
  361.  
  362.   TimerBase = (struct Device *) TimerIO->tr_node.io_Device;
  363.  
  364.   /* Utility Library */
  365.  
  366.   UtilityBase = (struct UtilityBase *) OpenLibrary( "utility.library", 37 );
  367.  
  368.   if( UtilityBase == NULL)
  369.   {
  370.     Req( "Unable to open 'utility.library'." );
  371.     return FALSE;
  372.   }
  373.  
  374.   MixBackend = MB_NATIVE;
  375.  
  376.   /* PPC/PowerPC library loading
  377.  
  378.      Strategy:
  379.  
  380.       1) If WarpUp is running, use it.
  381.       2) If WarpUp is is not running, but PowerUp is, use it
  382.       3) If neither of them are running, try WarpUp.
  383.       4) Finally, try PowerUp.
  384.  
  385.      Result:
  386.  
  387.       If both kernels are running, WarpUp will be used, since the PowerUp
  388.       kernel is the ppc.library emulation. (This is going to work until
  389.       somebody writes a WarpUp emulation for ppc.library....)
  390.  
  391.       If only one kernel is already running, it will be used.
  392.  
  393.       WarpUp will be used if no kernel is loaded, and WarpUp exists, since
  394.       WarpUp was selected for OS 3.5.  If WarpUp was not found, PowerUp
  395.       will be used.
  396.  
  397.   */
  398.  
  399.   // Check if WarpUp or PowerUp are already installed...
  400.  
  401.   Forbid();
  402.   PowerPCBase = (struct Library *) FindName( &SysBase->LibList,
  403.                                              "powerpc.library" );
  404.   PPCLibBase  = (struct Library *) FindName( &SysBase->LibList,
  405.                                              "ppc.library" );
  406.   Permit();
  407.  
  408.   if( PowerPCBase != NULL 
  409.       || ( PowerPCBase == NULL && PPCLibBase == NULL ) )
  410.   {
  411.     // Open WarpUp
  412.     PowerPCBase = OpenLibrary( "powerpc.library", 14 );
  413.     PPCLibBase  = NULL;
  414.   }
  415.  
  416.   if( PPCLibBase != NULL 
  417.       || ( PPCLibBase == NULL && PowerPCBase == NULL ) )
  418.   {
  419.     // Open PoweUp
  420.     PPCLibBase  = OpenLibrary( "ppc.library", 46 );
  421.     PowerPCBase = NULL;
  422.   }
  423.  
  424.   if( PPCLibBase != NULL 
  425.       && PPCLibBase->lib_Version == 46 
  426.       && PPCLibBase->lib_Revision < 24 )
  427.   {
  428.     Req( "Need at least version 46.26 of 'ppc.library'." );
  429.     return FALSE;
  430.   }
  431.  
  432.   if( PPCLibBase != NULL )
  433.   {
  434.     MixBackend  = MB_POWERUP;
  435.   }
  436.   
  437.   if( PowerPCBase != NULL )
  438.   {
  439.     MixBackend  = MB_WARPUP;
  440.   }
  441.  
  442.   if( PPCLibBase != NULL || PowerPCBase != NULL )
  443.   {
  444.     ULONG* version = NULL;
  445.     ULONG* revision = NULL;
  446.  
  447.     /* Load our code to PPC..  */
  448.  
  449.     PPCObject = AHILoadObject( "DEVS:ahi.elf" );
  450.  
  451.     if( PPCObject != NULL )
  452.     {
  453.       AHIGetELFSymbol( "__LIB_Version", (void*) &version );
  454.       AHIGetELFSymbol( "__LIB_Revision", (void*) &revision );
  455.     
  456.       if( version == NULL || revision == NULL )
  457.       {
  458.         Req( "Unable to fetch version information from 'ahi.elf'." );
  459.       }
  460.       if( *version != Version || *revision != Revision )
  461.       {
  462.         Req( "'ahi.elf' version %ld.%ld doesn't match 'ahi.device' %ld.%ld.",
  463.              *version, *revision, Version, Revision );
  464.  
  465.         return FALSE;
  466.       }
  467.     }
  468.     else
  469.     {
  470.       // PPC kernel found, but no ELF object. m68k mixing will be used.
  471.     }
  472.   }
  473.  
  474.   OpenahiCatalog(NULL, NULL);
  475.  
  476.   {
  477.     char buf[2];
  478.     
  479.     if( GetVar( "AHINoBetaRequester", buf, sizeof( buf ), 0 ) == -1 )
  480.     {
  481.       Req( "This is a beta release of AHI. The latest supported \n"
  482.            "version is 4.180, which can be found at\n"
  483.            "<URL:http://www.lysator.liu.se/~lcs/ahi.html>.\n"
  484.            "\n"
  485.            "Detailed bug reports and patches are welcome.\n"
  486.            "Sound kernel in use: %s.\n"
  487.            "\n"
  488.            "/Martin Blom <martin@blom.org>\n",
  489.            PPCObject == NULL ? CPU :
  490.              ( PPCLibBase == NULL ? "WarpUp" : "PowerUp" ) );
  491.            
  492.     }
  493.   }
  494.  
  495.   return TRUE;
  496. }
  497.  
  498.  
  499. /******************************************************************************
  500. ** CloseLibs *******************************************************************
  501. ******************************************************************************/
  502.  
  503. // This function is called by DevExpunge() when the device is about to be
  504. // flushed
  505.  
  506. static void
  507. CloseLibs ( void )
  508. {
  509.   CloseahiCatalog();
  510.  
  511.   if( PPCObject != NULL )
  512.   {
  513.     AHIUnloadObject( PPCObject );
  514.   }
  515.  
  516.   CloseLibrary( PPCLibBase );
  517.   CloseLibrary( PowerPCBase );
  518.  
  519.   CloseLibrary( (struct Library *) UtilityBase );
  520.   if( TimerIO  != NULL )
  521.   {
  522.     CloseDevice( (struct IORequest *) TimerIO );
  523.   }
  524.   FreeVec( timeval );
  525.   FreeVec( TimerIO );
  526.   CloseLibrary( (struct Library *) LocaleBase );
  527.   CloseLibrary( (struct Library *) IntuitionBase );
  528.   CloseLibrary( IFFParseBase );
  529.   CloseLibrary( GadToolsBase );
  530.   CloseLibrary( (struct Library *) GfxBase );
  531.   CloseLibrary( (struct Library *) DOSBase );
  532.  
  533. }
  534.