Search
lxdream.org :: lxdream/src/asic.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/asic.c
changeset 56:3224dceaf2a3
prev42:d06affd949ec
next94:8d80d9c7cc7d
author nkeynes
date Mon Jan 16 11:18:29 2006 +0000 (18 years ago)
permissions -rw-r--r--
last change Add 's3m' mode (for testing) and also headless mode
view annotate diff log raw
     1 /**
     2  * $Id: asic.c,v 1.10 2006-01-01 08:09:42 nkeynes Exp $
     3  *
     4  * Support for the miscellaneous ASIC functions (Primarily event multiplexing,
     5  * and DMA). 
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or
    12  * (at your option) any later version.
    13  *
    14  * This program is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU General Public License for more details.
    18  */
    20 #define MODULE asic_module
    22 #include <assert.h>
    23 #include "dream.h"
    24 #include "mem.h"
    25 #include "sh4/intc.h"
    26 #include "sh4/dmac.h"
    27 #include "dreamcast.h"
    28 #include "maple/maple.h"
    29 #include "gdrom/ide.h"
    30 #include "asic.h"
    31 #define MMIO_IMPL
    32 #include "asic.h"
    33 /*
    34  * Open questions:
    35  *   1) Does changing the mask after event occurance result in the
    36  *      interrupt being delivered immediately?
    37  * TODO: Logic diagram of ASIC event/interrupt logic.
    38  *
    39  * ... don't even get me started on the "EXTDMA" page, about which, apparently,
    40  * practically nothing is publicly known...
    41  */
    43 struct dreamcast_module asic_module = { "ASIC", asic_init, NULL, NULL, NULL,
    44 					NULL, NULL, NULL };
    46 void asic_check_cleared_events( void );
    48 void asic_init( void )
    49 {
    50     register_io_region( &mmio_region_ASIC );
    51     register_io_region( &mmio_region_EXTDMA );
    52     mmio_region_ASIC.trace_flag = 0; /* Because this is called so often */
    53     asic_event( EVENT_GDROM_CMD );
    54 }
    56 void mmio_region_ASIC_write( uint32_t reg, uint32_t val )
    57 {
    58     switch( reg ) {
    59     case PIRQ0:
    60     case PIRQ1:
    61     case PIRQ2:
    62 	/* Clear any interrupts */
    63 	MMIO_WRITE( ASIC, reg, MMIO_READ(ASIC, reg)&~val );
    64 	asic_check_cleared_events();
    65 	break;
    66     case MAPLE_STATE:
    67 	MMIO_WRITE( ASIC, reg, val );
    68 	if( val & 1 ) {
    69 	    uint32_t maple_addr = MMIO_READ( ASIC, MAPLE_DMA) &0x1FFFFFE0;
    70 	    WARN( "Maple request initiated at %08X, halting", maple_addr );
    71 	    maple_handle_buffer( maple_addr );
    72 	    MMIO_WRITE( ASIC, reg, 0 );
    73 	}
    74 	break;
    75     case PVRDMACTL: /* Initiate PVR DMA transfer */
    76 	if( val & 1 ) {
    77 	    uint32_t dest_addr = MMIO_READ( ASIC, PVRDMADEST) &0x1FFFFFE0;
    78 	    uint32_t count = MMIO_READ( ASIC, PVRDMACNT );
    79 	    char *data = alloca( count );
    80 	    uint32_t rcount = DMAC_get_buffer( 2, data, count );
    81 	    if( rcount != count )
    82 		WARN( "PVR received %08X bytes from DMA, expected %08X", rcount, count );
    83 	    if( (dest_addr &0xF0000000) == 0x10000000 ) { /* TA */
    84 		pvr2ta_write( data, rcount );
    85 	    }
    86 	    asic_event( EVENT_PVR_DMA );
    87 	}
    88 	break;
    89     default:
    90 	MMIO_WRITE( ASIC, reg, val );
    91 	WARN( "Write to ASIC (%03X <= %08X) [%s: %s]",
    92 	      reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
    93     }
    94 }
    96 int32_t mmio_region_ASIC_read( uint32_t reg )
    97 {
    98     int32_t val;
    99     switch( reg ) {
   100         /*
   101         case 0x89C:
   102             sh4_stop();
   103             return 0x000000B;
   104         */     
   105         case PIRQ0:
   106         case PIRQ1:
   107         case PIRQ2:
   108             val = MMIO_READ(ASIC, reg);
   109 //            WARN( "Read from ASIC (%03X => %08X) [%s: %s]",
   110 //                  reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
   111             return val;            
   112         case G2STATUS:
   113             return 0; /* find out later if there's any cases we actually need to care about */
   114         default:
   115             val = MMIO_READ(ASIC, reg);
   116             WARN( "Read from ASIC (%03X => %08X) [%s: %s]",
   117                   reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
   118             return val;
   119     }
   121 }
   123 void asic_event( int event )
   124 {
   125     int offset = ((event&0x60)>>3);
   126     int result = (MMIO_READ(ASIC, PIRQ0 + offset))  |=  (1<<(event&0x1F));
   128     if( result & MMIO_READ(ASIC, IRQA0 + offset) )
   129         intc_raise_interrupt( INT_IRQ13 );
   130     if( result & MMIO_READ(ASIC, IRQB0 + offset) )
   131         intc_raise_interrupt( INT_IRQ11 );
   132     if( result & MMIO_READ(ASIC, IRQC0 + offset) )
   133         intc_raise_interrupt( INT_IRQ9 );
   134 }
   136 void asic_check_cleared_events( )
   137 {
   138     int i, setA = 0, setB = 0, setC = 0;
   139     uint32_t bits;
   140     for( i=0; i<3; i++ ) {
   141 	bits = MMIO_READ( ASIC, PIRQ0 + i );
   142 	setA |= (bits & MMIO_READ(ASIC, IRQA0 + i ));
   143 	setB |= (bits & MMIO_READ(ASIC, IRQB0 + i ));
   144 	setC |= (bits & MMIO_READ(ASIC, IRQC0 + i ));
   145     }
   146     if( setA == 0 )
   147 	intc_clear_interrupt( INT_IRQ13 );
   148     if( setB == 0 )
   149 	intc_clear_interrupt( INT_IRQ11 );
   150     if( setC == 0 )
   151 	intc_clear_interrupt( INT_IRQ9 );
   152 }
   155 MMIO_REGION_WRITE_FN( EXTDMA, reg, val )
   156 {
   157     switch( reg ) {
   158         case IDEALTSTATUS: /* Device control */
   159             ide_write_control( val );
   160             break;
   161         case IDEDATA:
   162             ide_write_data_pio( val );
   163             break;
   164         case IDEFEAT:
   165             if( ide_can_write_regs() )
   166                 idereg.feature = (uint8_t)val;
   167             break;
   168         case IDECOUNT:
   169             if( ide_can_write_regs() )
   170                 idereg.count = (uint8_t)val;
   171             break;
   172         case IDELBA0:
   173             if( ide_can_write_regs() )
   174                 idereg.lba0 = (uint8_t)val;
   175             break;
   176         case IDELBA1:
   177             if( ide_can_write_regs() )
   178                 idereg.lba1 = (uint8_t)val;
   179             break;
   180         case IDELBA2:
   181             if( ide_can_write_regs() )
   182                 idereg.lba2 = (uint8_t)val;
   183             break;
   184         case IDEDEV:
   185             if( ide_can_write_regs() )
   186                 idereg.device = (uint8_t)val;
   187             break;
   188         case IDECMD:
   189             if( ide_can_write_regs() ) {
   190                 ide_clear_interrupt();
   191                 ide_write_command( (uint8_t)val );
   192             }
   193             break;
   194         default:
   195 	    WARN( "EXTDMA write %08X <= %08X", reg, val );
   197             MMIO_WRITE( EXTDMA, reg, val );
   198     }
   199 }
   201 MMIO_REGION_READ_FN( EXTDMA, reg )
   202 {
   203     uint32_t val;
   204     switch( reg ) {
   205         case IDEALTSTATUS: return idereg.status;
   206         case IDEDATA: return ide_read_data_pio( );
   207         case IDEFEAT: return idereg.error;
   208         case IDECOUNT:return idereg.count;
   209         case IDELBA0: return idereg.disc;
   210         case IDELBA1: return idereg.lba1;
   211         case IDELBA2: return idereg.lba2;
   212         case IDEDEV: return idereg.device;
   213         case IDECMD:
   214             ide_clear_interrupt();
   215             return idereg.status;
   216         default:
   217 	    val = MMIO_READ( EXTDMA, reg );
   218 	    DEBUG( "EXTDMA read %08X => %08X", reg, val );
   219 	    return val;
   220     }
   221 }
.