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"
65 Typical hardware dependant hack. This device allows the firmware
66 to gain access to all the things the firmware needs (but the OS
67 doesn't). All registers are little endian (byte 0 is the least
68 significant) and must be accessed correctly aligned.
70 <address> + 0: write - halts simulation with exit code byte[0].
72 <address> + 4: read - processor nr in byte[0].
74 <address> + 8: write - send interrupt message to port byte[0] with
77 <address> + 12: read - nr processors in byte[0].
86 hw_pal_reset_register
= 0x0,
87 hw_pal_cpu_nr_register
= 0x4,
88 hw_pal_int_register
= 0x8,
89 hw_pal_nr_cpu_register
= 0xa,
90 hw_pal_read_fifo
= 0x10,
91 hw_pal_read_status
= 0x14,
92 hw_pal_write_fifo
= 0x18,
93 hw_pal_write_status
= 0x1a,
94 hw_pal_address_mask
= 0x1f,
98 typedef struct _hw_pal_console_buffer
{
101 } hw_pal_console_buffer
;
103 typedef struct _hw_pal_device
{
104 hw_pal_console_buffer input
;
105 hw_pal_console_buffer output
;
109 /* check the console for an available character */
111 scan_hw_pal(hw_pal_device
*hw_pal
)
113 if (WITH_STDIO
== DO_USE_STDIO
) {
116 hw_pal
->input
.buffer
= 0;
117 hw_pal
->input
.status
= 0;
119 hw_pal
->input
.buffer
= c
;
120 hw_pal
->input
.status
= 1;
124 /* check for input */
127 /* get the old status */
128 flags
= fcntl(0, F_GETFL
, 0);
133 /* temp, disable blocking IO */
134 status
= fcntl(0, F_SETFL
, flags
| O_NDELAY
);
140 status
= read(0, &hw_pal
->input
.buffer
, 1);
142 hw_pal
->input
.status
= 1;
145 hw_pal
->input
.status
= 0;
147 /* return to regular vewing */
148 flags
= fcntl(0, F_SETFL
, flags
);
156 /* write the character to the hw_pal */
158 write_hw_pal(hw_pal_device
*hw_pal
,
161 if (WITH_STDIO
== DO_USE_STDIO
) {
165 printf_filtered("%c", val
) ;
168 hw_pal
->output
.buffer
= val
;
169 hw_pal
->output
.status
= 1;
174 hw_pal_io_read_buffer_callback(device
*me
,
182 hw_pal_device
*hw_pal
= (hw_pal_device
*)device_data(me
);
184 switch (addr
& hw_pal_address_mask
) {
185 case hw_pal_cpu_nr_register
:
186 val
= cpu_nr(processor
);
188 case hw_pal_nr_cpu_register
:
189 val
= device_find_integer_property(me
, "/openprom/options/smp");
191 case hw_pal_read_fifo
:
192 val
= hw_pal
->input
.buffer
;
194 case hw_pal_read_status
:
196 val
= hw_pal
->input
.status
;
198 case hw_pal_write_fifo
:
199 val
= hw_pal
->output
.buffer
;
201 case hw_pal_write_status
:
202 val
= hw_pal
->output
.status
;
207 memset(dest
, 0, nr_bytes
);
208 *(unsigned_1
*)dest
= val
;
214 hw_pal_io_write_buffer_callback(device
*me
,
222 hw_pal_device
*hw_pal
= (hw_pal_device
*)device_data(me
);
223 unsigned_1
*byte
= (unsigned_1
*)source
;
225 switch (addr
& hw_pal_address_mask
) {
226 case hw_pal_reset_register
:
227 cpu_halt(processor
, cia
, was_exited
, byte
[0]);
229 case hw_pal_int_register
:
230 device_interrupt_event(me
,
232 (nr_bytes
> 1 ? byte
[1] : 0), /* val */
235 case hw_pal_read_fifo
:
236 hw_pal
->input
.buffer
= byte
[0];
238 case hw_pal_read_status
:
239 hw_pal
->input
.status
= byte
[0];
241 case hw_pal_write_fifo
:
242 write_hw_pal(hw_pal
, byte
[0]);
244 case hw_pal_write_status
:
245 hw_pal
->output
.status
= byte
[0];
252 /* instances of the hw_pal device */
254 hw_pal_instance_create_callback(device
*me
,
257 /* make life easier, attach the hw_pal data to the instance */
258 return device_data(me
);
262 hw_pal_instance_delete_callback(device_instance
*instance
)
264 /* nothing to delete, the hw_pal is attached to the device */
269 hw_pal_instance_read_callback(device_instance
*instance
,
273 char *buf_char
= (char *)buf
;
274 hw_pal_device
*hw_pal
= device_instance_data(instance
);
275 if (WITH_STDIO
== DO_USE_STDIO
) {
276 char *line
= fgets (buf_char
, len
, stdin
);
277 return ((!line
) ? -1 : strlen (buf_char
));
280 return read(0, buf_char
, len
);
285 hw_pal_instance_write_callback(device_instance
*instance
,
290 const char *chp
= buf
;
291 hw_pal_device
*hw_pal
= device_instance_data(instance
);
292 for (i
= 0; i
< len
; i
++)
293 write_hw_pal(hw_pal
, chp
[i
]);
295 if (WITH_STDIO
== DO_USE_STDIO
) {
301 static device_callbacks
const hw_pal_callbacks
= {
302 { generic_device_init_address
, },
303 { NULL
, }, /* address */
304 { hw_pal_io_read_buffer_callback
,
305 hw_pal_io_write_buffer_callback
, },
307 { NULL
, }, /* interrupt */
308 { NULL
, }, /* unit */
309 { hw_pal_instance_create_callback
,
310 hw_pal_instance_delete_callback
,
311 hw_pal_instance_read_callback
,
312 hw_pal_instance_write_callback
, },
317 hw_pal_create(const char *name
,
318 const device_unit
*unit_address
,
322 /* create the descriptor */
323 hw_pal_device
*hw_pal
= ZALLOC(hw_pal_device
);
324 hw_pal
->output
.status
= 1;
325 hw_pal
->output
.buffer
= '\0';
326 hw_pal
->input
.status
= 0;
327 hw_pal
->input
.buffer
= '\0';
332 const device_descriptor hw_pal_device_descriptor
[] = {
333 { "pal", hw_pal_create
, &hw_pal_callbacks
},
337 #endif /* _HW_PAL_C_ */