2 * $Id: asic.c,v 1.10 2006-01-01 08:09:42 nkeynes Exp $
4 * Support for the miscellaneous ASIC functions (Primarily event multiplexing,
7 * Copyright (c) 2005 Nathan Keynes.
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.
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.
20 #define MODULE asic_module
27 #include "dreamcast.h"
28 #include "maple/maple.h"
29 #include "gdrom/ide.h"
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.
39 * ... don't even get me started on the "EXTDMA" page, about which, apparently,
40 * practically nothing is publicly known...
43 struct dreamcast_module asic_module = { "ASIC", asic_init, NULL, NULL, NULL,
46 void asic_check_cleared_events( void );
48 void asic_init( void )
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 );
56 void mmio_region_ASIC_write( uint32_t reg, uint32_t val )
62 /* Clear any interrupts */
63 MMIO_WRITE( ASIC, reg, MMIO_READ(ASIC, reg)&~val );
64 asic_check_cleared_events();
67 MMIO_WRITE( ASIC, reg, val );
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 );
75 case PVRDMACTL: /* Initiate PVR DMA transfer */
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 );
82 WARN( "PVR received %08X bytes from DMA, expected %08X", rcount, count );
83 if( (dest_addr &0xF0000000) == 0x10000000 ) { /* TA */
84 pvr2ta_write( data, rcount );
86 asic_event( EVENT_PVR_DMA );
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) );
96 int32_t mmio_region_ASIC_read( uint32_t reg )
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) );
113 return 0; /* find out later if there's any cases we actually need to care about */
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) );
123 void asic_event( int event )
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 );
136 void asic_check_cleared_events( )
138 int i, setA = 0, setB = 0, setC = 0;
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 ));
147 intc_clear_interrupt( INT_IRQ13 );
149 intc_clear_interrupt( INT_IRQ11 );
151 intc_clear_interrupt( INT_IRQ9 );
155 MMIO_REGION_WRITE_FN( EXTDMA, reg, val )
158 case IDEALTSTATUS: /* Device control */
159 ide_write_control( val );
162 ide_write_data_pio( val );
165 if( ide_can_write_regs() )
166 idereg.feature = (uint8_t)val;
169 if( ide_can_write_regs() )
170 idereg.count = (uint8_t)val;
173 if( ide_can_write_regs() )
174 idereg.lba0 = (uint8_t)val;
177 if( ide_can_write_regs() )
178 idereg.lba1 = (uint8_t)val;
181 if( ide_can_write_regs() )
182 idereg.lba2 = (uint8_t)val;
185 if( ide_can_write_regs() )
186 idereg.device = (uint8_t)val;
189 if( ide_can_write_regs() ) {
190 ide_clear_interrupt();
191 ide_write_command( (uint8_t)val );
195 WARN( "EXTDMA write %08X <= %08X", reg, val );
197 MMIO_WRITE( EXTDMA, reg, val );
201 MMIO_REGION_READ_FN( EXTDMA, 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;
214 ide_clear_interrupt();
215 return idereg.status;
217 val = MMIO_READ( EXTDMA, reg );
218 DEBUG( "EXTDMA read %08X => %08X", reg, val );
.