1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, 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_HW_PAL
26 #define STATIC_INLINE_HW_PAL STATIC_INLINE
29 #include "device_table.h"
57 #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
59 #define WITH_STDIO DO_USE_STDIO
69 Typical hardware dependant hack. This device allows the firmware
70 to gain access to all the things the firmware needs (but the OS
71 doesn't). All registers are little endian (byte 0 is the least
72 significant) and must be accessed correctly aligned.
74 <address> + 0: write - halts simulation with exit code byte[0].
76 <address> + 4: read - processor nr in byte[0].
78 <address> + 8: write - send interrupt message to port byte[0] with
81 <address> + 12: read - nr processors in byte[0].
90 hw_pal_reset_register
= 0x0,
91 hw_pal_cpu_nr_register
= 0x4,
92 hw_pal_int_register
= 0x8,
93 hw_pal_nr_cpu_register
= 0xa,
94 hw_pal_read_fifo
= 0x10,
95 hw_pal_read_status
= 0x14,
96 hw_pal_write_fifo
= 0x18,
97 hw_pal_write_status
= 0x1a,
98 hw_pal_address_mask
= 0x1f,
102 typedef struct _hw_pal_console_buffer
{
105 } hw_pal_console_buffer
;
107 typedef struct _hw_pal_device
{
108 hw_pal_console_buffer input
;
109 hw_pal_console_buffer output
;
113 /* check the console for an available character */
115 scan_hw_pal(hw_pal_device
*hw_pal
)
117 if (WITH_STDIO
== DO_USE_STDIO
) {
120 hw_pal
->input
.buffer
= 0;
121 hw_pal
->input
.status
= 0;
123 hw_pal
->input
.buffer
= c
;
124 hw_pal
->input
.status
= 1;
128 #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
129 error ("O_NDELAY, F_GETFL, or F_SETFL not defined");
132 /* check for input */
135 /* get the old status */
136 flags
= fcntl(0, F_GETFL
, 0);
141 /* temp, disable blocking IO */
142 status
= fcntl(0, F_SETFL
, flags
| O_NDELAY
);
148 status
= read(0, &hw_pal
->input
.buffer
, 1);
150 hw_pal
->input
.status
= 1;
153 hw_pal
->input
.status
= 0;
155 /* return to regular vewing */
156 flags
= fcntl(0, F_SETFL
, flags
);
165 /* write the character to the hw_pal */
167 write_hw_pal(hw_pal_device
*hw_pal
,
170 if (WITH_STDIO
== DO_USE_STDIO
) {
174 printf_filtered("%c", val
) ;
177 hw_pal
->output
.buffer
= val
;
178 hw_pal
->output
.status
= 1;
183 hw_pal_io_read_buffer_callback(device
*me
,
191 hw_pal_device
*hw_pal
= (hw_pal_device
*)device_data(me
);
193 switch (addr
& hw_pal_address_mask
) {
194 case hw_pal_cpu_nr_register
:
195 val
= cpu_nr(processor
);
197 case hw_pal_nr_cpu_register
:
198 val
= device_find_integer_property(me
, "/openprom/options/smp");
200 case hw_pal_read_fifo
:
201 val
= hw_pal
->input
.buffer
;
203 case hw_pal_read_status
:
205 val
= hw_pal
->input
.status
;
207 case hw_pal_write_fifo
:
208 val
= hw_pal
->output
.buffer
;
210 case hw_pal_write_status
:
211 val
= hw_pal
->output
.status
;
216 memset(dest
, 0, nr_bytes
);
217 *(unsigned_1
*)dest
= val
;
223 hw_pal_io_write_buffer_callback(device
*me
,
231 hw_pal_device
*hw_pal
= (hw_pal_device
*)device_data(me
);
232 unsigned_1
*byte
= (unsigned_1
*)source
;
234 switch (addr
& hw_pal_address_mask
) {
235 case hw_pal_reset_register
:
236 cpu_halt(processor
, cia
, was_exited
, byte
[0]);
238 case hw_pal_int_register
:
239 device_interrupt_event(me
,
241 (nr_bytes
> 1 ? byte
[1] : 0), /* val */
244 case hw_pal_read_fifo
:
245 hw_pal
->input
.buffer
= byte
[0];
247 case hw_pal_read_status
:
248 hw_pal
->input
.status
= byte
[0];
250 case hw_pal_write_fifo
:
251 write_hw_pal(hw_pal
, byte
[0]);
253 case hw_pal_write_status
:
254 hw_pal
->output
.status
= byte
[0];
261 /* instances of the hw_pal device */
263 hw_pal_instance_create_callback(device
*me
,
266 /* make life easier, attach the hw_pal data to the instance */
267 return device_data(me
);
271 hw_pal_instance_delete_callback(device_instance
*instance
)
273 /* nothing to delete, the hw_pal is attached to the device */
278 hw_pal_instance_read_callback(device_instance
*instance
,
282 char *buf_char
= (char *)buf
;
283 if (WITH_STDIO
== DO_USE_STDIO
) {
284 char *line
= fgets (buf_char
, len
, stdin
);
285 return ((!line
) ? -1 : strlen (buf_char
));
288 return read(0, buf_char
, len
);
293 hw_pal_instance_write_callback(device_instance
*instance
,
298 const char *chp
= buf
;
299 hw_pal_device
*hw_pal
= device_instance_data(instance
);
300 for (i
= 0; i
< len
; i
++)
301 write_hw_pal(hw_pal
, chp
[i
]);
303 if (WITH_STDIO
== DO_USE_STDIO
) {
309 static device_callbacks
const hw_pal_callbacks
= {
310 { generic_device_init_address
, },
311 { NULL
, }, /* address */
312 { hw_pal_io_read_buffer_callback
,
313 hw_pal_io_write_buffer_callback
, },
315 { NULL
, }, /* interrupt */
316 { NULL
, }, /* unit */
317 { hw_pal_instance_create_callback
,
318 hw_pal_instance_delete_callback
,
319 hw_pal_instance_read_callback
,
320 hw_pal_instance_write_callback
, },
325 hw_pal_create(const char *name
,
326 const device_unit
*unit_address
,
330 /* create the descriptor */
331 hw_pal_device
*hw_pal
= ZALLOC(hw_pal_device
);
332 hw_pal
->output
.status
= 1;
333 hw_pal
->output
.buffer
= '\0';
334 hw_pal
->input
.status
= 0;
335 hw_pal
->input
.buffer
= '\0';
340 const device_descriptor hw_pal_device_descriptor
[] = {
341 { "pal", hw_pal_create
, &hw_pal_callbacks
},
345 #endif /* _HW_PAL_C_ */