1 /* This file is part of the program psim.
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program 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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #ifndef STATIC_INLINE_CORE
26 #define STATIC_INLINE_CORE STATIC_INLINE
31 #include "device_tree.h"
35 typedef struct _core_mapping core_mapping
;
36 struct _core_mapping
{
42 device_io_read_buffer_callback
*reader
;
43 device_io_write_buffer_callback
*writer
;
54 core_mapping
*default_map
;
65 core_map map
[nr_core_map_types
];
72 core
*new_core
= ZALLOC(core
);
77 STATIC_INLINE_CORE
void
78 core_init(core
*memory
)
80 core_map_types access_type
;
82 access_type
< nr_core_map_types
;
84 core_map
*map
= memory
->map
+ access_type
;
85 /* blow away old mappings */
86 core_mapping
*curr
= map
->first
;
87 while (curr
!= NULL
) {
88 core_mapping
*tbd
= curr
;
90 if (tbd
->free_buffer
) {
91 ASSERT(tbd
->buffer
!= NULL
);
97 /* blow away the default */
98 if (map
->default_map
!= NULL
) {
99 ASSERT(map
->default_map
->buffer
== NULL
);
100 zfree(map
->default_map
);
102 map
->default_map
= NULL
;
108 /* the core has three sub mappings that the more efficient
109 read/write fixed quantity functions use */
111 INLINE_CORE core_map
*
112 core_readable(core
*memory
)
114 return memory
->map
+ core_read_map
;
117 INLINE_CORE core_map
*
118 core_writeable(core
*memory
)
120 return memory
->map
+ core_write_map
;
123 INLINE_CORE core_map
*
124 core_executable(core
*memory
)
126 return memory
->map
+ core_execute_map
;
131 STATIC_INLINE_CORE core_mapping
*
132 new_core_mapping(attach_type attach
,
136 const device
*device
,
140 core_mapping
*new_mapping
= ZALLOC(core_mapping
);
143 case attach_callback
:
144 new_mapping
->device
= device
;
145 new_mapping
->reader
= device
->callback
->io_read_buffer
;
146 new_mapping
->writer
= device
->callback
->io_write_buffer
;
148 case attach_raw_memory
:
149 new_mapping
->buffer
= buffer
;
150 new_mapping
->free_buffer
= free_buffer
;
153 error("new_core_mapping() - internal error - unknown attach type %d\n",
157 new_mapping
->space
= space
;
158 new_mapping
->base
= addr
;
159 new_mapping
->nr_bytes
= nr_bytes
;
160 new_mapping
->bound
= addr
+ (nr_bytes
- 1);
165 STATIC_INLINE_CORE
void
166 core_map_attach(core_map
*access_map
,
170 unsigned nr_bytes
, /* host limited */
171 const device
*device
, /*callback/default*/
172 void *buffer
, /*raw_memory*/
173 int free_buffer
) /*raw_memory*/
175 if (attach
== attach_default
) {
176 if (access_map
->default_map
!= NULL
)
177 error("core_map_attach() default mapping already in place\n");
178 ASSERT(buffer
== NULL
);
179 access_map
->default_map
= new_core_mapping(attach
,
180 space
, addr
, nr_bytes
,
181 device
, buffer
, free_buffer
);
184 /* find the insertion point for this additional mapping and insert */
185 core_mapping
*next_mapping
;
186 core_mapping
**last_mapping
;
188 /* actually do occasionally get a zero size map */
190 error("core_map_attach() size == 0\n");
192 /* find the insertion point (between last/next) */
193 next_mapping
= access_map
->first
;
194 last_mapping
= &access_map
->first
;
195 while(next_mapping
!= NULL
&& next_mapping
->bound
< addr
) {
196 /* assert: next_mapping->base > all bases before next_mapping */
197 /* assert: next_mapping->bound >= all bounds before next_mapping */
198 last_mapping
= &next_mapping
->next
;
199 next_mapping
= next_mapping
->next
;
202 /* check insertion point correct */
203 if (next_mapping
!= NULL
&& next_mapping
->base
< (addr
+ (nr_bytes
- 1))) {
204 error("core_map_attach() map overlap\n");
207 /* create/insert the new mapping */
208 *last_mapping
= new_core_mapping(attach
,
209 space
, addr
, nr_bytes
,
210 device
, buffer
, free_buffer
);
211 (*last_mapping
)->next
= next_mapping
;
217 core_attach(core
*memory
,
222 unsigned nr_bytes
, /* host limited */
223 const device
*device
) /*callback/default*/
225 core_map_types access_map
;
228 ASSERT(attach
== attach_default
|| nr_bytes
> 0);
229 if (attach
== attach_raw_memory
)
230 buffer
= zalloc(nr_bytes
);
232 access_map
< nr_core_map_types
;
234 switch (access_map
) {
236 if (access
& access_read
)
237 core_map_attach(memory
->map
+ access_map
,
239 space
, addr
, nr_bytes
,
240 device
, buffer
, !free_buffer
);
244 if (access
& access_write
)
245 core_map_attach(memory
->map
+ access_map
,
247 space
, addr
, nr_bytes
,
248 device
, buffer
, !free_buffer
);
251 case core_execute_map
:
252 if (access
& access_exec
)
253 core_map_attach(memory
->map
+ access_map
,
255 space
, addr
, nr_bytes
,
256 device
, buffer
, !free_buffer
);
260 error("core_attach() internal error\n");
264 ASSERT(free_buffer
> 0); /* must attach to at least one thing */
268 STATIC_INLINE_CORE core_mapping
*
269 core_map_find_mapping(core_map
*map
,
274 int abort
) /*either 0 or 1 - helps inline */
276 core_mapping
*mapping
= map
->first
;
277 ASSERT((addr
& (nr_bytes
- 1)) == 0); /* must be aligned */
278 ASSERT((addr
+ (nr_bytes
- 1)) >= addr
); /* must not wrap */
279 while (mapping
!= NULL
) {
280 if (addr
>= mapping
->base
281 && (addr
+ (nr_bytes
- 1)) <= mapping
->bound
)
283 mapping
= mapping
->next
;
285 if (map
->default_map
!= NULL
)
286 return map
->default_map
;
288 error("core_find_mapping() - access to unmaped address, attach a default map to handle this - addr=0x%x nr_bytes=0x%x processor=0x%x cia=0x%x\n",
289 addr
, nr_bytes
, processor
, cia
);
294 STATIC_INLINE_CORE
void *
295 core_translate(core_mapping
*mapping
,
298 return mapping
->buffer
+ addr
- mapping
->base
;
303 core_map_read_buffer(core_map
*map
,
310 for (count
= 0; count
< len
; count
++) {
311 unsigned_word raddr
= addr
+ count
;
312 core_mapping
*mapping
=
313 core_map_find_mapping(map
,
320 if (mapping
->reader
!= NULL
) {
321 if (mapping
->reader(mapping
->device
,
324 raddr
- mapping
->base
,
331 byte
= *(unsigned_1
*)core_translate(mapping
,
333 ((unsigned_1
*)buffer
)[count
] = T2H_1(byte
);
340 core_map_write_buffer(core_map
*map
,
347 for (count
= 0; count
< len
; count
++) {
348 unsigned_word raddr
= addr
+ count
;
349 core_mapping
*mapping
= core_map_find_mapping(map
,
356 byte
= H2T_1(((unsigned_1
*)buffer
)[count
]);
357 if (mapping
->writer
!= NULL
) {
358 if (mapping
->writer(mapping
->device
,
361 raddr
- mapping
->base
,
368 *(unsigned_1
*)core_translate(mapping
, raddr
) = byte
;
375 /* Top level core(root) device: core@garbage
377 The core device captures incomming dma requests and changes them to
378 outgoing io requests. */
380 STATIC_INLINE_CORE
void
381 core_init_callback(const device
*me
,
384 core
*memory
= (core
*)me
->data
;
390 STATIC_INLINE_CORE
void
391 core_attach_address_callback(const device
*me
,
398 const device
*who
) /*callback/default*/
400 core
*memory
= (core
*)me
->data
;
401 DTRACE_ATTACH_ADDRESS(core
);
403 error("core_attach_address_callback() invalid address space\n");
414 STATIC_INLINE_CORE
unsigned
415 core_dma_read_buffer_callback(const device
*me
,
421 core
*memory
= (core
*)me
->data
;
422 DTRACE_DMA_READ_BUFFER(core
);
423 return core_map_read_buffer(core_readable(memory
),
430 STATIC_INLINE_CORE
unsigned
431 core_dma_write_buffer_callback(const device
*me
,
436 int violate_read_only_section
)
438 core
*memory
= (core
*)me
->data
;
439 core_map
*map
= (violate_read_only_section
440 ? core_readable(memory
)
441 : core_writeable(memory
));
442 DTRACE_DMA_WRITE_BUFFER(core
);
443 return core_map_write_buffer(map
,
450 static device_callbacks
const core_callbacks
= {
452 core_attach_address_callback
,
453 unimp_device_detach_address
,
454 unimp_device_io_read_buffer
,
455 unimp_device_io_write_buffer
,
456 core_dma_read_buffer_callback
,
457 core_dma_write_buffer_callback
,
458 unimp_device_attach_interrupt
,
459 unimp_device_detach_interrupt
,
460 unimp_device_interrupt
,
461 unimp_device_interrupt_ack
,
466 INLINE_CORE
const device
*
467 core_device_create(core
*memory
)
469 return device_create_from("core", "/", memory
, &core_callbacks
, NULL
);
474 /* define the read/write 1/2/4/8/word functions */
496 #endif /* _CORE_C_ */