#ifndef _HW_PAL_C_
#define _HW_PAL_C_
#ifndef STATIC_INLINE_HW_PAL
#define STATIC_INLINE_HW_PAL STATIC_INLINE
#endif
#include "device_table.h"
#include "cpu.h"
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
enum {
hw_pal_reset_register = 0x0,
hw_pal_cpu_nr_register = 0x4,
hw_pal_int_register = 0x8,
hw_pal_nr_cpu_register = 0xa,
hw_pal_read_fifo = 0x10,
hw_pal_read_status = 0x14,
hw_pal_write_fifo = 0x18,
hw_pal_write_status = 0x1a,
hw_pal_address_mask = 0x1f,
};
typedef struct _hw_pal_console_buffer {
char buffer;
int status;
} hw_pal_console_buffer;
typedef struct _hw_pal_device {
hw_pal_console_buffer input;
hw_pal_console_buffer output;
device *disk;
} hw_pal_device;
static void
scan_hw_pal(hw_pal_device *hw_pal)
{
char c;
int count;
count = sim_io_read_stdin(&c, sizeof(c));
switch (count) {
case sim_io_not_ready:
case sim_io_eof:
hw_pal->input.buffer = 0;
hw_pal->input.status = 0;
break;
default:
hw_pal->input.buffer = c;
hw_pal->input.status = 1;
}
}
static void
write_hw_pal(hw_pal_device *hw_pal,
char val)
{
sim_io_write_stdout(&val, 1);
hw_pal->output.buffer = val;
hw_pal->output.status = 1;
}
static unsigned
hw_pal_io_read_buffer_callback(device *me,
void *dest,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
unsigned_1 val;
switch (addr & hw_pal_address_mask) {
case hw_pal_cpu_nr_register:
val = cpu_nr(processor);
DTRACE(pal, ("read - cpu-nr %d\n", val));
break;
case hw_pal_nr_cpu_register:
val = tree_find_integer_property(me, "/openprom/options/smp");
DTRACE(pal, ("read - nr-cpu %d\n", val));
break;
case hw_pal_read_fifo:
val = hw_pal->input.buffer;
DTRACE(pal, ("read - input-fifo %d\n", val));
break;
case hw_pal_read_status:
scan_hw_pal(hw_pal);
val = hw_pal->input.status;
DTRACE(pal, ("read - input-status %d\n", val));
break;
case hw_pal_write_fifo:
val = hw_pal->output.buffer;
DTRACE(pal, ("read - output-fifo %d\n", val));
break;
case hw_pal_write_status:
val = hw_pal->output.status;
DTRACE(pal, ("read - output-status %d\n", val));
break;
default:
val = 0;
DTRACE(pal, ("read - ???\n"));
}
memset(dest, 0, nr_bytes);
*(unsigned_1*)dest = val;
return nr_bytes;
}
static unsigned
hw_pal_io_write_buffer_callback(device *me,
const void *source,
int space,
unsigned_word addr,
unsigned nr_bytes,
cpu *processor,
unsigned_word cia)
{
hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
unsigned_1 *byte = (unsigned_1*)source;
switch (addr & hw_pal_address_mask) {
case hw_pal_reset_register:
cpu_halt(processor, cia, was_exited, byte[0]);
break;
case hw_pal_int_register:
device_interrupt_event(me,
byte[0],
(nr_bytes > 1 ? byte[1] : 0),
processor, cia);
break;
case hw_pal_read_fifo:
hw_pal->input.buffer = byte[0];
DTRACE(pal, ("write - input-fifo %d\n", byte[0]));
break;
case hw_pal_read_status:
hw_pal->input.status = byte[0];
DTRACE(pal, ("write - input-status %d\n", byte[0]));
break;
case hw_pal_write_fifo:
write_hw_pal(hw_pal, byte[0]);
DTRACE(pal, ("write - output-fifo %d\n", byte[0]));
break;
case hw_pal_write_status:
hw_pal->output.status = byte[0];
DTRACE(pal, ("write - output-status %d\n", byte[0]));
break;
}
return nr_bytes;
}
static void
hw_pal_instance_delete_callback(device_instance *instance)
{
return;
}
static int
hw_pal_instance_read_callback(device_instance *instance,
void *buf,
unsigned_word len)
{
DITRACE(pal, ("read - %s (%ld)", (const char*)buf, (long int)len));
return sim_io_read_stdin(buf, len);
}
static int
hw_pal_instance_write_callback(device_instance *instance,
const void *buf,
unsigned_word len)
{
int i;
const char *chp = buf;
hw_pal_device *hw_pal = device_instance_data(instance);
DITRACE(pal, ("write - %s (%ld)", (const char*)buf, (long int)len));
for (i = 0; i < len; i++)
write_hw_pal(hw_pal, chp[i]);
sim_io_flush_stdoutput();
return i;
}
static const device_instance_callbacks hw_pal_instance_callbacks = {
hw_pal_instance_delete_callback,
hw_pal_instance_read_callback,
hw_pal_instance_write_callback,
};
static device_instance *
hw_pal_create_instance(device *me,
const char *path,
const char *args)
{
return device_create_instance_from(me, NULL,
device_data(me),
path, args,
&hw_pal_instance_callbacks);
}
static const device_interrupt_port_descriptor hw_pal_interrupt_ports[] = {
{ "int", 0, MAX_NR_PROCESSORS },
{ NULL }
};
static void
hw_pal_attach_address(device *me,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
device *client)
{
hw_pal_device *pal = (hw_pal_device*)device_data(me);
pal->disk = client;
}
static device_callbacks const hw_pal_callbacks = {
{ generic_device_init_address, },
{ hw_pal_attach_address, },
{ hw_pal_io_read_buffer_callback,
hw_pal_io_write_buffer_callback, },
{ NULL, },
{ NULL, NULL, hw_pal_interrupt_ports },
{ generic_device_unit_decode,
generic_device_unit_encode,
generic_device_address_to_attach_address,
generic_device_size_to_attach_size },
hw_pal_create_instance,
};
static void *
hw_pal_create(const char *name,
const device_unit *unit_address,
const char *args)
{
hw_pal_device *hw_pal = ZALLOC(hw_pal_device);
hw_pal->output.status = 1;
hw_pal->output.buffer = '\0';
hw_pal->input.status = 0;
hw_pal->input.buffer = '\0';
return hw_pal;
}
const device_descriptor hw_pal_device_descriptor[] = {
{ "pal", hw_pal_create, &hw_pal_callbacks },
{ NULL },
};
#endif