update from Andrew

This commit is contained in:
Michael Meissner 1996-04-17 20:09:36 +00:00
parent 221d1e19de
commit d4d3c7adbb
11 changed files with 4496 additions and 0 deletions

View File

@ -28,6 +28,7 @@ BUGS
COPYING
COPYING.LIB
ChangeLog
ChangeLog.00
INSTALL
Makefile.in
NOTES
@ -67,6 +68,18 @@ events.c
events.h
filter_filename.c
filter_filename.h
hw_com.c
hw_cpu.c
hw_cpu.h
hw_eeprom.c
hw_iobus.c
hw_memory.c
hw_nvram.c
hw_pal.c
hw_pci_ide.c
hw_phb.c
hw_phb.h
hw_pic.c
idecode_branch.h
idecode_expression.h
idecode_fields.h
@ -98,6 +111,7 @@ ppc-spr-table
ppc.mt
psim.c
psim.h
psim.texinfo
registers.c
registers.h
sim-endian-n.h

2455
sim/ppc/ChangeLog.00 Normal file

File diff suppressed because it is too large Load Diff

23
sim/ppc/hw_com.c Normal file
View File

@ -0,0 +1,23 @@
static unsigned
hw_com_io_write_buffer_callback(device *me,
const void *source,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
hw_com_device *hw_com = (hw_com_device*)device_data(me);
unsigned_1 val = *(unsigned_1*)source;
switch ((int)addr & hw_com_offset_mask) {
default:
error("hw_com_write_callback() internal error\n");
}
return nr_bytes;
}
#endif /* _HW_COM_ */

145
sim/ppc/hw_cpu.c Normal file
View File

@ -0,0 +1,145 @@
/* This file is part of the program psim.
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HW_CPU_C_
#define _HW_CPU_C_
#ifndef STATIC_INLINE_HW_CPU
#define STATIC_INLINE_HW_CPU STATIC_INLINE
#endif
#include "device_table.h"
#include "hw_cpu.h"
#include "interrupts.h"
#include "cpu.h"
/* CPU (HW) - Interface to a Processor
Description:
The CPU device provides the connection between the interrupt net
(linking the devices and the interrupt controller) and the
simulated model of each processor. This device contains interrupt
ports that correspond directly to the external interrupt stimulus
that can be sent to a given processor. Sending an interrupt to one
of the ports results in an interrupt being delivered to the
corresponding processor.
Typically, an interrupt controller would have its inputs connected
to device interrupt sources and its outputs (sreset, int, et.al.)
connected to this device.
Properties:
cpu-nr = <integer>. Specify the processor (1..N) that this cpu
device node should control. */
typedef struct _hw_cpu_device {
int cpu_nr;
cpu *processor;
} hw_cpu_device;
static const device_interrupt_port_descriptor hw_cpu_interrupt_ports[] = {
{ "hreset", hw_cpu_hard_reset },
{ "sreset", hw_cpu_soft_reset },
{ "int", hw_cpu_external_interrupt },
{ "mci", hw_cpu_machine_check_interrupt },
{ "smi", hw_cpu_system_management_interrupt },
{ NULL }
};
static void *
hw_cpu_create(const char *name,
const device_unit *unit_address,
const char *args,
device *parent)
{
hw_cpu_device *hw_cpu = ZALLOC(hw_cpu_device);
return hw_cpu;
}
/* during address initialization ensure that any missing cpu
properties are added to this devices node */
static void
hw_cpu_init_address(device *me)
{
hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
/* populate the node with properties */
/* clear our data */
memset(hw_cpu, 0x0, sizeof(hw_cpu_device));
hw_cpu->cpu_nr = device_find_integer_property(me, "cpu-nr");
hw_cpu->processor = psim_cpu(device_system(me), hw_cpu->cpu_nr);
}
/* Take the interrupt and synchronize its delivery with the clock. If
we've not yet scheduled an interrupt for the next clock tick, take
the oportunity to do it now */
static void
hw_cpu_interrupt_event(device *me,
int my_port,
device *source,
int source_port,
int level,
cpu *processor,
unsigned_word cia)
{
hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
if (my_port < 0 || my_port >= hw_cpu_nr_interrupt_ports)
error("hw_cpu_interrupt_event_callback: interrupt port out of range %d\n",
my_port);
switch (my_port) {
/*case hw_cpu_hard_reset:*/
/*case hw_cpu_soft_reset:*/
case hw_cpu_external_interrupt:
external_interrupt(hw_cpu->processor, level);
break;
/*case hw_cpu_machine_check_interrupt:*/
default:
error("hw_cpu_deliver_interrupt: unimplemented interrupt port %d\n",
my_port);
break;
}
}
static device_callbacks const hw_cpu_callbacks = {
{ hw_cpu_init_address, }, /* init */
{ NULL, }, /* address */
{ NULL, }, /* io */
{ NULL, }, /* DMA */
{ hw_cpu_interrupt_event, NULL, hw_cpu_interrupt_ports }, /* interrupts */
{ NULL, NULL, },
};
const device_descriptor hw_cpu_device_descriptor[] = {
{ "hw-cpu", hw_cpu_create, &hw_cpu_callbacks },
{ "cpu", hw_cpu_create, &hw_cpu_callbacks },
{ NULL, },
};
#endif /* _HW_CPU_C_ */

34
sim/ppc/hw_cpu.h Normal file
View File

@ -0,0 +1,34 @@
/* This file is part of the program psim.
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HW_CPU_H_
#define _HW_CPU_H_
enum {
hw_cpu_hard_reset,
hw_cpu_soft_reset,
hw_cpu_external_interrupt,
hw_cpu_machine_check_interrupt,
hw_cpu_system_management_interrupt,
hw_cpu_nr_interrupt_ports
};
#endif /* _HW_CPU_H_ */

289
sim/ppc/hw_eeprom.c Normal file
View File

@ -0,0 +1,289 @@
/* This file is part of the program psim.
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HW_EEPROM_C_
#define _HW_EEPROM_C_
#ifndef STATIC_INLINE_HW_EEPROM
#define STATIC_INLINE_HW_EEPROM STATIC_INLINE
#endif
#include "device_table.h"
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
/* EEPROM - electricaly erasable programable memory
Description:
This device implements a small byte addressable EEPROM.
Programming is performed using the same write sequences as used by
modern EEPROM components. Writes occure in real time, the device
returning a progress value until the programing has been completed.
Properties:
reg = <address> <size>. Determine where the device lives in the
parents address space.
nr-sectors = <integer>. When erasing an entire sector is cleared
at a time. This specifies the number of sectors in the EEPROM
component.
byte-write-delay = <integer>. Number of clock ticks before the
programming of a single byte completes.
sector-start-delay = <integer>. When erasing sectors, the number
of clock ticks after the sector has been specified and the actual
erase process commences.
erase-delay = <intger>. Number of clock ticks before an erase
program completes. */
typedef enum {
read_reset,
write_nr_2,
write_nr_3,
write_nr_4,
write_nr_5,
write_nr_6,
byte_program,
byte_programming,
chip_erase, chip_erasing,
sector_erase, sector_erasing,
sector_erase_suspend,
sector_erase_resume,
} eeprom_states;
typedef struct _eeprom_device {
unsigned8 *memory;
unsigned sizeof_memory;
unsigned sector_size;
unsigned nr_sectors;
unsigned byte_write_delay;
unsigned sector_start_delay;
unsigned erase_delay;
signed64 programme_start_time;
unsigned program_byte_address;
eeprom_states state;
} eeprom_device;
static void *
eeprom_create(const char *name,
const device_unit *unit_address,
const char *args,
device *parent)
{
eeprom_device *eeprom = ZALLOC(eeprom_device);
return eeprom;
}
typedef struct _eeprom_reg_spec {
unsigned32 base;
unsigned32 size;
} eeprom_reg_spec;
static void
eeprom_init_address(device *me,
psim *system)
{
eeprom_device *eeprom = (eeprom_device*)device_data(me);
const device_property *reg = device_find_array_property(me, "reg");
const eeprom_reg_spec *spec = reg->array;
int nr_entries = reg->sizeof_array / sizeof(*spec);
if ((reg->sizeof_array % sizeof(*spec)) != 0)
error("devices/%s reg property of incorrect size\n", device_name(me));
if (nr_entries > 1)
error("devices/%s reg property contains multiple specs\n",
device_name(me));
/* initialize the eeprom */
if (eeprom->memory == NULL) {
eeprom->sizeof_memory = BE2H_4(spec->size);
eeprom->memory = zalloc(eeprom->sizeof_memory);
}
else
memset(eeprom->memory, eeprom->sizeof_memory, 0);
/* figure out the sectors in the eeprom */
eeprom->nr_sectors = device_find_integer_property(me, "nr-sectors");
eeprom->sector_size = eeprom->sizeof_memory / eeprom->nr_sectors;
if (eeprom->sector_size * eeprom->nr_sectors != eeprom->sizeof_memory)
error("device/%s nr-sectors does not evenly divide eeprom\n",
device_name(me));
/* timing */
eeprom->byte_write_delay = device_find_integer_property(me, "byte-write-delay");
eeprom->sector_start_delay = device_find_integer_property(me, "sector-start-delay");
eeprom->erase_delay = device_find_integer_property(me, "erase-delay");
device_attach_address(device_parent(me),
device_name(me),
attach_callback,
0 /*address space*/,
BE2H_4(spec->base),
eeprom->sizeof_memory,
access_read_write_exec,
me);
}
static unsigned
eeprom_io_read_buffer(device *me,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
eeprom_device *eeprom = (eeprom_device*)device_data(me);
int i;
for (i = 0; i < nr_bytes; i++) {
unsigned_word address = (addr + nr_bytes) % eeprom->sizeof_memory;
eeprom->memory[address] = eeprom_io_read_byte(address);
}
return nr_bytes;
}
static void
eeprom_io_write_byte()
{
switch (state) {
case read_reset:
if (address == 0x5555 && data = 0xaa)
state = first_write;
else
state = read_reset;
break;
case first_write:
if (address == 0x2aaa && data == 0x55)
state = second_write;
else
state = read_reset; /* issue warning */
break;
case second_write:
if (address == 0x5555 && data == 0xf0)
state = read_reset;
else if (address == 0x5555 && data == 0x90)
state = auto_select;
else if (address == 0x5555 && data == 0xa0)
state = byte_program;
else if (address == 0x5555 && data == 0x80)
state = third_write;
else
state = read_reset;
break;
case fourth_write:
if (address == 0x5555 && data == 0xaa)
state = fith_write;
else
state = read_reset;
break;
case fith_write:
if (address == 0x2aaa && data == 0x55)
state = sixth_write;
else
state = read_reset;
break;
case sixth_write:
if (address == 0x5555 && data == 0x10)
state = chip_erase;
else
sector_erase();
break;
case auto_select:
if (data == 0xf0)
state = read_reset;
else if (address == 0x5555 && data == 0xaa)
state = second_write;
else
state = read_reset; /* issue warning */
break;
case sector_erase:
if (data == 0xb0)
state = sector_erase_suspend;
else
state = sector_erase; /* ignore */
break;
case sector_erase_suspend:
if (data == 0x30)
state = sector_erase;
else
state = sector_erase_suspend; /* ignore */
break;
case byte_program:
/* perform the byte program */
program_address = address;
program_start = some_time();
toggle = 0;
/* but only make things `0' and never 1 */
byte[address] = data;
state = byte_programming;
break;
case byte_programming:
if (finished)
state = read_reset;
else
state = byte_programming;
break;
}
}
static unsigned
eeprom_io_write_buffer(device *me,
const void *source,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
eeprom_device *eeprom = (eeprom_device*)device_data(me);
int i;
for (i = 0; i < nr_bytes; i++) {
unsigned_word address = (addr + nr_bytes) % eeprom->sizeof_memory;
eeprom_io_read_byte(address, eeprom->memory[address]);
}
return nr_bytes;
}
static device_callbacks const eeprom_callbacks = {
{ eeprom_init_address, },
{ NULL, }, /* address */
{ eeprom_io_read_buffer, eeprom_io_write_buffer }, /* IO */
};
const device_descriptor eeprom_device_descriptor[] = {
{ "eeprom", eeprom_create, &eeprom_callbacks },
{ NULL },
};
#endif /* _HW_EEPROM_C_ */

98
sim/ppc/hw_iobus.c Normal file
View File

@ -0,0 +1,98 @@
/* This file is part of the program psim.
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HW_IOBUS_C_
#define _HW_IOBUS_C_
#ifndef STATIC_INLINE_HW_IOBUS
#define STATIC_INLINE_HW_IOBUS STATIC_INLINE
#endif
#include "device_table.h"
/* Device:
iobus@<address> - bus for attaching devices
Description:
IOBUS provides a simple `local' bus for attaching (hanging)
programmed IO devices from. All child devices are mapped into this
devices parent address space (after adjusting for the iobus's base
address).
Properties:
None.
*/
static void
hw_iobus_attach_address_callback(device *me,
const char *name,
attach_type type,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
device *who) /*callback/default*/
{
unsigned_word hw_iobus_addr;
/* sanity check */
if (space != 0)
error("hw_iobus_attach_address_callback() no space for %s/%s\n",
device_name(me), name);
/* get the bus address */
if (device_unit_address(me)->nr_cells != 1)
error("hw_iobus_attach_address_callback() invalid address for %s\n",
device_name(me));
hw_iobus_addr = device_unit_address(me)->cells[0];
device_attach_address(device_parent(me),
device_name(me),
type,
0 /*space*/,
hw_iobus_addr + addr,
nr_bytes,
access,
who);
}
static device_callbacks const hw_iobus_callbacks = {
{ NULL, },
{ hw_iobus_attach_address_callback, },
{ NULL, }, /* IO */
{ NULL, }, /* DMA */
{ NULL, }, /* interrupt */
{ generic_device_unit_decode,
generic_device_unit_encode, }
};
const device_descriptor hw_iobus_device_descriptor[] = {
{ "iobus", NULL, &hw_iobus_callbacks },
{ NULL, },
};
#endif /* _HW_IOBUS_ */

234
sim/ppc/hw_nvram.c Normal file
View File

@ -0,0 +1,234 @@
/* This file is part of the program psim.
Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HW_NVRAM_C_
#define _HW_NVRAM_C_
#ifndef STATIC_INLINE_HW_NVRAM
#define STATIC_INLINE_HW_NVRAM STATIC_INLINE
#endif
#include "device_table.h"
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
/* NVRAM - non-volatile memory with optional clock.
Description:
This device implements a small byte addressable non-volatile memory
component. The component may include an optional real-time clock
at its upper addresses.
Properties:
reg = <address> <size>. Determine where the device lives in the
parents address space.
timezone = <integer>. Adjustment to current host's GMT (in secons)
that should be applied when updating the NVRAM's clock. */
typedef struct _hw_nvram_device {
unsigned8 *memory;
unsigned sizeof_memory;
#ifdef HAVE_TIME_H
time_t host_time;
#else
long host_time;
#endif
unsigned timezone;
/* useful */
unsigned addr_year;
unsigned addr_month;
unsigned addr_date;
unsigned addr_day;
unsigned addr_hour;
unsigned addr_minutes;
unsigned addr_seconds;
unsigned addr_control;
} hw_nvram_device;
static void *
hw_nvram_create(const char *name,
const device_unit *unit_address,
const char *args,
device *parent)
{
hw_nvram_device *hw_nvram = ZALLOC(hw_nvram_device);
return hw_nvram;
}
typedef struct _hw_nvram_reg_spec {
unsigned32 base;
unsigned32 size;
} hw_nvram_reg_spec;
static void
hw_nvram_init_address(device *me)
{
hw_nvram_device *hw_nvram = (hw_nvram_device*)device_data(me);
const device_property *reg = device_find_array_property(me, "reg");
const hw_nvram_reg_spec *spec = reg->array;
int nr_entries = reg->sizeof_array / sizeof(*spec);
if ((reg->sizeof_array % sizeof(*spec)) != 0)
error("devices/%s reg property of incorrect size\n", device_name(me));
if (nr_entries > 1)
error("devices/%s reg property contains multiple specs\n",
device_name(me));
/* initialize the hw_nvram */
if (hw_nvram->memory == NULL) {
hw_nvram->sizeof_memory = BE2H_4(spec->size);
hw_nvram->memory = zalloc(hw_nvram->sizeof_memory);
}
else
memset(hw_nvram->memory, hw_nvram->sizeof_memory, 0);
hw_nvram->timezone = device_find_integer_property(me, "timezone");
hw_nvram->addr_year = hw_nvram->sizeof_memory - 1;
hw_nvram->addr_month = hw_nvram->sizeof_memory - 2;
hw_nvram->addr_date = hw_nvram->sizeof_memory - 3;
hw_nvram->addr_day = hw_nvram->sizeof_memory - 4;
hw_nvram->addr_hour = hw_nvram->sizeof_memory - 5;
hw_nvram->addr_minutes = hw_nvram->sizeof_memory - 6;
hw_nvram->addr_seconds = hw_nvram->sizeof_memory - 7;
hw_nvram->addr_control = hw_nvram->sizeof_memory - 8;
device_attach_address(device_parent(me),
device_name(me),
attach_callback,
0 /*address space*/,
BE2H_4(spec->base),
hw_nvram->sizeof_memory,
access_read_write_exec,
me);
}
static int
hw_nvram_bcd(int val)
{
return ((val / 10) << 4) + (val % 10);
}
/* If reached an update interval and allowed, update the clock within
the hw_nvram. While this function could be implemented using events
it isn't on the assumption that the HW_NVRAM will hardly ever be
referenced and hence there is little need in keeping the clock
continually up-to-date */
static void
hw_nvram_update_clock(hw_nvram_device *hw_nvram, cpu *processor)
{
#ifdef HAVE_TIME_H
if (!(hw_nvram->memory[hw_nvram->addr_control] & 0xc0)) {
time_t host_time = time(NULL);
if (hw_nvram->host_time != host_time) {
time_t nvtime = hw_nvram->host_time + hw_nvram->timezone;
struct tm *clock = gmtime(&nvtime);
hw_nvram->host_time = host_time;
hw_nvram->memory[hw_nvram->addr_year] = hw_nvram_bcd(clock->tm_year);
hw_nvram->memory[hw_nvram->addr_month] = hw_nvram_bcd(clock->tm_mon + 1);
hw_nvram->memory[hw_nvram->addr_date] = hw_nvram_bcd(clock->tm_mday);
hw_nvram->memory[hw_nvram->addr_day] = hw_nvram_bcd(clock->tm_wday + 1);
hw_nvram->memory[hw_nvram->addr_hour] = hw_nvram_bcd(clock->tm_hour);
hw_nvram->memory[hw_nvram->addr_minutes] = hw_nvram_bcd(clock->tm_min);
hw_nvram->memory[hw_nvram->addr_seconds] = hw_nvram_bcd(clock->tm_sec);
}
}
#else
error("fixme - where do I find out GMT\n");
#endif
}
static void
hw_nvram_set_clock(hw_nvram_device *hw_nvram, cpu *processor)
{
error ("fixme - how do I set the localtime\n");
}
static unsigned
hw_nvram_io_read_buffer(device *me,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
int i;
hw_nvram_device *hw_nvram = (hw_nvram_device*)device_data(me);
for (i = 0; i < nr_bytes; i++) {
unsigned address = (addr + i) % hw_nvram->sizeof_memory;
unsigned8 data = hw_nvram->memory[address];
hw_nvram_update_clock(hw_nvram, processor);
((unsigned8*)dest)[i] = data;
}
return nr_bytes;
}
static unsigned
hw_nvram_io_write_buffer(device *me,
const void *source,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
int i;
hw_nvram_device *hw_nvram = (hw_nvram_device*)device_data(me);
for (i = 0; i < nr_bytes; i++) {
unsigned address = (addr + i) % hw_nvram->sizeof_memory;
unsigned8 data = ((unsigned8*)source)[i];
if (address == hw_nvram->addr_control
&& (data & 0x80) == 0
&& (hw_nvram->memory[address] & 0x80) == 0x80)
hw_nvram_set_clock(hw_nvram, processor);
else
hw_nvram_update_clock(hw_nvram, processor);
hw_nvram->memory[address] = data;
}
return nr_bytes;
}
static device_callbacks const hw_nvram_callbacks = {
{ hw_nvram_init_address, },
{ NULL, }, /* address */
{ hw_nvram_io_read_buffer, hw_nvram_io_write_buffer }, /* IO */
};
const device_descriptor hw_nvram_device_descriptor[] = {
{ "nvram", hw_nvram_create, &hw_nvram_callbacks },
{ NULL },
};
#endif /* _HW_NVRAM_C_ */

1
sim/ppc/hw_pci_ide.c Normal file
View File

@ -0,0 +1 @@
something goes here

98
sim/ppc/hw_pic.c Normal file
View File

@ -0,0 +1,98 @@
/* ICU device: icu@<address>
<address> : read - processor nr
<address> : write - interrupt processor nr
<address> + 4 : read - nr processors
Single byte registers that control a simple ICU.
Illustrates passing of events to parent device. Passing of
interrupts to an interrupt destination. */
static unsigned
icu_io_read_buffer_callback(device *me,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
memset(dest, 0, nr_bytes);
switch (addr & 4) {
case 0:
*(unsigned_1*)dest = cpu_nr(processor);
break;
case 4:
*(unsigned_1*)dest =
device_find_integer_property(me, "/openprom/options/smp");
break;
}
return nr_bytes;
}
static unsigned
icu_io_write_buffer_callback(device *me,
const void *source,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
unsigned_1 val = H2T_1(*(unsigned_1*)source);
/* tell the parent device that the interrupt lines have changed.
For this fake ICU. The interrupt lines just indicate the cpu to
interrupt next */
device_interrupt_event(me,
val, /*my_port*/
val, /*val*/
processor, cia);
return nr_bytes;
}
static void
icu_do_interrupt(event_queue *queue,
void *data)
{
cpu *target = (cpu*)data;
/* try to interrupt the processor. If the attempt fails, try again
on the next tick */
if (!external_interrupt(target))
event_queue_schedule(queue, 1, icu_do_interrupt, target);
}
static void
icu_interrupt_event_callback(device *me,
int my_port,
device *source,
int source_port,
int level,
cpu *processor,
unsigned_word cia)
{
/* the interrupt controller can't interrupt a cpu at any time.
Rather it must synchronize with the system clock before
performing an interrupt on the given processor */
psim *system = cpu_system(processor);
cpu *target = psim_cpu(system, my_port);
if (target != NULL) {
event_queue *events = cpu_event_queue(target);
event_queue_schedule(events, 1, icu_do_interrupt, target);
}
}
static device_callbacks const icu_callbacks = {
{ generic_device_init_address, },
{ NULL, }, /* address */
{ icu_io_read_buffer_callback,
icu_io_write_buffer_callback, },
{ NULL, }, /* DMA */
{ icu_interrupt_event_callback, },
{ NULL, }, /* unit */
};

1105
sim/ppc/psim.texinfo Normal file

File diff suppressed because it is too large Load Diff