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

  1. /*
  2.      AHI - Hardware independent audio subsystem
  3.      Copyright (C) 1996-1999 Martin Blom <martin@blom.org>
  4.      
  5.      This library is free software; you can redistribute it and/or
  6.      modify it under the terms of the GNU Library General Public
  7.      License as published by the Free Software Foundation; either
  8.      version 2 of the License, or (at your option) any later version.
  9.      
  10.      This library is distributed in the hope that it will be useful,
  11.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.      Library General Public License for more details.
  14.      
  15.      You should have received a copy of the GNU Library General Public
  16.      License along with this library; if not, write to the
  17.      Free Software Foundation, Inc., 59 Temple Place - Suite 330, Cambridge,
  18.      MA 02139, USA.
  19. */
  20.  
  21. #if defined( VERSIONPPC )
  22.  
  23. #include <config.h>
  24. #include <CompilerSpecific.h>
  25.  
  26. #include <exec/types.h>
  27. #include <hardware/intbits.h>
  28. #include <powerup/ppclib/tasks.h>
  29. #include <powerpc/powerpc.h>
  30.  
  31. #include "version.h"
  32. #include "ahi_def.h"
  33. #include "mixer.h"
  34. #include "ppcheader.h"
  35.  
  36. /******************************************************************************
  37. ** Prototypes *****************************************************************
  38. ******************************************************************************/
  39.  
  40. void
  41. FlushCache( void* address, unsigned long length );
  42.  
  43. void
  44. FlushCacheAll( void  );
  45.  
  46. void
  47. InvalidateCache( void* address, unsigned long length );
  48.  
  49. void WarpUpInt( void );
  50.  
  51. /******************************************************************************
  52. ** First address **************************************************************
  53. ******************************************************************************/
  54.  
  55. // This must be the first code in the ELF object due to a bug in
  56. // ppc.library < 46.26
  57.  
  58. asm("
  59.         .text
  60.  
  61.         .align  2
  62.         .globl  KernelObject
  63.           .type   KernelObject,@function
  64.  
  65.  
  66. KernelObject:
  67.         stwu    1,-24(1)
  68.         mflr    0
  69.         stw     0,28(1)
  70.         stw     11,8(1)
  71.         stw     12,12(1)
  72.         stw     13,16(1)
  73.  
  74.         bl      CallMixroutine
  75.  
  76.         lwz     11,8(1)
  77.         lwz     12,12(1)
  78.         lwz     13,16(1)
  79.         lwz     0,28(1)
  80.         mtlr    0
  81.         addi    1,1,24
  82.         blr
  83.  
  84. ");
  85.  
  86.  
  87. /******************************************************************************
  88. ** Function used to call the actual mixing routine ****************************
  89. ******************************************************************************/
  90.  
  91. int
  92. CallMixroutine( unsigned int             magic,
  93.                 struct Hook*             Hook, 
  94.                 void*                    dst, 
  95.                 struct AHIPrivAudioCtrl* audioctrl,
  96.                 int                      flush_result )
  97. {
  98.   struct AHISoundData *sd;
  99.   int                  i;
  100.  
  101.   if( magic != 0xC0DECAFE )
  102.   {
  103.     // If the magic cookie was not correct, return error.
  104.  
  105.     return 20; // RETURN_FAIL
  106.   }
  107.  
  108.  
  109.   // Wait for start signal...
  110.  
  111.   while( audioctrl->ahiac_PPCCommand != AHIAC_COM_START );
  112.  
  113.  
  114.   // Start m68k interrupt handler
  115.  
  116.   audioctrl->ahiac_PPCCommand = AHIAC_COM_INIT;
  117.   *((WORD*) 0xdff09C)  = INTF_SETCLR | INTF_PORTS;
  118.  
  119.   // Invalidate dynamic sample sounds (which is faster than flushing).
  120.   // Currently, the PPC is assumed not to modify dynamic samples.
  121.   // It makes sense as long as no PPC hooks can be called from AHI.
  122.   // Anyway, each dynamic sample is flushed on the m68k side before
  123.   // this routine is called, and invalidated here on the PPC side.
  124.   // However, should a dynamic sample start at address 0, which
  125.   // probably means that the whole address space is used for that
  126.   // sample, all of the data caches are instead flushed.
  127.  
  128.   sd = audioctrl->ahiac_SoundDatas;
  129.  
  130.   for( i = 0; i < audioctrl->ac.ahiac_Sounds; i++)
  131.   {
  132.     if( sd->sd_Type == AHIST_DYNAMICSAMPLE )
  133.     {
  134.       if( sd->sd_Addr == NULL )
  135.       {
  136.         // *Flush* all and exit (add an L2 cache and watch this code break!)
  137.  
  138.         FlushCacheAll();
  139.         break;
  140.       }
  141.       else
  142.       {
  143.         // *Invalidate* block
  144.  
  145.         InvalidateCache( sd->sd_Addr,
  146.                          sd->sd_Length * InternalSampleFrameSize( sd->sd_Type ) );
  147.       }
  148.     }
  149.     sd++;
  150.   }
  151.  
  152.   // Wait for m68k interrupt handler to go active
  153.  
  154.   while( audioctrl->ahiac_PPCCommand != AHIAC_COM_ACK );
  155.  
  156.   // Mix
  157.  
  158.   MixGeneric( Hook, dst, audioctrl );
  159.  
  160.   // Flush mixed samples to memory (PowerUp only!)
  161.  
  162.   if( flush_result )
  163.   {
  164.     FlushCache( dst, audioctrl->ahiac_BuffSizeNow );
  165.   }
  166.  
  167.   // Kill the m68k interrupt handler
  168.  
  169.   audioctrl->ahiac_PPCCommand = AHIAC_COM_QUIT;
  170.   *((WORD*) 0xdff09C)  = INTF_SETCLR | INTF_PORTS;
  171.  
  172.   // Wait for it
  173.  
  174.   while( audioctrl->ahiac_PPCCommand != AHIAC_COM_ACK );
  175.  
  176.   audioctrl->ahiac_PPCCommand = AHIAC_COM_FINISHED;
  177.   return 0;
  178. }
  179.  
  180. /******************************************************************************
  181. ** Cache manipulation routines ************************************************
  182. ******************************************************************************/
  183.  
  184. asm( "
  185.         .text
  186.  
  187. /*     r3 = beginning address of data block to flush
  188.  *     r4 = size of data block to flush (in bytes)
  189.  *     assumes cache block granule is 32 bytes
  190.  */
  191.  
  192.         .align  2
  193.         .globl  FlushCache
  194.           .type   FlushCache,@function
  195.  
  196. FlushCache:
  197.         addi    4,4,31
  198.         srwi    4,4,5           /* convert to cache blocks to flush */
  199.         mtctr   4
  200.         li      4,0
  201. 1:
  202.         dcbf    3,4             /* flush data cache block to mem */
  203.         addi    4,4,32
  204.         bdnz    1b
  205.  
  206.         sync                    /* force mem transactions to complete */
  207.         blr                     /* return to calling routine */
  208.  
  209.  
  210.         .align  2
  211.         .globl  FlushCacheAll
  212.           .type   FlushCacheAll,@function
  213.  
  214. FlushCacheAll:
  215.  
  216. /* Load the entire data cache with known contents. */
  217.         li      3,-16           /* Start at address 0 */
  218.         li      4,2*256         /* 2 ways, 256 sets per way */
  219.         mtctr   4               /* (use CTR register to save an instruction) */
  220. 1:
  221.         lwzu    5,16(3)         /* load a cache line if it's not already present */
  222.         bdnz    1b
  223.  
  224. /* Flush those known contents from the cache. */
  225.         li      3,0             /* Read 2*128*16 bytes at address 0 */
  226.         mtctr   4               /* (use CTR register to save an instruction) */
  227. 2:
  228.         dcbf    0,3             /* flush a cache line */
  229.         addi    3,3,16          /* next line: assumes cache lines are 16 bytes */
  230.         bdnz    2b
  231.         sync
  232.         blr
  233.  
  234.  
  235. /*     r3 = beginning address of data block to flush
  236.  *     r4 = size of data block to flush (in bytes)
  237.  *     assumes cache block granule is 32 bytes
  238.  */
  239.         .align  2
  240.         .globl  InvalidateCache
  241.           .type   InvalidateCache,@function
  242.  
  243. InvalidateCache:
  244.         addi    4,4,31
  245.         srwi    4,4,5           /* convert to cache blocks to invalidate */
  246.         mtctr   4
  247.         li      4,0
  248. 1:
  249.         dcbi    3,4             /* invalidate data cache block */
  250.         addi    4,4,32
  251.         bdnz    1b
  252.  
  253.         sync                    /* force mem transactions to complete */
  254.         blr                     /* return to calling routine */
  255.  
  256. ");
  257.  
  258.  
  259. /******************************************************************************
  260. ** WarpUp stuff ***************************************************************
  261. ******************************************************************************/
  262.  
  263. static void* blinkbase = (void*) 0xbfe001;
  264. static ULONG magic     = 0xC0DECAFE;
  265.  
  266. static char IntName[] = "AHI/WarpUp Exception Handler";
  267.  
  268. struct TagItem InitTags[] =
  269. {
  270.   { EXCATTR_CODE,  (ULONG) &WarpUpInt,                },
  271.   { EXCATTR_DATA,  0,                                 },
  272.   { EXCATTR_NAME,  (ULONG) &IntName,                  },
  273.   { EXCATTR_PRI,   32,                                },
  274.   { EXCATTR_EXCID, EXCF_INTERRUPT,                    },
  275.   { EXCATTR_FLAGS, EXCF_GLOBAL | EXCF_LARGECONTEXT,   },
  276.   { TAG_DONE,      0                                  }
  277. };
  278.  
  279. asm( "
  280.           .text
  281.  
  282. _LVOSetExcHandler = -516
  283. _LVORemExcHandler = -522
  284. _LVOSetExcMMU     = -576
  285. _LVOClearExcMMU   = -582
  286.  
  287. EXCRETURN_ABORT   = 1
  288.  
  289. # struct WarpUpContext
  290.  
  291. wc_Active        = 0
  292. wc_AudioCtrl     = 4
  293. wc_PowerPCBase   = 8
  294. wc_XLock         = 12
  295. wc_Hook          = 16
  296. wc_Dst           = 20
  297. "
  298. #ifndef WARPUP_INVALIDATE_CACHE
  299. "
  300. wc_MixBuffer     = 24;
  301. wc_MixLongWords  = 28;
  302. "
  303. #endif
  304. "
  305. /* InitWarpUp ****************************************************************/
  306.  
  307.         .align  2
  308.         .globl  InitWarpUp
  309.         .type   InitWarpUp,@function
  310.  
  311. /*     r3 = struct WarpUpContext*
  312.  */
  313.  
  314. InitWarpUp:
  315.         mflr    0
  316.         stw     0,8(1)
  317.         mfcr    0
  318.         stw     0,4(1)
  319.         stw     13,-4(1)
  320.         subi    13,1,4
  321.         stwu    1,-(28+14*4+1*4)(1)
  322.  
  323.         stw     14,-4(13)
  324.  
  325.         mr      14,3                        # Save WarpUpContext in r14
  326.  
  327. # Build the tag list on the stack
  328.  
  329.         lis     4,(InitTags-4)@ha
  330.         addi    4,4,InitTags-4@l
  331.  
  332.         addi    5,1,28-4
  333.  
  334. 1:
  335.         lwzu    6,4(4)
  336.         stwu    6,4(5)
  337.         cmpwi   0,6,0
  338.         lwzu    6,4(4)
  339.         stwu    6,4(5)
  340.         bne     1b
  341.  
  342.         stw     14,28+3*4(1)                # Store WarpUpContext in tag list
  343.  
  344. # Register the exception handler
  345.  
  346.         lwz     3,wc_PowerPCBase(14)
  347.         addi    4,1,28
  348.         lwz     0,_LVOSetExcHandler+2(3)
  349.         mtlr    0
  350.         blrl
  351.  
  352.         stw     3,wc_XLock(14)
  353.  
  354.         lwz     14,-4(13)
  355.  
  356.         lwz     1,0(1)
  357.         lwz     13,-4(1)
  358.         lwz     0,4(1)
  359.         mtcr    0
  360.         lwz     0,8(1)
  361.         mtlr    0
  362.         blr
  363.  
  364.  
  365. /* WarpUpInt *****************************************************************/
  366.  
  367.         .align  2
  368.         .globl  WarpUpInt
  369.         .type   WarpUpInt,@function
  370.  
  371. WarpUpInt:
  372.         mflr    0
  373.         stw     0,8(1)
  374.         mfcr    0
  375.         stw     0,4(1)
  376.         stw     13,-4(1)
  377.         subi    13,1,4
  378.         stwu    1,-(28+1*4)(1)
  379.  
  380.         stw     14,-4(13)
  381.  
  382.         mr      14,2
  383.  
  384. # Set up MMU
  385.  
  386.         lwz     3,wc_PowerPCBase(14)
  387.         lwz     0,_LVOSetExcMMU+2(3)
  388.         mtlr    0
  389.         blrl
  390.  
  391. # Test and clear activation flag (is this out interrupt or somebody elses?)
  392.  
  393.         addi    3,14,wc_Active
  394.         li      4,0
  395. 1:
  396.         lwarx   5,0,3
  397.         stwcx.  4,0,3
  398.         bne-    1b
  399.  
  400.         cmpwi   0,5,0
  401.         beq     2f
  402.  
  403. # Call the CallMixroutine (V.4 ABI)
  404.  
  405.         stwu    1,-16(1)
  406.         stw     2,8(1)
  407.         stw     13,12(1)
  408.  
  409.         lis     3,magic@ha
  410.         addi    3,3,magic@l
  411.         lwz     3,0(3)
  412.         lwz     4,wc_Hook(14)
  413.         lwz     6,wc_AudioCtrl(14)
  414. "
  415. #ifdef WARPUP_INVALIDATE_CACHE
  416. "
  417.         lwz     5,wc_Dst(14)
  418.         li      7,1                          # Do flush the buffer!
  419. "
  420. #else
  421. "
  422.         lwz     5,wc_MixBuffer(14)
  423.         li      7,0                          # No need to flush the buffer!
  424. "
  425. #endif
  426. "
  427.         bl      CallMixroutine
  428.  
  429.         lwz     2,8(1)
  430.         lwz     13,12(1)
  431.         addi    1,1,16
  432. "
  433. #ifndef WARPUP_INVALIDATE_CACHE
  434.  
  435. "
  436. # Copy the cachable mixing buffer to the non-cachable (so the m68k can read it)
  437.  
  438.         lwz     3,wc_MixBuffer(14)
  439.         lwz     4,wc_Dst(14)
  440.         subi    3,3,4
  441.         subi    4,4,4
  442.         lwz     5,wc_MixLongWords(14)
  443.         mtctr   5
  444. 3:
  445.         lwzu    5,4(3)
  446.         stwu    5,4(4)
  447.         bdnz    3b
  448. "
  449. #endif
  450. "        
  451. 2:
  452.  
  453. # Restore MMU
  454.  
  455.         lwz     3,wc_PowerPCBase(14)
  456.         lwz     0,_LVOClearExcMMU+2(3)
  457.         mtlr    0
  458.         blrl
  459.  
  460.         li      3,EXCRETURN_ABORT
  461.  
  462.         lwz     14,-4(13)
  463.  
  464.         lwz     1,0(1)
  465.         lwz     13,-4(1)
  466.         lwz     0,4(1)
  467.         mtcr    0
  468.         lwz     0,8(1)
  469.         mtlr    0
  470.         blr
  471.  
  472. /* CleanUpWarpUp *************************************************************/
  473.  
  474.         .align  2
  475.         .globl  CleanUpWarpUp
  476.         .type   CleanUpWarpUp,@function
  477.  
  478. /*     r3 = struct WarpUpContext*
  479.  */
  480.  
  481. CleanUpWarpUp:
  482.         mflr    0
  483.         stw     0,8(1)
  484.         mfcr    0
  485.         stw     0,4(1)
  486.         stw     13,-4(1)
  487.         subi    13,1,4
  488.         stwu    1,-28(1)
  489.  
  490. # Unregister the exception handler
  491.  
  492.         lwz     4,wc_XLock(3)
  493.         lwz     3,wc_PowerPCBase(3)
  494.         lwz     0,_LVORemExcHandler+2(3)
  495.         mtlr    0
  496.         blrl
  497.  
  498.         lwz     1,0(1)
  499.         lwz     13,-4(1)
  500.         lwz     0,4(1)
  501.         mtcr    0
  502.         lwz     0,8(1)
  503.         mtlr    0
  504.         blr
  505. ");
  506.  
  507.  
  508. /******************************************************************************
  509. ** Library & Linking **********************************************************
  510. ******************************************************************************/
  511.  
  512. // Just some library stuff... All the stuff will have to be added 
  513. // in the final release. TODO!
  514.  
  515. ULONG    __LIB_Version  = VERSION;
  516. ULONG    __LIB_Revision = REVISION;
  517.  
  518. static const char VersTag[] = 
  519.  "$VER: ahi.elf " VERS " ©1994-1999 Martin Blom. " CPU " version.\r\n";
  520.  
  521.  
  522. // Make sure all add-routines are fetched.
  523.  
  524. static void* a1 = AddByteMono;
  525. static void* a2 = AddLofiByteMono;
  526.  
  527. #endif /* defined( VERSIONPPC ) */
  528.