filename | src/asic.c |
changeset | 35:21a4be098304 |
prev | 31:495e480360d7 |
next | 42:d06affd949ec |
author | nkeynes |
date | Mon Dec 26 03:54:55 2005 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Remove modules.h - move definitions into dream.h Add source string to output list (taken from module name) ARM Work in progress |
view | annotate | diff | log | raw |
1 /**
2 * $Id: asic.c,v 1.8 2005-12-26 03:54:52 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 "dreamcast.h"
27 #include "maple/maple.h"
28 #include "gdrom/ide.h"
29 #include "asic.h"
30 #define MMIO_IMPL
31 #include "asic.h"
32 /*
33 * Open questions:
34 * 1) Does changing the mask after event occurance result in the
35 * interrupt being delivered immediately?
36 * TODO: Logic diagram of ASIC event/interrupt logic.
37 *
38 * ... don't even get me started on the "EXTDMA" page, about which, apparently,
39 * practically nothing is publicly known...
40 */
42 struct dreamcast_module asic_module = { "ASIC", asic_init, NULL, NULL, NULL,
43 NULL, NULL, NULL };
45 void asic_check_cleared_events( void );
47 void asic_init( void )
48 {
49 register_io_region( &mmio_region_ASIC );
50 register_io_region( &mmio_region_EXTDMA );
51 mmio_region_ASIC.trace_flag = 0; /* Because this is called so often */
52 asic_event( EVENT_GDROM_CMD );
53 }
55 void mmio_region_ASIC_write( uint32_t reg, uint32_t val )
56 {
57 switch( reg ) {
58 case PIRQ0:
59 case PIRQ1:
60 case PIRQ2:
61 /* Clear any interrupts */
62 MMIO_WRITE( ASIC, reg, MMIO_READ(ASIC, reg)&~val );
63 DEBUG( "ASIC Write %08X => %08X", val, reg );
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 // dreamcast_stop();
74 }
75 break;
76 default:
77 MMIO_WRITE( ASIC, reg, val );
78 WARN( "Write to ASIC (%03X <= %08X) [%s: %s]",
79 reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
80 }
81 }
83 int32_t mmio_region_ASIC_read( uint32_t reg )
84 {
85 int32_t val;
86 switch( reg ) {
87 /*
88 case 0x89C:
89 sh4_stop();
90 return 0x000000B;
91 */
92 case PIRQ0:
93 case PIRQ1:
94 case PIRQ2:
95 val = MMIO_READ(ASIC, reg);
96 // WARN( "Read from ASIC (%03X => %08X) [%s: %s]",
97 // reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
98 return val;
99 case G2STATUS:
100 return 0; /* find out later if there's any cases we actually need to care about */
101 default:
102 val = MMIO_READ(ASIC, reg);
103 WARN( "Read from ASIC (%03X => %08X) [%s: %s]",
104 reg, val, MMIO_REGID(ASIC,reg), MMIO_REGDESC(ASIC,reg) );
105 return val;
106 }
108 }
110 void asic_event( int event )
111 {
112 int offset = ((event&0x60)>>3);
113 int result = (MMIO_READ(ASIC, PIRQ0 + offset)) |= (1<<(event&0x1F));
115 if( result & MMIO_READ(ASIC, IRQA0 + offset) )
116 intc_raise_interrupt( INT_IRQ13 );
117 if( result & MMIO_READ(ASIC, IRQB0 + offset) )
118 intc_raise_interrupt( INT_IRQ11 );
119 if( result & MMIO_READ(ASIC, IRQC0 + offset) )
120 intc_raise_interrupt( INT_IRQ9 );
121 }
123 void asic_check_cleared_events( )
124 {
125 int i, setA = 0, setB = 0, setC = 0;
126 uint32_t bits;
127 for( i=0; i<3; i++ ) {
128 bits = MMIO_READ( ASIC, PIRQ0 + i );
129 setA |= (bits & MMIO_READ(ASIC, IRQA0 + i ));
130 setB |= (bits & MMIO_READ(ASIC, IRQB0 + i ));
131 setC |= (bits & MMIO_READ(ASIC, IRQC0 + i ));
132 }
133 if( setA == 0 )
134 intc_clear_interrupt( INT_IRQ13 );
135 if( setB == 0 )
136 intc_clear_interrupt( INT_IRQ11 );
137 if( setC == 0 )
138 intc_clear_interrupt( INT_IRQ9 );
139 }
142 MMIO_REGION_WRITE_FN( EXTDMA, reg, val )
143 {
144 switch( reg ) {
145 case IDEALTSTATUS: /* Device control */
146 ide_write_control( val );
147 break;
148 case IDEDATA:
149 ide_write_data_pio( val );
150 break;
151 case IDEFEAT:
152 if( ide_can_write_regs() )
153 idereg.feature = (uint8_t)val;
154 break;
155 case IDECOUNT:
156 if( ide_can_write_regs() )
157 idereg.count = (uint8_t)val;
158 break;
159 case IDELBA0:
160 if( ide_can_write_regs() )
161 idereg.lba0 = (uint8_t)val;
162 break;
163 case IDELBA1:
164 if( ide_can_write_regs() )
165 idereg.lba1 = (uint8_t)val;
166 break;
167 case IDELBA2:
168 if( ide_can_write_regs() )
169 idereg.lba2 = (uint8_t)val;
170 break;
171 case IDEDEV:
172 if( ide_can_write_regs() )
173 idereg.device = (uint8_t)val;
174 break;
175 case IDECMD:
176 if( ide_can_write_regs() ) {
177 ide_clear_interrupt();
178 ide_write_command( (uint8_t)val );
179 }
180 break;
182 default:
183 MMIO_WRITE( EXTDMA, reg, val );
184 }
185 }
187 MMIO_REGION_READ_FN( EXTDMA, reg )
188 {
189 switch( reg ) {
190 case IDEALTSTATUS: return idereg.status;
191 case IDEDATA: return ide_read_data_pio( );
192 case IDEFEAT: return idereg.error;
193 case IDECOUNT:return idereg.count;
194 case IDELBA0: return idereg.disc;
195 case IDELBA1: return idereg.lba1;
196 case IDELBA2: return idereg.lba2;
197 case IDEDEV: return idereg.device;
198 case IDECMD:
199 ide_clear_interrupt();
200 return idereg.status;
201 default:
202 return MMIO_READ( EXTDMA, reg );
203 }
204 }
.