1 /* This file is part of the program psim.
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"
51 #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
53 #define WITH_STDIO DO_USE_STDIO
58 pal - glue logic device containing assorted junk
62 Typical hardware dependant hack. This device allows the firmware
63 to gain access to all the things the firmware needs (but the OS
66 The pal contains the following registers. Except for the interrupt
67 level register, each of the below is 8 bytes in size and must be
68 accessed using correct alignment. For 16 and 32 bit accesses the
69 bytes not directed to the register are ignored:
71 |0 reset register (write)
72 |4 processor id register (read)
73 |8 interrupt port (write)
74 |9 interrupt level (write)
75 |12 processor count register (read)
76 |16 tty input fifo register (read)
77 |20 tty input status register (read)
78 |24 tty output fifo register (write)
79 |28 tty output status register (read)
81 Reset register (write) halts the simulator exiting with the
84 Processor id register (read) returns the processor number (0
85 .. N-1) of the processor performing the read.
87 The interrupt registers should be accessed as a pair (using a 16 or
88 32 bit store). The low byte specifies the interrupt port while the
89 high byte specifies the level to drive that port at. By
90 convention, the pal's interrupt ports (int0, int1, ...) are wired
91 up to the corresponding processor's level sensative external
92 interrupt pin. Eg: A two byte write to address 8 of 0x0102
93 (big-endian) will result in processor 2's external interrupt pin to
96 Processor count register (read) returns the total number of
97 processors active in the current simulation.
99 TTY input fifo register (read), if the TTY input status register
100 indicates a character is available by being nonzero, returns the
101 next available character from the pal's tty input port.
103 Similarly, the TTY output fifo register (write), if the TTY output
104 status register indicates the output fifo is not full by being
105 nonzero, outputs the character written to the tty's output port.
109 reg = <address> <size> (required)
111 Specify the address (within the parent bus) that this device is to
118 hw_pal_reset_register = 0x0,
119 hw_pal_cpu_nr_register = 0x4,
120 hw_pal_int_register = 0x8,
121 hw_pal_nr_cpu_register = 0xa,
122 hw_pal_read_fifo = 0x10,
123 hw_pal_read_status = 0x14,
124 hw_pal_write_fifo = 0x18,
125 hw_pal_write_status = 0x1a,
126 hw_pal_address_mask = 0x1f,
130 typedef struct _hw_pal_console_buffer {
133 } hw_pal_console_buffer;
135 typedef struct _hw_pal_device {
136 hw_pal_console_buffer input;
137 hw_pal_console_buffer output;
141 /* check the console for an available character */
143 scan_hw_pal(hw_pal_device *hw_pal)
145 if (WITH_STDIO == DO_USE_STDIO) {
148 hw_pal->input.buffer = 0;
149 hw_pal->input.status = 0;
151 hw_pal->input.buffer = c;
152 hw_pal->input.status = 1;
156 #if !defined(O_NDELAY) || !defined(F_GETFL) || !defined(F_SETFL)
157 error ("O_NDELAY, F_GETFL, or F_SETFL not defined");
160 /* check for input */
163 /* get the old status */
164 flags = fcntl(0, F_GETFL, 0);
169 /* temp, disable blocking IO */
170 status = fcntl(0, F_SETFL, flags | O_NDELAY);
176 status = read(0, &hw_pal->input.buffer, 1);
178 hw_pal->input.status = 1;
181 hw_pal->input.status = 0;
183 /* return to regular vewing */
184 flags = fcntl(0, F_SETFL, flags);
193 /* write the character to the hw_pal */
195 write_hw_pal(hw_pal_device *hw_pal,
198 if (WITH_STDIO == DO_USE_STDIO) {
202 printf_filtered("%c", val) ;
205 hw_pal->output.buffer = val;
206 hw_pal->output.status = 1;
211 hw_pal_io_read_buffer_callback(device *me,
219 hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
221 switch (addr & hw_pal_address_mask) {
222 case hw_pal_cpu_nr_register:
223 val = cpu_nr(processor);
225 case hw_pal_nr_cpu_register:
226 val = device_find_integer_property(me, "/openprom/options/smp");
228 case hw_pal_read_fifo:
229 val = hw_pal->input.buffer;
231 case hw_pal_read_status:
233 val = hw_pal->input.status;
235 case hw_pal_write_fifo:
236 val = hw_pal->output.buffer;
238 case hw_pal_write_status:
239 val = hw_pal->output.status;
244 memset(dest, 0, nr_bytes);
245 *(unsigned_1*)dest = val;
251 hw_pal_io_write_buffer_callback(device *me,
259 hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
260 unsigned_1 *byte = (unsigned_1*)source;
262 switch (addr & hw_pal_address_mask) {
263 case hw_pal_reset_register:
264 cpu_halt(processor, cia, was_exited, byte[0]);
266 case hw_pal_int_register:
267 device_interrupt_event(me,
269 (nr_bytes > 1 ? byte[1] : 0), /* val */
272 case hw_pal_read_fifo:
273 hw_pal->input.buffer = byte[0];
275 case hw_pal_read_status:
276 hw_pal->input.status = byte[0];
278 case hw_pal_write_fifo:
279 write_hw_pal(hw_pal, byte[0]);
281 case hw_pal_write_status:
282 hw_pal->output.status = byte[0];
289 /* instances of the hw_pal device */
292 hw_pal_instance_delete_callback(device_instance *instance)
294 /* nothing to delete, the hw_pal is attached to the device */
299 hw_pal_instance_read_callback(device_instance *instance,
303 char *buf_char = (char *)buf;
304 if (WITH_STDIO == DO_USE_STDIO) {
305 char *line = fgets (buf_char, len, stdin);
306 return ((!line) ? -1 : strlen (buf_char));
309 return read(0, buf_char, len);
314 hw_pal_instance_write_callback(device_instance *instance,
319 const char *chp = buf;
320 hw_pal_device *hw_pal = device_instance_data(instance);
321 for (i = 0; i < len; i++)
322 write_hw_pal(hw_pal, chp[i]);
324 if (WITH_STDIO == DO_USE_STDIO) {
330 static const device_instance_callbacks hw_pal_instance_callbacks = {
331 hw_pal_instance_delete_callback,
332 hw_pal_instance_read_callback,
333 hw_pal_instance_write_callback,
336 static device_instance *
337 hw_pal_create_instance(device *me,
341 return device_create_instance_from(me, NULL,
344 &hw_pal_instance_callbacks);
347 static const device_interrupt_port_descriptor hw_pal_interrupt_ports[] = {
348 { "int", 0, MAX_NR_PROCESSORS },
353 static device_callbacks const hw_pal_callbacks = {
354 { generic_device_init_address, },
355 { NULL, }, /* address */
356 { hw_pal_io_read_buffer_callback,
357 hw_pal_io_write_buffer_callback, },
359 { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */
360 { NULL, }, /* unit */
361 hw_pal_create_instance,
366 hw_pal_create(const char *name,
367 const device_unit *unit_address,
370 /* create the descriptor */
371 hw_pal_device *hw_pal = ZALLOC(hw_pal_device);
372 hw_pal->output.status = 1;
373 hw_pal->output.buffer = '\0';
374 hw_pal->input.status = 0;
375 hw_pal->input.buffer = '\0';
380 const device_descriptor hw_pal_device_descriptor[] = {
381 { "pal", hw_pal_create, &hw_pal_callbacks },
385 #endif /* _HW_PAL_C_ */