Remove missing file "PROBLEMS" from list of files to keep.
[deliverable/binutils-gdb.git] / sim / ppc / device_table.c
CommitLineData
cb7a6892
MM
1/* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
4
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.
9
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.
14
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.
18
19 */
20
21
93fac324
MM
22#ifndef _DEVICE_TABLE_C_
23#define _DEVICE_TABLE_C_
cb7a6892 24
93fac324
MM
25#ifndef STATIC_INLINE_DEVICE_TABLE
26#define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
cb7a6892
MM
27#endif
28
cb7a6892 29#include <stdio.h>
cb7a6892 30#include <fcntl.h>
dec38dac
MM
31#include <signal.h>
32#include <stdarg.h>
979c3c25 33#include <ctype.h>
cb7a6892 34
93fac324
MM
35#include "device_table.h"
36
cb7a6892
MM
37#include "events.h"
38
c494cadd
MM
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42
43#ifdef HAVE_STDLIB_H
44#include <stdlib.h>
45#endif
46
47#ifdef HAVE_STRING_H
48#include <string.h>
49#else
50#ifdef HAVE_STRINGS_H
51#include <strings.h>
52#endif
53#endif
54
dec38dac
MM
55#include "cpu.h"
56
57#include "bfd.h"
cb7a6892
MM
58
59/* Helper functions */
60
dec38dac
MM
61/* Generic device init: Attaches the device of size <nr_bytes> (taken
62 from <name>@<int>,<nr_bytes>) to its parent at address zero and
63 with read/write access. */
64
93fac324
MM
65STATIC_INLINE_DEVICE_TABLE void
66generic_init_callback(device *me,
dec38dac 67 psim *system)
cb7a6892 68{
dec38dac
MM
69 unsigned_word addr;
70 unsigned nr_bytes;
93fac324
MM
71 if (scand_uw_u(device_name(me), &addr, &nr_bytes) != 2)
72 error("generic_init_callback() invalid nr_bytes in %s\n", device_name(me));
73 device_attach_address(device_parent(me),
74 device_name(me),
75 attach_callback,
76 0 /*space*/,
77 addr,
78 nr_bytes,
79 access_read_write,
80 me);
cb7a6892
MM
81}
82
83
1dc7c0ed 84/* DMA a file into memory */
93fac324
MM
85STATIC_INLINE_DEVICE_TABLE int
86dma_file(device *me,
1dc7c0ed
MM
87 const char *file_name,
88 unsigned_word addr)
89{
90 int count;
91 int inc;
92 FILE *image;
93 char buf[1024];
94
95 /* get it open */
96 image = fopen(file_name, "r");
97 if (image == NULL)
98 return -1;
99
100 /* read it in slowly */
101 count = 0;
102 while (1) {
93fac324
MM
103 inc = fread(buf, 1, sizeof(buf), image);
104 if (feof(image) || ferror(image))
1dc7c0ed 105 break;
93fac324
MM
106 if (device_dma_write_buffer(device_parent(me),
107 buf,
108 0 /*address-space*/,
109 addr+count,
110 inc /*nr-bytes*/,
111 1 /*violate ro*/) != inc) {
1dc7c0ed
MM
112 fclose(image);
113 return -1;
114 }
115 count += inc;
116 }
117
118 /* close down again */
119 fclose(image);
120
121 return count;
122}
123
124
dec38dac
MM
125\f
126/* inimplemented versions of each function */
cb7a6892 127
93fac324
MM
128void
129unimp_device_init(device *me,
dec38dac
MM
130 psim *system)
131{
93fac324 132 error("device_init_callback for %s not implemented\n", device_name(me));
dec38dac 133}
cb7a6892 134
93fac324
MM
135void
136unimp_device_attach_address(device *me,
dec38dac
MM
137 const char *name,
138 attach_type type,
5b4d72dd 139 int space,
dec38dac
MM
140 unsigned_word addr,
141 unsigned nr_bytes,
142 access_type access,
93fac324 143 device *who) /*callback/default*/
dec38dac 144{
93fac324 145 error("device_attach_address_callback for %s not implemented\n", device_name(me));
dec38dac 146}
cb7a6892 147
93fac324
MM
148void
149unimp_device_detach_address(device *me,
dec38dac
MM
150 const char *name,
151 attach_type type,
5b4d72dd 152 int space,
dec38dac
MM
153 unsigned_word addr,
154 unsigned nr_bytes,
155 access_type access,
93fac324 156 device *who) /*callback/default*/
dec38dac 157{
93fac324 158 error("device_detach_address_callback for %s not implemented\n", device_name(me));
dec38dac 159}
cb7a6892 160
93fac324
MM
161unsigned
162unimp_device_io_read_buffer(device *me,
dec38dac 163 void *dest,
5b4d72dd 164 int space,
dec38dac
MM
165 unsigned_word addr,
166 unsigned nr_bytes,
167 cpu *processor,
168 unsigned_word cia)
169{
93fac324 170 error("device_io_read_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
171 return 0;
172}
cb7a6892 173
93fac324
MM
174unsigned
175unimp_device_io_write_buffer(device *me,
dec38dac 176 const void *source,
5b4d72dd 177 int space,
dec38dac
MM
178 unsigned_word addr,
179 unsigned nr_bytes,
180 cpu *processor,
181 unsigned_word cia)
182{
93fac324 183 error("device_io_write_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
184 return 0;
185}
186
93fac324
MM
187unsigned
188unimp_device_dma_read_buffer(device *me,
dec38dac 189 void *target,
5b4d72dd 190 int space,
dec38dac
MM
191 unsigned_word addr,
192 unsigned nr_bytes)
193{
93fac324 194 error("device_dma_read_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
195 return 0;
196}
197
93fac324
MM
198unsigned
199unimp_device_dma_write_buffer(device *me,
dec38dac 200 const void *source,
5b4d72dd 201 int space,
dec38dac
MM
202 unsigned_word addr,
203 unsigned nr_bytes,
204 int violate_read_only_section)
205{
93fac324 206 error("device_dma_write_buffer_callback for %s not implemented\n", device_name(me));
dec38dac
MM
207 return 0;
208}
209
93fac324
MM
210void
211unimp_device_attach_interrupt(device *me,
212 device *who,
dec38dac
MM
213 int interrupt_line,
214 const char *name)
215{
93fac324 216 error("device_attach_interrupt_callback for %s not implemented\n", device_name(me));
dec38dac
MM
217}
218
93fac324
MM
219void
220unimp_device_detach_interrupt(device *me,
221 device *who,
dec38dac
MM
222 int interrupt_line,
223 const char *name)
224{
93fac324 225 error("device_detach_interrupt_callback for %s not implemented\n", device_name(me));
dec38dac
MM
226}
227
93fac324
MM
228void
229unimp_device_interrupt(device *me,
230 device *who,
dec38dac
MM
231 int interrupt_line,
232 int interrupt_status,
233 cpu *processor,
234 unsigned_word cia)
235{
93fac324 236 error("device_interrupt_callback for %s not implemented\n", device_name(me));
dec38dac
MM
237}
238
93fac324
MM
239void
240unimp_device_interrupt_ack(device *me,
dec38dac
MM
241 int interrupt_line,
242 int interrupt_status)
243{
93fac324 244 error("device_interrupt_ack_callback for %s not implemented\n", device_name(me));
dec38dac
MM
245}
246
93fac324
MM
247void
248unimp_device_ioctl(device *me,
dec38dac
MM
249 psim *system,
250 cpu *processor,
251 unsigned_word cia,
93fac324 252 va_list ap)
dec38dac 253{
93fac324 254 error("device_ioctl_callback for %s not implemented\n", device_name(me));
dec38dac
MM
255}
256
257
258\f
259/* ignore/passthrough versions of each function */
260
93fac324
MM
261void
262ignore_device_init(device *me,
dec38dac
MM
263 psim *system)
264{
265 /*null*/
266}
267
93fac324
MM
268void
269passthrough_device_attach_address(device *me,
270 const char *name,
271 attach_type attach,
272 int space,
273 unsigned_word addr,
274 unsigned nr_bytes,
275 access_type access,
276 device *who) /*callback/default*/
dec38dac 277{
93fac324
MM
278 device_attach_address(device_parent(me), name, attach,
279 space, addr, nr_bytes,
280 access,
281 who);
dec38dac
MM
282}
283
93fac324
MM
284void
285passthrough_device_detach_address(device *me,
286 const char *name,
287 attach_type attach,
288 int space,
289 unsigned_word addr,
dec38dac
MM
290 unsigned nr_bytes,
291 access_type access,
93fac324 292 device *who) /*callback/default*/
dec38dac 293{
93fac324
MM
294 device_detach_address(device_parent(me), name, attach,
295 space, addr, nr_bytes, access,
296 who);
dec38dac
MM
297}
298
93fac324
MM
299unsigned
300passthrough_device_dma_read_buffer(device *me,
5b4d72dd
MM
301 void *dest,
302 int space,
dec38dac
MM
303 unsigned_word addr,
304 unsigned nr_bytes)
305{
93fac324
MM
306 return device_dma_read_buffer(device_parent(me), dest,
307 space, addr, nr_bytes);
dec38dac
MM
308}
309
93fac324
MM
310unsigned
311passthrough_device_dma_write_buffer(device *me,
dec38dac 312 const void *source,
5b4d72dd 313 int space,
dec38dac
MM
314 unsigned_word addr,
315 unsigned nr_bytes,
316 int violate_read_only_section)
317{
93fac324
MM
318 return device_dma_write_buffer(device_parent(me), source,
319 space, addr,
320 nr_bytes,
321 violate_read_only_section);
dec38dac
MM
322}
323
93fac324
MM
324void
325passthrough_device_attach_interrupt(device *me,
326 device *who,
327 int interrupt_line,
328 const char *name)
dec38dac 329{
93fac324
MM
330 device_attach_interrupt(device_parent(me), who,
331 interrupt_line, name);
dec38dac
MM
332}
333
93fac324
MM
334void
335passthrough_device_detach_interrupt(device *me,
336 device *who,
dec38dac
MM
337 int interrupt_line,
338 const char *name)
339{
93fac324
MM
340 device_detach_interrupt(device_parent(me), who,
341 interrupt_line, name);
dec38dac
MM
342}
343
344
93fac324
MM
345void
346passthrough_device_interrupt(device *me,
347 device *who,
dec38dac
MM
348 int interrupt_line,
349 int interrupt_status,
350 cpu *processor,
351 unsigned_word cia)
352{
93fac324 353 device_interrupt(device_parent(me), who,
dec38dac
MM
354 interrupt_line, interrupt_status,
355 processor, cia);
356}
357
358
93fac324
MM
359static const device_callbacks passthrough_callbacks = {
360 ignore_device_init,
361 passthrough_device_attach_address,
362 passthrough_device_detach_address,
363 unimp_device_io_read_buffer,
364 unimp_device_io_write_buffer,
365 passthrough_device_dma_read_buffer,
366 passthrough_device_dma_write_buffer,
367 passthrough_device_attach_interrupt,
368 passthrough_device_detach_interrupt,
369 passthrough_device_interrupt,
370 unimp_device_interrupt_ack,
371 unimp_device_ioctl,
372};
373
374
dec38dac 375\f
1dc7c0ed 376/* Simple console device: console@<address>,16
dec38dac
MM
377
378 Input characters are taken from the keyboard, output characters
379 sent to the terminal. Echoing of characters is not disabled.
380
381 The device has four registers:
382
383 0x0: read
384 0x4: read-status
385 0x8: write
386 0xC: write-status
387
388 Where a nonzero status register indicates that the device is ready
389 (input fifo contains a character or output fifo has space). */
cb7a6892
MM
390
391typedef struct _console_buffer {
392 char buffer;
393 int status;
394 event_entry_tag event_tag;
395} console_buffer;
396
397typedef struct _console_device {
cb7a6892
MM
398 console_buffer input;
399 console_buffer output;
400} console_device;
401
402typedef enum {
403 console_read_buffer = 0,
404 console_read_status = 4,
405 console_write_buffer = 8,
406 console_write_status = 12,
407 console_offset_mask = 0xc,
408 console_size = 16,
409} console_offsets;
410
411
93fac324
MM
412static unsigned
413console_io_read_buffer_callback(device *me,
dec38dac 414 void *dest,
5b4d72dd 415 int space,
dec38dac
MM
416 unsigned_word addr,
417 unsigned nr_bytes,
418 cpu *processor,
419 unsigned_word cia)
cb7a6892 420{
93fac324 421 console_device *console = (console_device*)device_data(me);
dec38dac 422 unsigned_1 val;
cb7a6892 423
dec38dac 424 /* determine what was read */
cb7a6892 425
c5addc19 426 switch ((int)addr) {
cb7a6892
MM
427
428 case console_read_buffer:
dec38dac
MM
429 val = console->input.buffer;
430 break;
cb7a6892
MM
431
432 case console_read_status:
433 { /* check for input */
434 int flags;
435 int status;
436 /* get the old status */
437 flags = fcntl(0, F_GETFL, 0);
438 if (flags == -1) {
439 perror("console");
dec38dac
MM
440 val = 0;
441 break;
cb7a6892
MM
442 }
443 /* temp, disable blocking IO */
444 status = fcntl(0, F_SETFL, flags | O_NDELAY);
445 if (status == -1) {
446 perror("console");
dec38dac
MM
447 val = 0;
448 break;
cb7a6892
MM
449 }
450 /* try for input */
dec38dac 451 status = read(0, &console->input.buffer, 1);
cb7a6892 452 if (status == 1) {
dec38dac 453 console->input.status = 1;
cb7a6892
MM
454 }
455 else {
dec38dac 456 console->input.status = 0;
cb7a6892
MM
457 }
458 /* return to regular vewing */
459 fcntl(0, F_SETFL, flags);
460 }
dec38dac
MM
461 val = console->input.status;
462 break;
cb7a6892
MM
463
464 case console_write_buffer:
dec38dac
MM
465 val = console->output.buffer;
466 break;
cb7a6892
MM
467
468 case console_write_status:
dec38dac
MM
469 val = console->output.status;
470 break;
cb7a6892
MM
471
472 default:
473 error("console_read_callback() internal error\n");
dec38dac
MM
474 val = 0;
475 break;
cb7a6892
MM
476
477 }
478
1dc7c0ed 479 memset(dest, 0, nr_bytes);
dec38dac
MM
480 *(unsigned_1*)dest = val;
481 return nr_bytes;
cb7a6892
MM
482}
483
93fac324
MM
484static unsigned
485console_io_write_buffer_callback(device *me,
dec38dac 486 const void *source,
5b4d72dd 487 int space,
dec38dac
MM
488 unsigned_word addr,
489 unsigned nr_bytes,
490 cpu *processor,
491 unsigned_word cia)
cb7a6892 492{
93fac324 493 console_device *console = (console_device*)device_data(me);
1dc7c0ed 494 unsigned_1 val = *(unsigned_1*)source;
cb7a6892 495
c5addc19 496 switch ((int)addr) {
dec38dac
MM
497 case console_read_buffer:
498 console->input.buffer = val;
499 break;
500 case console_read_status:
501 console->input.status = val;
502 break;
cb7a6892 503 case console_write_buffer:
5b4d72dd 504 DTRACE(console, ("<%c:%d>", val, val));
dec38dac
MM
505 printf_filtered("%c",val) ;
506 console->output.buffer = val;
507 console->output.status = 1;
cb7a6892
MM
508 break;
509 case console_write_status:
dec38dac 510 console->output.status = val;
cb7a6892 511 break;
dec38dac
MM
512 default:
513 error("console_write_callback() internal error\n");
cb7a6892 514 }
dec38dac
MM
515
516 return nr_bytes;
cb7a6892
MM
517}
518
dec38dac
MM
519
520static device_callbacks const console_callbacks = {
521 generic_init_callback,
522 unimp_device_attach_address,
523 unimp_device_detach_address,
524 console_io_read_buffer_callback,
525 console_io_write_buffer_callback,
526 unimp_device_dma_read_buffer,
527 unimp_device_dma_write_buffer,
528 unimp_device_attach_interrupt,
529 unimp_device_detach_interrupt,
530 unimp_device_interrupt,
531 unimp_device_interrupt_ack,
532 unimp_device_ioctl,
cb7a6892
MM
533};
534
cb7a6892 535
93fac324 536static void *
dec38dac 537console_create(const char *name,
93fac324 538 device *parent)
dec38dac 539{
cb7a6892
MM
540 /* create the descriptor */
541 console_device *console = ZALLOC(console_device);
cb7a6892
MM
542 console->output.status = 1;
543 console->output.buffer = '\0';
544 console->input.status = 0;
545 console->input.buffer = '\0';
93fac324 546 return console;
cb7a6892
MM
547}
548
cb7a6892 549
dec38dac
MM
550\f
551/* ICU device: icu@0x<address>,4
cb7a6892
MM
552
553 Single 4 byte register. Read returns processor number. Write
554 interrupts specified processor.
555
556 Illustrates passing of events to parent device. Passing of
557 interrupts to parent bus.
558
559 NB: For the sake of illustrating the passing of interrupts. This
560 device doesn't pass interrupt events to its parent. Instead it
561 passes them back to its self. */
562
93fac324
MM
563static unsigned
564icu_io_read_buffer_callback(device *me,
dec38dac 565 void *dest,
5b4d72dd
MM
566 int space,
567 unsigned_word addr,
dec38dac
MM
568 unsigned nr_bytes,
569 cpu *processor,
570 unsigned_word cia)
cb7a6892 571{
dec38dac 572 unsigned_1 val;
dec38dac 573 val = cpu_nr(processor);
1dc7c0ed 574 memset(dest, 0, nr_bytes);
dec38dac
MM
575 *(unsigned_1*)dest = val;
576 return nr_bytes;
cb7a6892
MM
577}
578
dec38dac 579
93fac324
MM
580static unsigned
581icu_io_write_buffer_callback(device *me,
dec38dac 582 const void *source,
5b4d72dd
MM
583 int space,
584 unsigned_word addr,
dec38dac
MM
585 unsigned nr_bytes,
586 cpu *processor,
587 unsigned_word cia)
cb7a6892 588{
dec38dac 589 unsigned_1 val = H2T_1(*(unsigned_1*)source);
cb7a6892
MM
590 /* tell the parent device that the interrupt lines have changed.
591 For this fake ICU. The interrupt lines just indicate the cpu to
592 interrupt next */
93fac324
MM
593 device_interrupt(device_parent(me), me,
594 val, val,
595 processor, cia);
dec38dac 596 return nr_bytes;
cb7a6892
MM
597}
598
dec38dac
MM
599
600static device_callbacks const icu_callbacks = {
601 generic_init_callback,
602 unimp_device_attach_address,
603 unimp_device_detach_address,
604 icu_io_read_buffer_callback,
605 icu_io_write_buffer_callback,
606 unimp_device_dma_read_buffer,
607 unimp_device_dma_write_buffer,
608 unimp_device_attach_interrupt,
609 unimp_device_detach_interrupt,
610 unimp_device_interrupt,
611 unimp_device_interrupt_ack,
612 unimp_device_ioctl,
613};
614
615
616\f
617/* HALT device: halt@0x<address>,4
618
619 With real hardware, the processor operation is normally terminated
620 through a reset. This device illustrates how a reset device could
621 be attached to an address */
622
623
93fac324
MM
624static unsigned
625halt_io_read_buffer_callback(device *me,
dec38dac 626 void *dest,
5b4d72dd
MM
627 int space,
628 unsigned_word addr,
dec38dac
MM
629 unsigned nr_bytes,
630 cpu *processor,
631 unsigned_word cia)
632{
633 cpu_halt(processor, cia, was_exited, 0);
634 return 0;
635}
636
637
93fac324
MM
638static unsigned
639halt_io_write_buffer_callback(device *me,
dec38dac 640 const void *source,
5b4d72dd 641 int space,
dec38dac
MM
642 unsigned_word addr,
643 unsigned nr_bytes,
644 cpu *processor,
645 unsigned_word cia)
646{
1dc7c0ed 647 cpu_halt(processor, cia, was_exited, *(unsigned_1*)source);
dec38dac
MM
648 return 0;
649}
650
651
652static device_callbacks const halt_callbacks = {
653 generic_init_callback,
654 unimp_device_attach_address,
655 unimp_device_detach_address,
656 halt_io_read_buffer_callback,
657 halt_io_write_buffer_callback,
658 unimp_device_dma_read_buffer,
659 unimp_device_dma_write_buffer,
660 unimp_device_attach_interrupt,
661 unimp_device_detach_interrupt,
662 unimp_device_interrupt,
663 unimp_device_interrupt_ack,
664 unimp_device_ioctl,
665};
666
667
668\f
93fac324 669/* Register init device: register
dec38dac 670
93fac324 671 Properties attached to the register device specify the name/value
979c3c25
MM
672 initialization pair for cpu registers.
673
674 FIXME: A specific processor can be initialized by creating a
675 property with a name like `0.pc'. */
dec38dac 676
93fac324
MM
677static void
678register_init(device *me,
679 const char *name,
680 void *data)
681{
682 psim *system = (psim*)data;
683 unsigned32 value = device_find_integer_property(me, name);
979c3c25
MM
684 int processor;
685 if (isdigit(name[0]) && name[1] == '.') {
686 processor = atol(name);
687 name += 2;
52edddb9 688 DTRACE(register, ("%d.%s=0x%lx\n", processor, name, (unsigned long)value));
979c3c25
MM
689 }
690 else {
691 processor = -1;
692 DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
693 }
694 psim_write_register(system, processor, /* all processors */
93fac324
MM
695 &value,
696 name,
697 cooked_transfer);
698}
699
700
701static void
702register_init_callback(device *me,
dec38dac
MM
703 psim *system)
704{
93fac324 705 device_traverse_properties(me, register_init, system);
dec38dac
MM
706}
707
708
709static device_callbacks const register_callbacks = {
710 register_init_callback,
711 unimp_device_attach_address,
712 unimp_device_detach_address,
713 unimp_device_io_read_buffer,
714 unimp_device_io_write_buffer,
715 unimp_device_dma_read_buffer,
716 unimp_device_dma_write_buffer,
717 unimp_device_attach_interrupt,
718 unimp_device_detach_interrupt,
719 unimp_device_interrupt,
720 unimp_device_interrupt_ack,
721 unimp_device_ioctl,
722};
723
724
725\f
726/* VEA VM device: vm@0x<stack-base>,<nr_bytes>
727
728 A VEA mode device. This sets its self up as the default memory
729 device capturing all accesses (reads/writes) to currently unmapped
730 addresses. If the unmaped access falls within unallocated stack or
731 heap address ranges then memory is allocated and the access is
732 allowed to continue.
733
734 During init phase, this device expects to receive `attach' requests
735 from its children for the text/data/bss memory areas. Typically,
736 this would be done by the binary device.
737
738 STACK: The location of the stack in memory is specified as part of
739 the devices name. Unmaped accesses that fall within the stack
740 space result in the allocated stack being grown downwards so that
741 it includes the page of the culprit access.
742
743 HEAP: During initialization, the vm device monitors all `attach'
744 operations from its children using this to determine the initial
745 location of the heap. The heap is then extended by system calls
746 that frob the heap upper bound variable (see system.c). */
747
748
749typedef struct _vm_device {
750 /* area of memory valid for stack addresses */
751 unsigned_word stack_base; /* min possible stack value */
752 unsigned_word stack_bound;
753 unsigned_word stack_lower_limit;
754 /* area of memory valid for heap addresses */
755 unsigned_word heap_base;
756 unsigned_word heap_bound;
757 unsigned_word heap_upper_limit;
758} vm_device;
759
760
93fac324
MM
761static void
762vm_init_callback(device *me,
dec38dac
MM
763 psim *system)
764{
93fac324 765 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
766
767 /* revert the stack/heap variables to their defaults */
768 vm->stack_lower_limit = vm->stack_bound;
769 vm->heap_base = 0;
770 vm->heap_bound = 0;
771 vm->heap_upper_limit = 0;
772
773 /* establish this device as the default memory handler */
93fac324
MM
774 device_attach_address(device_parent(me),
775 device_name(me),
776 attach_default,
777 0 /*address space - ignore*/,
778 0 /*addr - ignore*/,
779 0 /*nr_bytes - ignore*/,
780 access_read_write /*access*/,
781 me);
dec38dac
MM
782}
783
784
93fac324
MM
785static void
786vm_attach_address(device *me,
dec38dac 787 const char *name,
5b4d72dd
MM
788 attach_type attach,
789 int space,
dec38dac
MM
790 unsigned_word addr,
791 unsigned nr_bytes,
792 access_type access,
93fac324 793 device *who) /*callback/default*/
dec38dac 794{
93fac324 795 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
796 /* update end of bss if necessary */
797 if (vm->heap_base < addr + nr_bytes) {
798 vm->heap_base = addr + nr_bytes;
799 vm->heap_bound = addr + nr_bytes;
800 vm->heap_upper_limit = addr + nr_bytes;
801 }
93fac324
MM
802 device_attach_address(device_parent(me),
803 "vm@0x0,0", /* stop remap */
804 attach_raw_memory,
805 0 /*address space*/,
806 addr,
807 nr_bytes,
808 access,
809 me);
dec38dac
MM
810}
811
812
93fac324
MM
813STATIC_INLINE_DEVICE_TABLE unsigned
814add_vm_space(device *me,
dec38dac
MM
815 unsigned_word addr,
816 unsigned nr_bytes,
817 cpu *processor,
818 unsigned_word cia)
819{
93fac324 820 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
821 unsigned_word block_addr;
822 unsigned block_nr_bytes;
823
824 /* an address in the stack area, allocate just down to the addressed
825 page */
826 if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
827 block_addr = FLOOR_PAGE(addr);
828 block_nr_bytes = vm->stack_lower_limit - block_addr;
829 vm->stack_lower_limit = block_addr;
830 }
831 /* an address in the heap area, allocate all of the required heap */
832 else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
833 block_addr = vm->heap_upper_limit;
834 block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
835 vm->heap_upper_limit = vm->heap_bound;
836 }
837 /* oops - an invalid address - abort the cpu */
838 else if (processor != NULL) {
839 cpu_halt(processor, cia, was_signalled, SIGSEGV);
840 return 0;
841 }
842 /* 2*oops - an invalid address and no processor */
843 else {
844 return 0;
845 }
846
847 /* got the parameters, allocate the space */
93fac324
MM
848 device_attach_address(device_parent(me),
849 "vm@0x0,0", /* stop remap */
850 attach_raw_memory,
851 0 /*address space*/,
852 block_addr,
853 block_nr_bytes,
854 access_read_write,
855 me);
dec38dac
MM
856 return block_nr_bytes;
857}
858
859
93fac324
MM
860static unsigned
861vm_io_read_buffer_callback(device *me,
dec38dac 862 void *dest,
5b4d72dd 863 int space,
dec38dac
MM
864 unsigned_word addr,
865 unsigned nr_bytes,
866 cpu *processor,
867 unsigned_word cia)
868{
869 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
1dc7c0ed 870 memset(dest, 0, nr_bytes); /* always initialized to zero */
dec38dac
MM
871 return nr_bytes;
872 }
873 else
874 return 0;
875}
876
877
93fac324
MM
878static unsigned
879vm_io_write_buffer_callback(device *me,
dec38dac 880 const void *source,
5b4d72dd 881 int space,
dec38dac
MM
882 unsigned_word addr,
883 unsigned nr_bytes,
884 cpu *processor,
885 unsigned_word cia)
886{
887 if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
93fac324
MM
888 return device_dma_write_buffer(device_parent(me), source,
889 space, addr,
890 nr_bytes,
891 0/*violate_read_only*/);
dec38dac
MM
892 }
893 else
894 return 0;
895}
896
897
8e20a3ac 898static void
93fac324 899vm_ioctl_callback(device *me,
dec38dac
MM
900 psim *system,
901 cpu *processor,
902 unsigned_word cia,
93fac324 903 va_list ap)
dec38dac
MM
904{
905 /* While the caller is notified that the heap has grown by the
906 requested amount, the heap is infact extended out to a page
907 boundary. */
93fac324 908 vm_device *vm = (vm_device*)device_data(me);
dec38dac
MM
909 unsigned_word new_break = ALIGN_8(cpu_registers(processor)->gpr[3]);
910 unsigned_word old_break = vm->heap_bound;
911 signed_word delta = new_break - old_break;
912 if (delta > 0)
913 vm->heap_bound = ALIGN_PAGE(new_break);
914 cpu_registers(processor)->gpr[0] = 0;
915 cpu_registers(processor)->gpr[3] = new_break;
916}
917
918
919static device_callbacks const vm_callbacks = {
920 vm_init_callback,
921 vm_attach_address,
93fac324 922 passthrough_device_detach_address,
dec38dac
MM
923 vm_io_read_buffer_callback,
924 vm_io_write_buffer_callback,
925 unimp_device_dma_read_buffer,
93fac324 926 passthrough_device_dma_write_buffer,
dec38dac
MM
927 unimp_device_attach_interrupt,
928 unimp_device_detach_interrupt,
929 unimp_device_interrupt,
930 unimp_device_interrupt_ack,
931 vm_ioctl_callback,
932};
933
934
93fac324 935static void *
dec38dac 936vea_vm_create(const char *name,
93fac324 937 device *parent)
dec38dac
MM
938{
939 vm_device *vm = ZALLOC(vm_device);
940 unsigned_word addr;
941 unsigned nr_bytes;
942
943 /* extract out the stack parameters */
944 if (scand_uw_u(name, &addr, &nr_bytes) != 2)
945 error("vm_device_create() invalid vm device %s\n", name);
946 vm->stack_base = addr;
947 vm->stack_bound = addr + nr_bytes;
93fac324 948 return vm;
dec38dac
MM
949}
950
951
952\f
953/* Memory init device: memory@0x<addr>,<size>,<access>
954
955 This strange device is used create sections of memory */
956
93fac324
MM
957static void
958memory_init_callback(device *me,
dec38dac
MM
959 psim *system)
960{
961 unsigned_word addr;
962 unsigned nr_bytes;
963 unsigned access;
5b4d72dd 964 int nr_args;
dec38dac 965
93fac324 966 nr_args = scand_uw_u_u(device_name(me), &addr, &nr_bytes, &access);
5b4d72dd
MM
967 switch (nr_args) {
968 case 2:
969 access = access_read_write_exec;
970 break;
971 case 3:
972 break;
973 default:
93fac324 974 error("memory_init_callback() invalid memory device %s\n", device_name(me));
5b4d72dd
MM
975 break;
976 }
dec38dac 977
93fac324
MM
978 device_attach_address(device_parent(me),
979 device_name(me),
980 attach_raw_memory,
981 0 /*address space*/,
982 addr,
983 nr_bytes,
984 (access_type)access,
985 me);
dec38dac
MM
986}
987
988
989static device_callbacks const memory_callbacks = {
990 memory_init_callback,
991 unimp_device_attach_address,
992 unimp_device_detach_address,
993 unimp_device_io_read_buffer,
994 unimp_device_io_write_buffer,
995 unimp_device_dma_read_buffer,
996 unimp_device_dma_write_buffer,
997 unimp_device_attach_interrupt,
998 unimp_device_detach_interrupt,
999 unimp_device_interrupt,
1000 unimp_device_interrupt_ack,
1001 unimp_device_ioctl,
1002};
1003
1004
dec38dac
MM
1005\f
1006/* IOBUS device: iobus@<address>
1007
1008 Simple bus on which some IO devices live */
1009
93fac324
MM
1010static void
1011iobus_attach_address_callback(device *me,
dec38dac
MM
1012 const char *name,
1013 attach_type type,
5b4d72dd 1014 int space,
dec38dac
MM
1015 unsigned_word addr,
1016 unsigned nr_bytes,
1017 access_type access,
93fac324 1018 device *who) /*callback/default*/
dec38dac
MM
1019{
1020 unsigned_word iobus_addr;
1021 /* sanity check */
1022 if (type == attach_default)
1023 error("iobus_attach_address_callback() no default for %s/%s\n",
93fac324 1024 device_name(me), name);
5b4d72dd
MM
1025 if (space != 0)
1026 error("iobus_attach_address_callback() no space for %s/%s\n",
93fac324 1027 device_name(me), name);
dec38dac 1028 /* get the bus address */
93fac324 1029 if (scand_uw(device_name(me), &iobus_addr) != 1)
dec38dac 1030 error("iobus_attach_address_callback() invalid address for %s\n",
93fac324
MM
1031 device_name(me));
1032 device_attach_address(device_parent(me),
1033 device_name(me),
1034 type,
1035 0 /*space*/,
1036 iobus_addr + addr,
1037 nr_bytes,
1038 access,
1039 who);
dec38dac
MM
1040}
1041
1042
93fac324 1043STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
1044iobus_do_interrupt(event_queue *queue,
1045 void *data)
cb7a6892
MM
1046{
1047 cpu *target = (cpu*)data;
1048 /* try to interrupt the processor. If the attempt fails, try again
1049 on the next tick */
1050 if (!external_interrupt(target))
dec38dac 1051 event_queue_schedule(queue, 1, iobus_do_interrupt, target);
cb7a6892
MM
1052}
1053
dec38dac 1054
93fac324
MM
1055static void
1056iobus_interrupt_callback(device *me,
1057 device *who,
dec38dac
MM
1058 int interrupt_line,
1059 int interrupt_status,
1060 cpu *processor,
1061 unsigned_word cia)
cb7a6892
MM
1062{
1063 /* the interrupt controler can't interrupt a cpu at any time.
1064 Rather it must synchronize with the system clock before
1065 performing an interrupt on the given processor */
1066 psim *system = cpu_system(processor);
1067 cpu *target = psim_cpu(system, interrupt_status);
1068 if (target != NULL) {
1069 event_queue *events = cpu_event_queue(target);
dec38dac 1070 event_queue_schedule(events, 1, iobus_do_interrupt, target);
cb7a6892
MM
1071 }
1072}
1073
dec38dac
MM
1074
1075static device_callbacks const iobus_callbacks = {
1076 ignore_device_init,
1077 iobus_attach_address_callback,
1078 unimp_device_detach_address,
1079 unimp_device_io_read_buffer,
1080 unimp_device_io_write_buffer,
1081 unimp_device_dma_read_buffer,
1082 unimp_device_dma_write_buffer,
1083 unimp_device_attach_interrupt,
1084 unimp_device_detach_interrupt,
1085 iobus_interrupt_callback,
1086 unimp_device_interrupt_ack,
1087 unimp_device_ioctl,
cb7a6892
MM
1088};
1089
dec38dac
MM
1090
1091\f
1092/* FILE device: file@0x<address>,<file-name>
1093 (later - file@0x<address>,<size>,<file-offset>,<file-name>)
1094
1095 Specifies a file to read directly into memory starting at <address> */
1096
1097
93fac324
MM
1098static void
1099file_init_callback(device *me,
dec38dac 1100 psim *system)
cb7a6892 1101{
dec38dac 1102 unsigned_word addr;
1dc7c0ed
MM
1103 int count;
1104 char file_name[1024];
dec38dac 1105
93fac324 1106 if (scand_uw_c(device_name(me), &addr, file_name, sizeof(file_name)) != 2)
1dc7c0ed
MM
1107 error("devices/file - Usage: file@<address>,<file-name>\n");
1108
1109 /* load the file */
1110 count = dma_file(me, file_name, addr);
1111 if (count < 0)
93fac324 1112 error("device_table/%s - Problem loading file %s\n", device_name(me), file_name);
dec38dac 1113}
cb7a6892 1114
cb7a6892 1115
dec38dac
MM
1116static device_callbacks const file_callbacks = {
1117 file_init_callback,
1118 unimp_device_attach_address,
1119 unimp_device_detach_address,
1120 unimp_device_io_read_buffer,
1121 unimp_device_io_write_buffer,
1122 unimp_device_dma_read_buffer,
1123 unimp_device_dma_write_buffer,
1124 unimp_device_attach_interrupt,
1125 unimp_device_detach_interrupt,
1126 unimp_device_interrupt,
1127 unimp_device_interrupt_ack,
1128 unimp_device_ioctl,
1129};
1130
1131
93fac324
MM
1132\f
1133/* DATA device: data@<address>,<count>,<value>
1134
1135 Store <value> at <address> using <count> size transfer */
1136
1137static void
1138data_init_callback(device *me,
1139 psim *system)
1140{
1141 unsigned_word addr;
1142 unsigned count;
1143 unsigned value;
1144 union {
1145 unsigned_1 v1;
1146 unsigned_2 v2;
1147 unsigned_4 v4;
1148 unsigned_8 v8;
1149 } buf;
1150
1151 if (scand_uw_u_u(device_name(me), &addr, &count, &value) != 3)
1152 error("devices/data - Usage: data@<address>,<count>,<value>\n");
1153
1154 /* store the data value */
1155 switch (count) {
1156 case 1:
1157 buf.v1 = H2T_1(value);
1158 break;
1159 case 2:
1160 buf.v2 = H2T_2(value);
1161 break;
1162 case 4:
1163 buf.v4 = H2T_4(value);
1164 break;
1165 case 8:
1166 buf.v8 = H2T_8(value);
1167 break;
1168 }
1169 if (device_dma_write_buffer(device_parent(me),
1170 &buf,
1171 0 /*address-space*/,
1172 addr,
1173 count, /*nr-bytes*/
1174 1 /*violate ro*/) != count) {
1175 error("devices/%s - Problem storing 0x%x at 0x%lx\n",
1176 device_name(me), value, (long)addr);
1177 }
1178}
1179
1180
1181static device_callbacks const data_callbacks = {
1182 data_init_callback,
1183 unimp_device_attach_address,
1184 unimp_device_detach_address,
1185 unimp_device_io_read_buffer,
1186 unimp_device_io_write_buffer,
1187 unimp_device_dma_read_buffer,
1188 unimp_device_dma_write_buffer,
1189 unimp_device_attach_interrupt,
1190 unimp_device_detach_interrupt,
1191 unimp_device_interrupt,
1192 unimp_device_interrupt_ack,
1193 unimp_device_ioctl,
1194};
1195
1196
dec38dac 1197\f
1dc7c0ed 1198/* HTAB: htab@<address>,<nr_bytes>
93fac324
MM
1199 PTE: pte@<real-address>,<virtual-address>,<nr_bytes>,<wimg>,<pp>
1200 PTE: pte@<real-address>,<wimg>,<pp>,<binary>
dec38dac
MM
1201
1202 HTAB defines the location (in physical memory) of a HASH table.
1203 PTE (as a child of HTAB) defines a mapping that is to be entered
1204 into that table.
1205
1206 NB: All the work in this device is done during init by the PTE.
1207 The pte, looks up its parent to determine the address of the HTAB
1208 and then uses DMA calls to establish the required mapping. */
1209
1210
93fac324
MM
1211STATIC_INLINE_DEVICE_TABLE void
1212htab_decode_hash_table(device *parent,
1213 unsigned32 *htaborg,
1214 unsigned32 *htabmask)
1215{
1216 unsigned_word htab_ra;
1217 unsigned htab_nr_bytes;
1218 unsigned n;
1219 /* determine the location/size of the hash table */
1220 if (parent == NULL
1221 || strncmp(device_name(parent), "htab@", strlen("htab@")) != 0)
1222 error("devices/htab - missing htab device\n");
1223 if (scand_uw_u(device_name(parent), &htab_ra, &htab_nr_bytes) != 2)
1224 error("devices/%s - Usage: htab@<real-addr>,<nr_bytes>\n",
1225 device_name(parent));
1226 for (n = htab_nr_bytes; n > 1; n = n / 2) {
1227 if (n % 2 != 0)
1228 error("devices/%s - htab size 0x%x not a power of two\n",
1229 device_name(parent), htab_nr_bytes);
1230 }
1231 *htaborg = htab_ra;
1232 *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
1233 if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
1234 error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
1235 device_name(parent), *htaborg, *htabmask);
1236 }
979c3c25
MM
1237 DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
1238 (unsigned long)*htaborg, (unsigned long)*htabmask));
93fac324
MM
1239}
1240
1241
1242STATIC_INLINE void
1243htab_map_page(device *me,
1244 unsigned_word ra,
1245 unsigned64 va,
1246 unsigned wimg,
1247 unsigned pp,
1248 unsigned32 htaborg,
1249 unsigned32 htabmask)
1250{
1251 unsigned64 vpn = va << 12;
1252 unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
1253 unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
1254 unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
1255 ^ EXTRACTED32(page, 0, 15),
1256 7, 31-6);
1257 int h;
1258 for (h = 0; h < 2; h++) {
1259 unsigned32 pteg = (htaborg | (hash & htabmask));
1260 int pti;
1261 for (pti = 0; pti < 8; pti++, pteg += 8) {
979c3c25
MM
1262 unsigned32 current_target_pte0;
1263 unsigned32 current_pte0;
93fac324 1264 if (device_dma_read_buffer(device_parent(me),
979c3c25 1265 &current_target_pte0,
93fac324
MM
1266 0, /*space*/
1267 pteg,
979c3c25 1268 sizeof(current_target_pte0)) != 4)
93fac324
MM
1269 error("htab_init_callback() failed to read a pte at 0x%x\n",
1270 pteg);
979c3c25
MM
1271 current_pte0 = T2H_4(current_target_pte0);
1272 if (!MASKED32(current_pte0, 0, 0)) {
93fac324
MM
1273 /* empty pte fill it */
1274 unsigned32 pte0 = (MASK32(0, 0)
1275 | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
1276 | INSERTED32(h, 25, 25)
1277 | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31));
979c3c25 1278 unsigned32 target_pte0 = H2T_4(pte0);
93fac324
MM
1279 unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
1280 | INSERTED32(wimg, 25, 28)
1281 | INSERTED32(pp, 30, 31));
979c3c25 1282 unsigned32 target_pte1 = H2T_4(pte1);
93fac324 1283 if (device_dma_write_buffer(device_parent(me),
979c3c25 1284 &target_pte0,
93fac324
MM
1285 0, /*space*/
1286 pteg,
979c3c25 1287 sizeof(target_pte0),
93fac324
MM
1288 1/*ro?*/) != 4
1289 || device_dma_write_buffer(device_parent(me),
979c3c25 1290 &target_pte1,
93fac324
MM
1291 0, /*space*/
1292 pteg + 4,
979c3c25 1293 sizeof(target_pte1),
93fac324
MM
1294 1/*ro?*/) != 4)
1295 error("htab_init_callback() failed to write a pte a 0x%x\n",
1296 pteg);
1297 DTRACE(htab, ("map - va=0x%lx ra=0x%lx &pte0=0x%lx pte0=0x%lx pte1=0x%lx\n",
1298 (unsigned long)va, (unsigned long)ra,
1299 (unsigned long)pteg,
1300 (unsigned long)pte0, (unsigned long)pte1));
1301 return;
1302 }
1303 }
1304 /* re-hash */
1305 hash = MASKED32(~hash, 0, 18);
1306 }
1307}
1308
1309STATIC_INLINE_DEVICE_TABLE void
1310htab_map_region(device *me,
1311 unsigned_word pte_ra,
1312 unsigned_word pte_va,
1313 unsigned nr_bytes,
1314 unsigned wimg,
1315 unsigned pp,
1316 unsigned32 htaborg,
1317 unsigned32 htabmask)
1318{
1319 unsigned_word ra;
1320 unsigned64 va;
1321 /* go through all pages and create a pte for each */
1322 for (ra = pte_ra, va = (signed_word)pte_va;
1323 ra < pte_ra + nr_bytes;
1324 ra += 0x1000, va += 0x1000) {
1325 htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
1326 }
1327}
1328
1329typedef struct _htab_binary_sizes {
1330 unsigned_word text_ra;
1331 unsigned_word text_base;
1332 unsigned_word text_bound;
1333 unsigned_word data_ra;
1334 unsigned_word data_base;
1335 unsigned data_bound;
1336 device *me;
1337} htab_binary_sizes;
1338
1339STATIC_INLINE_DEVICE_TABLE void
1340htab_sum_binary(bfd *abfd,
1341 sec_ptr sec,
1342 PTR data)
1343{
1344 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
1345 unsigned_word size = bfd_get_section_size_before_reloc (sec);
1346 unsigned_word vma = bfd_get_section_vma (abfd, sec);
1347
1348 /* skip the section if no memory to allocate */
1349 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
1350 return;
1351
1352 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
1353 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
1354 if (sizes->text_bound < vma + size)
1355 sizes->text_bound = ALIGN_PAGE(vma + size);
1356 if (sizes->text_base > vma)
1357 sizes->text_base = FLOOR_PAGE(vma);
1358 }
1359 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
1360 || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
1361 if (sizes->data_bound < vma + size)
1362 sizes->data_bound = ALIGN_PAGE(vma + size);
1363 if (sizes->data_base > vma)
1364 sizes->data_base = FLOOR_PAGE(vma);
1365 }
1366}
1367
1368STATIC_INLINE_DEVICE_TABLE void
1369htab_dma_binary(bfd *abfd,
1370 sec_ptr sec,
1371 PTR data)
1372{
1373 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
1374 void *section_init;
1375 unsigned_word section_vma;
1376 unsigned_word section_size;
1377 unsigned_word section_ra;
1378 device *me = sizes->me;
1379
1380 /* skip the section if no memory to allocate */
1381 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
1382 return;
1383
1384 /* check/ignore any sections of size zero */
1385 section_size = bfd_get_section_size_before_reloc(sec);
1386 if (section_size == 0)
1387 return;
1388
1389 /* if nothing to load, ignore this one */
1390 if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
1391 return;
1392
1393 /* find where it is to go */
1394 section_vma = bfd_get_section_vma(abfd, sec);
1395 section_ra = 0;
1396 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
1397 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
1398 section_ra = (section_vma - sizes->text_base + sizes->text_ra);
1399 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
1400 section_ra = (section_vma - sizes->data_base + sizes->data_ra);
1401 else
1402 return; /* just ignore it */
1403
1404 DTRACE(htab,
1405 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
1406 bfd_get_section_name(abfd, sec),
1407 (long)section_vma,
1408 (long)section_size,
1409 (long)section_ra,
1410 (long)bfd_get_section_flags(abfd, sec),
1411 bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
1412 bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
1413 bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
1414 bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
1415 bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
1416 ));
1417
1418 /* dma in the sections data */
1419 section_init = zalloc(section_size);
1420 if (!bfd_get_section_contents(abfd,
1421 sec,
1422 section_init, 0,
1423 section_size)) {
1424 bfd_perror("devices/pte");
1425 error("devices/%s - no data loaded\n", device_name(me));
1426 }
1427 if (device_dma_write_buffer(device_parent(me),
1428 section_init,
1429 0 /*space*/,
1430 section_ra,
1431 section_size,
1432 1 /*violate_read_only*/)
1433 != section_size)
1434 error("devices/%s - broken dma transfer\n", device_name(me));
1435 zfree(section_init); /* only free if load */
1436}
1437
1438
1439STATIC_INLINE_DEVICE_TABLE void
1440htab_map_binary(device *me,
1441 unsigned_word ra,
1442 unsigned wimg,
1443 unsigned pp,
1444 char *file_name,
1445 unsigned32 htaborg,
1446 unsigned32 htabmask)
1447{
1448 htab_binary_sizes sizes;
1449 bfd *image;
1450 sizes.text_base = -1;
1451 sizes.data_base = -1;
1452 sizes.text_bound = 0;
1453 sizes.data_bound = 0;
1454 sizes.me = me;
1455
1456 /* open the file */
1457 image = bfd_openr(file_name, NULL);
1458 if (image == NULL) {
1459 bfd_perror("devices/pte");
1460 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
1461 }
1462
1463 /* check it is valid */
1464 if (!bfd_check_format(image, bfd_object)) {
1465 bfd_close(image);
1466 error("devices/%s - the file %s has an invalid binary format\n",
1467 device_name(me), file_name);
1468 }
1469
1470 /* determine the size of each of the files regions */
1471 bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
1472
1473 /* determine the real addresses of the sections */
1474 sizes.text_ra = ra;
1475 sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
1476 (sizes.text_bound - sizes.text_base));
1477
1478 DTRACE(htab, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
979c3c25
MM
1479 (unsigned long)sizes.text_base,
1480 (unsigned long)sizes.text_bound,
1481 (unsigned long)sizes.text_ra));
93fac324 1482 DTRACE(htab, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
979c3c25
MM
1483 (unsigned long)sizes.data_base,
1484 (unsigned long)sizes.data_bound,
1485 (unsigned long)sizes.data_ra));
93fac324
MM
1486
1487 /* set up virtual memory maps for each of the regions */
1488 htab_map_region(me, sizes.text_ra, sizes.text_base,
1489 sizes.text_bound - sizes.text_base,
1490 wimg, pp,
1491 htaborg, htabmask);
1492 htab_map_region(me, sizes.data_ra, sizes.data_base,
1493 sizes.data_bound - sizes.data_base,
1494 wimg, pp,
1495 htaborg, htabmask);
1496
1497 /* dma the sections into physical memory */
1498 bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
1499}
1500
1501static void
1502htab_init_callback(device *me,
dec38dac
MM
1503 psim *system)
1504{
1dc7c0ed
MM
1505 if (WITH_TARGET_WORD_BITSIZE != 32)
1506 error("devices/htab: only 32bit targets currently suported\n");
93fac324 1507
dec38dac 1508 /* only the pte does work */
93fac324
MM
1509 if (strncmp(device_name(me), "pte@", strlen("pte@")) == 0) {
1510 unsigned32 htaborg;
1511 unsigned32 htabmask;
1dc7c0ed
MM
1512 signed32 pte_va; /* so that 0xff...0 is make 0xffffff00 */
1513 unsigned32 pte_ra;
dec38dac 1514 unsigned pte_nr_bytes;
1dc7c0ed
MM
1515 unsigned pte_wimg;
1516 unsigned pte_pp;
93fac324 1517 char file_name[1024];
1dc7c0ed 1518
93fac324 1519 htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
1dc7c0ed 1520
93fac324
MM
1521 /* handle a normal mapping definition */
1522 if (scand_uw_uw_u_u_u(device_name(me), &pte_ra, &pte_va, &pte_nr_bytes,
1523 &pte_wimg, &pte_pp) == 5) {
979c3c25
MM
1524 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
1525 (unsigned long)pte_ra,
1526 (long)pte_wimg,
1527 (long)pte_pp,
1528 (unsigned long)pte_va,
1529 (long)pte_nr_bytes));
93fac324
MM
1530 htab_map_region(me, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
1531 htaborg, htabmask);
1532 }
1533 else if (scand_uw_u_u_c(device_name(me), &pte_ra, &pte_wimg, &pte_pp,
1534 file_name, sizeof(file_name)) == 4) {
979c3c25
MM
1535 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, binary=%s\n",
1536 (unsigned long)pte_ra,
1537 (unsigned long)pte_wimg,
1538 (long)pte_pp,
1539 file_name));
93fac324
MM
1540 htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
1541 htaborg, htabmask);
1542 }
1543 else {
1544 error("devices/%s - Usage: %s\nor\t%s\n",
1545 device_name(me),
1546 "pte@,<real-addr>,<virtual-addr>,<nr-bytes>,<wimg>,<pp>",
1547 "pte@<real-addr>,<wimg>,<pp>,<binary>");
1dc7c0ed 1548 }
dec38dac 1549 }
cb7a6892
MM
1550}
1551
dec38dac
MM
1552
1553static device_callbacks const htab_callbacks = {
1554 htab_init_callback,
1555 unimp_device_attach_address,
1556 unimp_device_detach_address,
1557 unimp_device_io_read_buffer,
1558 unimp_device_io_write_buffer,
93fac324
MM
1559 passthrough_device_dma_read_buffer,
1560 passthrough_device_dma_write_buffer,
dec38dac
MM
1561 unimp_device_attach_interrupt,
1562 unimp_device_detach_interrupt,
1563 unimp_device_interrupt,
1564 unimp_device_interrupt_ack,
1565 unimp_device_ioctl,
cb7a6892
MM
1566};
1567
1568
dec38dac
MM
1569\f
1570/* Simulator device: sim@0x<address>,<nr_bytes>
1571
1572 Eventually gives access to the hardware configuration. For
1573 instance, it could allow the setting (on the fly) of variables such
1574 as hardware floating-point or strict-alignment.
1575
1576 It's intended use is as part of testing the simulators
1577 functionality */
1578
1579static device_callbacks const sim_callbacks = {
1580 ignore_device_init,
1581 unimp_device_attach_address,
1582 unimp_device_detach_address,
1583 unimp_device_io_read_buffer,
1584 unimp_device_io_write_buffer,
1585 unimp_device_dma_read_buffer,
1586 unimp_device_dma_write_buffer,
1587 unimp_device_attach_interrupt,
1588 unimp_device_detach_interrupt,
1589 unimp_device_interrupt,
1590 unimp_device_interrupt_ack,
1591 unimp_device_ioctl,
1592};
cb7a6892
MM
1593
1594
dec38dac 1595\f
93fac324 1596/* Load device: binary
cb7a6892 1597
93fac324
MM
1598 Single property the name of which specifies the file (understood by
1599 BFD) that is to be DMAed into memory as part of init */
cb7a6892 1600
93fac324 1601STATIC_INLINE_DEVICE_TABLE void
5b4d72dd
MM
1602update_for_binary_section(bfd *abfd,
1603 asection *the_section,
1604 PTR obj)
cb7a6892 1605{
dec38dac
MM
1606 unsigned_word section_vma;
1607 unsigned_word section_size;
1608 access_type access;
1609 device *me = (device*)obj;
1610
1611 /* skip the section if no memory to allocate */
1612 if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
1613 return;
1614
1615 /* check/ignore any sections of size zero */
1616 section_size = bfd_get_section_size_before_reloc(the_section);
1617 if (section_size == 0)
1618 return;
1619
1620 /* find where it is to go */
1621 section_vma = bfd_get_section_vma(abfd, the_section);
1622
5b4d72dd 1623 DTRACE(binary,
c5addc19 1624 ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
5b4d72dd 1625 bfd_get_section_name(abfd, the_section),
c5addc19
MM
1626 (long)section_vma,
1627 (long)section_size,
1628 (long)bfd_get_section_flags(abfd, the_section),
5b4d72dd
MM
1629 bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
1630 bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
1631 bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
1632 bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
1633 bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
1634 ));
dec38dac
MM
1635
1636 /* determine the devices access */
1637 access = access_read;
1638 if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
1639 access |= access_exec;
1640 if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
1641 access |= access_write;
1642
1643 /* if a map, pass up a request to create the memory in core */
93fac324
MM
1644 if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
1645 device_attach_address(device_parent(me),
1646 device_name(me),
1647 attach_raw_memory,
1648 0 /*address space*/,
1649 section_vma,
1650 section_size,
1651 access,
1652 me);
dec38dac
MM
1653
1654 /* if a load dma in the required data */
1655 if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
1656 void *section_init = zalloc(section_size);
1657 if (!bfd_get_section_contents(abfd,
1658 the_section,
1659 section_init, 0,
1660 section_size)) {
1661 bfd_perror("core:load_section()");
1662 error("load of data failed");
1663 return;
1664 }
93fac324
MM
1665 if (device_dma_write_buffer(device_parent(me),
1666 section_init,
1667 0 /*space*/,
1668 section_vma,
1669 section_size,
1670 1 /*violate_read_only*/)
dec38dac 1671 != section_size)
93fac324 1672 error("data_init_callback() broken transfer for %s\n", device_name(me));
dec38dac
MM
1673 zfree(section_init); /* only free if load */
1674 }
cb7a6892
MM
1675}
1676
dec38dac 1677
93fac324
MM
1678static void
1679binary_init_callback(device *me,
dec38dac 1680 psim *system)
cb7a6892 1681{
93fac324 1682 const char *file_name;
dec38dac
MM
1683 bfd *image;
1684
93fac324
MM
1685
1686 /* get the property specifying the file name */
1687 file_name = device_find_next_property(me, NULL);
dec38dac
MM
1688
1689 /* open the file */
1690 image = bfd_openr(file_name, NULL);
1691 if (image == NULL) {
1dc7c0ed 1692 bfd_perror("devices/binary");
93fac324 1693 error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
dec38dac
MM
1694 }
1695
1696 /* check it is valid */
1697 if (!bfd_check_format(image, bfd_object)) {
dec38dac 1698 bfd_close(image);
93fac324
MM
1699 error("devices/%s - the file %s has an invalid binary format\n",
1700 device_name(me), file_name);
dec38dac
MM
1701 }
1702
1703 /* and the data sections */
1704 bfd_map_over_sections(image,
5b4d72dd 1705 update_for_binary_section,
dec38dac
MM
1706 (PTR)me);
1707
1708 bfd_close(image);
cb7a6892
MM
1709}
1710
1711
dec38dac
MM
1712static device_callbacks const binary_callbacks = {
1713 binary_init_callback,
1714 unimp_device_attach_address,
1715 unimp_device_detach_address,
1716 unimp_device_io_read_buffer,
1717 unimp_device_io_write_buffer,
1718 unimp_device_dma_read_buffer,
1719 unimp_device_dma_write_buffer,
1720 unimp_device_attach_interrupt,
1721 unimp_device_detach_interrupt,
1722 unimp_device_interrupt,
1723 unimp_device_interrupt_ack,
1724 unimp_device_ioctl,
cb7a6892
MM
1725};
1726
dec38dac
MM
1727
1728\f
1729/* Stack device: stack@<type>
1730
1731 Has a single IOCTL to create a stack frame of the specified type.
1732 If <type> is elf or xcoff then a corresponding stack is created.
1733 Any other value of type is ignored.
1734
1735 The IOCTL takes the additional arguments:
1736
1737 unsigned_word stack_end -- where the stack should come down from
1738 char **argv -- ...
1739 char **envp -- ...
1740
1741 */
1742
93fac324 1743STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
1744sizeof_argument_strings(char **arg)
1745{
1746 int sizeof_strings = 0;
1747
1748 /* robust */
1749 if (arg == NULL)
1750 return 0;
1751
1752 /* add up all the string sizes (padding as we go) */
1753 for (; *arg != NULL; arg++) {
1754 int len = strlen(*arg) + 1;
1755 sizeof_strings += ALIGN_8(len);
1756 }
1757
1758 return sizeof_strings;
1759}
1760
93fac324 1761STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
1762number_of_arguments(char **arg)
1763{
1764 int nr;
1765 if (arg == NULL)
1766 return 0;
1767 for (nr = 0; *arg != NULL; arg++, nr++);
1768 return nr;
1769}
1770
93fac324 1771STATIC_INLINE_DEVICE_TABLE int
dec38dac
MM
1772sizeof_arguments(char **arg)
1773{
1774 return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
1775}
1776
93fac324 1777STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
1778write_stack_arguments(psim *system,
1779 char **arg,
1780 unsigned_word start_block,
1781 unsigned_word end_block,
1782 unsigned_word start_arg,
1783 unsigned_word end_arg)
1784{
5b4d72dd 1785 DTRACE(stack,
c5addc19
MM
1786 ("write_stack_arguments(system=0x%lx, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
1787 (long)system, (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
dec38dac
MM
1788 if (arg == NULL)
1789 error("write_arguments: character array NULL\n");
1790 /* only copy in arguments, memory is already zero */
1791 for (; *arg != NULL; arg++) {
1792 int len = strlen(*arg)+1;
1793 unsigned_word target_start_block;
5b4d72dd 1794 DTRACE(stack,
c5addc19
MM
1795 ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
1796 "**arg", *arg, "start_block", (long)start_block,
1797 "len", (long)len, "start_arg", (long)start_arg));
dec38dac
MM
1798 if (psim_write_memory(system, 0, *arg,
1799 start_block, len,
1800 0/*violate_readonly*/) != len)
1801 error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
1802 *arg, start_block);
1803 target_start_block = H2T_word(start_block);
1804 if (psim_write_memory(system, 0, &target_start_block,
1805 start_arg, sizeof(target_start_block),
1806 0) != sizeof(target_start_block))
1807 error("write_stack_arguments() - write of *arg failed\n");
1808 start_block += ALIGN_8(len);
1809 start_arg += sizeof(start_block);
1810 }
1811 start_arg += sizeof(start_block); /*the null at the end*/
1812 if (start_block != end_block
1813 || ALIGN_8(start_arg) != end_arg)
1814 error("write_stack_arguments - possible corruption\n");
5b4d72dd
MM
1815 DTRACE(stack,
1816 ("write_stack_arguments() = void\n"));
dec38dac
MM
1817}
1818
93fac324 1819STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
1820create_elf_stack_frame(psim *system,
1821 unsigned_word bottom_of_stack,
1822 char **argv,
1823 char **envp)
1824{
1825 /* fixme - this is over aligned */
1826
1827 /* information block */
1828 const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
1829 const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
1830 const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
1831 const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
1832
1833 /* auxiliary vector - contains only one entry */
1834 const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
1835 const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
1836
1837 /* environment points (including null sentinal) */
1838 const unsigned sizeof_envp = sizeof_arguments(envp);
1839 const unsigned_word start_envp = start_aux - sizeof_envp;
1840
1841 /* argument pointers (including null sentinal) */
1842 const int argc = number_of_arguments(argv);
1843 const unsigned sizeof_argv = sizeof_arguments(argv);
1844 const unsigned_word start_argv = start_envp - sizeof_argv;
1845
1846 /* link register save address - alligned to a 16byte boundary */
1847 const unsigned_word top_of_stack = ((start_argv
1848 - 2 * sizeof(unsigned_word))
1849 & ~0xf);
1850
1851 /* install arguments on stack */
1852 write_stack_arguments(system, envp,
1853 start_envp_block, bottom_of_stack,
1854 start_envp, start_aux);
1855 write_stack_arguments(system, argv,
1856 start_argv_block, start_envp_block,
1857 start_argv, start_envp);
1858
1859 /* set up the registers */
1860 psim_write_register(system, -1,
1861 &top_of_stack, "sp", cooked_transfer);
1862 psim_write_register(system, -1,
1863 &argc, "r3", cooked_transfer);
1864 psim_write_register(system, -1,
1865 &start_argv, "r4", cooked_transfer);
1866 psim_write_register(system, -1,
1867 &start_envp, "r5", cooked_transfer);
1868 psim_write_register(system, -1,
1869 &start_aux, "r6", cooked_transfer);
1870}
1871
93fac324 1872STATIC_INLINE_DEVICE_TABLE void
dec38dac
MM
1873create_aix_stack_frame(psim *system,
1874 unsigned_word bottom_of_stack,
1875 char **argv,
1876 char **envp)
cb7a6892 1877{
dec38dac
MM
1878 unsigned_word core_envp;
1879 unsigned_word core_argv;
1880 unsigned_word core_argc;
1881 unsigned_word core_aux;
1882 unsigned_word top_of_stack;
1883
1884 /* cheat - create an elf stack frame */
1885 create_elf_stack_frame(system, bottom_of_stack, argv, envp);
1886
1887 /* extract argument addresses from registers */
1888 psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
1889 psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
1890 psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
1891 psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
1892 psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
1893
1894 /* extract arguments from registers */
1895 error("create_aix_stack_frame() - what happens next?\n");
1896}
1897
1898
cb7a6892 1899
8e20a3ac 1900static void
93fac324 1901stack_ioctl_callback(device *me,
dec38dac
MM
1902 psim *system,
1903 cpu *processor,
1904 unsigned_word cia,
93fac324 1905 va_list ap)
dec38dac 1906{
dec38dac 1907 unsigned_word stack_pointer;
93fac324 1908 const char *stack_type;
dec38dac
MM
1909 char **argv;
1910 char **envp;
dec38dac
MM
1911 stack_pointer = va_arg(ap, unsigned_word);
1912 argv = va_arg(ap, char **);
1913 envp = va_arg(ap, char **);
5b4d72dd 1914 DTRACE(stack,
c5addc19 1915 ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
93fac324
MM
1916 (long)me, device_name(me), (long)system, (long)processor, (long)cia, (long)argv, (long)envp));
1917 stack_type = device_find_next_property(me, NULL);
1918 if (stack_type != NULL) {
1919 if (strcmp(stack_type, "elf") == 0)
1920 create_elf_stack_frame(system, stack_pointer, argv, envp);
1921 else if (strcmp(stack_type, "xcoff") == 0)
1922 create_aix_stack_frame(system, stack_pointer, argv, envp);
1923 }
5b4d72dd
MM
1924 DTRACE(stack,
1925 ("stack_ioctl_callback() = void\n"));
cb7a6892
MM
1926}
1927
93fac324
MM
1928\f
1929
dec38dac
MM
1930
1931static device_callbacks const stack_callbacks = {
1932 ignore_device_init,
1933 unimp_device_attach_address,
1934 unimp_device_detach_address,
1935 unimp_device_io_read_buffer,
1936 unimp_device_io_write_buffer,
1937 unimp_device_dma_read_buffer,
1938 unimp_device_dma_write_buffer,
1939 unimp_device_attach_interrupt,
1940 unimp_device_detach_interrupt,
1941 unimp_device_interrupt,
1942 unimp_device_interrupt_ack,
1943 stack_ioctl_callback,
cb7a6892
MM
1944};
1945
1946
dec38dac 1947\f
93fac324
MM
1948device_descriptor device_table[] = {
1949 { "console", console_create, &console_callbacks },
5b4d72dd 1950 { "memory", NULL, &memory_callbacks },
93fac324 1951 { "vm", vea_vm_create, &vm_callbacks },
dec38dac
MM
1952 { "halt", NULL, &halt_callbacks },
1953 { "icu", NULL, &icu_callbacks },
1954 { "register", NULL, &register_callbacks },
1955 { "iobus", NULL, &iobus_callbacks },
1956 { "file", NULL, &file_callbacks },
93fac324 1957 { "data", NULL, &data_callbacks },
dec38dac
MM
1958 { "htab", NULL, &htab_callbacks },
1959 { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
1960 { "stack", NULL, &stack_callbacks },
1961 { "sim", NULL, &sim_callbacks },
1962 { "load-binary", NULL, &binary_callbacks },
1963 { "map-binary", NULL, &binary_callbacks },
93fac324
MM
1964 { "options", NULL, &passthrough_callbacks },
1965 { "init", NULL, &passthrough_callbacks },
1966 { "chosen", NULL, &passthrough_callbacks },
dec38dac 1967 { NULL },
cb7a6892
MM
1968};
1969
93fac324 1970#endif /* _DEVICE_TABLE_C_ */
This page took 0.127864 seconds and 4 git commands to generate.