filename | src/asic.c |
changeset | 94:8d80d9c7cc7d |
prev | 56:3224dceaf2a3 |
next | 100:995e42e96cc9 |
author | nkeynes |
date | Sun Feb 05 04:05:27 2006 +0000 (18 years ago) |
permissions | -rw-r--r-- |
last change | Video code reshuffle to start getting real video happening. Implement colourspace conversions Various tweaks |
view | annotate | diff | log | raw |
1 /**
2 * $Id: asic.c,v 1.11 2006-02-05 04:05:27 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 MMIO_WRITE( ASIC, reg, val );
77 WARN( "Write to ASIC (%03X <= %08X) [%s: %s]",
78 reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
79 if( val & 1 ) {
80 uint32_t dest_addr = MMIO_READ( ASIC, PVRDMADEST) &0x1FFFFFE0;
81 uint32_t count = MMIO_READ( ASIC, PVRDMACNT );
82 char *data = alloca( count );
83 uint32_t rcount = DMAC_get_buffer( 2, data, count );
84 if( rcount != count )
85 WARN( "PVR received %08X bytes from DMA, expected %08X", rcount, count );
86 if( (dest_addr &0xF0000000) == 0x10000000 ) { /* TA */
87 pvr2ta_write( data, rcount );
88 }
89 asic_event( EVENT_PVR_DMA );
90 }
91 break;
92 default:
93 MMIO_WRITE( ASIC, reg, val );
94 WARN( "Write to ASIC (%03X <= %08X) [%s: %s]",
95 reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
96 }
97 }
99 int32_t mmio_region_ASIC_read( uint32_t reg )
100 {
101 int32_t val;
102 switch( reg ) {
103 /*
104 case 0x89C:
105 sh4_stop();
106 return 0x000000B;
107 */
108 case PIRQ0:
109 case PIRQ1:
110 case PIRQ2:
111 case IRQA0:
112 case IRQA1:
113 case IRQA2:
114 case IRQB0:
115 case IRQB1:
116 case IRQB2:
117 case IRQC0:
118 case IRQC1:
119 case IRQC2:
120 val = MMIO_READ(ASIC, reg);
121 // WARN( "Read from ASIC (%03X => %08X) [%s: %s]",
122 // reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
123 return val;
124 case G2STATUS:
125 return 0; /* find out later if there's any cases we actually need to care about */
126 default:
127 val = MMIO_READ(ASIC, reg);
128 WARN( "Read from ASIC (%03X => %08X) [%s: %s]",
129 reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
130 return val;
131 }
133 }
135 void asic_event( int event )
136 {
137 int offset = ((event&0x60)>>3);
138 int result = (MMIO_READ(ASIC, PIRQ0 + offset)) |= (1<<(event&0x1F));
140 if( result & MMIO_READ(ASIC, IRQA0 + offset) )
141 intc_raise_interrupt( INT_IRQ13 );
142 if( result & MMIO_READ(ASIC, IRQB0 + offset) )
143 intc_raise_interrupt( INT_IRQ11 );
144 if( result & MMIO_READ(ASIC, IRQC0 + offset) )
145 intc_raise_interrupt( INT_IRQ9 );
146 }
148 void asic_check_cleared_events( )
149 {
150 int i, setA = 0, setB = 0, setC = 0;
151 uint32_t bits;
152 for( i=0; i<3; i++ ) {
153 bits = MMIO_READ( ASIC, PIRQ0 + i );
154 setA |= (bits & MMIO_READ(ASIC, IRQA0 + i ));
155 setB |= (bits & MMIO_READ(ASIC, IRQB0 + i ));
156 setC |= (bits & MMIO_READ(ASIC, IRQC0 + i ));
157 }
158 if( setA == 0 )
159 intc_clear_interrupt( INT_IRQ13 );
160 if( setB == 0 )
161 intc_clear_interrupt( INT_IRQ11 );
162 if( setC == 0 )
163 intc_clear_interrupt( INT_IRQ9 );
164 }
167 MMIO_REGION_WRITE_FN( EXTDMA, reg, val )
168 {
169 switch( reg ) {
170 case IDEALTSTATUS: /* Device control */
171 ide_write_control( val );
172 break;
173 case IDEDATA:
174 ide_write_data_pio( val );
175 break;
176 case IDEFEAT:
177 if( ide_can_write_regs() )
178 idereg.feature = (uint8_t)val;
179 break;
180 case IDECOUNT:
181 if( ide_can_write_regs() )
182 idereg.count = (uint8_t)val;
183 break;
184 case IDELBA0:
185 if( ide_can_write_regs() )
186 idereg.lba0 = (uint8_t)val;
187 break;
188 case IDELBA1:
189 if( ide_can_write_regs() )
190 idereg.lba1 = (uint8_t)val;
191 break;
192 case IDELBA2:
193 if( ide_can_write_regs() )
194 idereg.lba2 = (uint8_t)val;
195 break;
196 case IDEDEV:
197 if( ide_can_write_regs() )
198 idereg.device = (uint8_t)val;
199 break;
200 case IDECMD:
201 if( ide_can_write_regs() ) {
202 ide_clear_interrupt();
203 ide_write_command( (uint8_t)val );
204 }
205 break;
206 default:
207 WARN( "EXTDMA write %08X <= %08X", reg, val );
209 MMIO_WRITE( EXTDMA, reg, val );
210 }
211 }
213 MMIO_REGION_READ_FN( EXTDMA, reg )
214 {
215 uint32_t val;
216 switch( reg ) {
217 case IDEALTSTATUS: return idereg.status;
218 case IDEDATA: return ide_read_data_pio( );
219 case IDEFEAT: return idereg.error;
220 case IDECOUNT:return idereg.count;
221 case IDELBA0: return idereg.disc;
222 case IDELBA1: return idereg.lba1;
223 case IDELBA2: return idereg.lba2;
224 case IDEDEV: return idereg.device;
225 case IDECMD:
226 ide_clear_interrupt();
227 return idereg.status;
228 default:
229 val = MMIO_READ( EXTDMA, reg );
230 //DEBUG( "EXTDMA read %08X => %08X", reg, val );
231 return val;
232 }
233 }
.