Fix INLN in bugapi to read a full line
[deliverable/binutils-gdb.git] / sim / ppc / hw_pal.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
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.
9
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.
14
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.
18
19 */
20
21
22 #ifndef _HW_PAL_C_
23 #define _HW_PAL_C_
24
25 #ifndef STATIC_INLINE_HW_PAL
26 #define STATIC_INLINE_HW_PAL STATIC_INLINE
27 #endif
28
29 #include "device_table.h"
30 #include "cpu.h"
31
32
33 #include <stdio.h>
34 #include <fcntl.h>
35
36 #if 0
37 #ifdef HAVE_TIME_H
38 #include <time.h>
39 #endif
40 #endif
41
42 #ifdef HAVE_STRING_H
43 #include <string.h>
44 #else
45 #ifdef HAVE_STRINGS_H
46 #include <strings.h>
47 #endif
48 #endif
49
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53 #ifdef HAVE_STDLIB_H
54 #include <stdlib.h>
55 #endif
56
57
58 /* Device:
59
60 pal@<address>
61
62
63 Description:
64
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.
69
70 <address> + 0: write - halts simulation with exit code byte[0].
71
72 <address> + 4: read - processor nr in byte[0].
73
74 <address> + 8: write - send interrupt message to port byte[0] with
75 value byte[1].
76
77 <address> + 12: read - nr processors in byte[0].
78
79
80 Properties:
81
82 NONE. */
83
84
85 enum {
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,
95 };
96
97
98 typedef struct _hw_pal_console_buffer {
99 char buffer;
100 int status;
101 } hw_pal_console_buffer;
102
103 typedef struct _hw_pal_device {
104 hw_pal_console_buffer input;
105 hw_pal_console_buffer output;
106 } hw_pal_device;
107
108
109 /* check the console for an available character */
110 static void
111 scan_hw_pal(hw_pal_device *hw_pal)
112 {
113 if (WITH_STDIO == DO_USE_STDIO) {
114 int c = getchar ();
115 if (c == EOF) {
116 hw_pal->input.buffer = 0;
117 hw_pal->input.status = 0;
118 } else {
119 hw_pal->input.buffer = c;
120 hw_pal->input.status = 1;
121 }
122
123 } else {
124 /* check for input */
125 int flags;
126 int status;
127 /* get the old status */
128 flags = fcntl(0, F_GETFL, 0);
129 if (flags == -1) {
130 perror("hw_pal");
131 return;
132 }
133 /* temp, disable blocking IO */
134 status = fcntl(0, F_SETFL, flags | O_NDELAY);
135 if (status == -1) {
136 perror("hw_pal");
137 return;
138 }
139 /* try for input */
140 status = read(0, &hw_pal->input.buffer, 1);
141 if (status == 1) {
142 hw_pal->input.status = 1;
143 }
144 else {
145 hw_pal->input.status = 0;
146 }
147 /* return to regular vewing */
148 flags = fcntl(0, F_SETFL, flags);
149 if (flags == -1) {
150 perror("hw_pal");
151 return;
152 }
153 }
154 }
155
156 /* write the character to the hw_pal */
157 static void
158 write_hw_pal(hw_pal_device *hw_pal,
159 char val)
160 {
161 if (WITH_STDIO == DO_USE_STDIO) {
162 putchar (val);
163
164 } else {
165 printf_filtered("%c", val) ;
166 }
167
168 hw_pal->output.buffer = val;
169 hw_pal->output.status = 1;
170 }
171
172
173 static unsigned
174 hw_pal_io_read_buffer_callback(device *me,
175 void *dest,
176 int space,
177 unsigned_word addr,
178 unsigned nr_bytes,
179 cpu *processor,
180 unsigned_word cia)
181 {
182 hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
183 unsigned_1 val;
184 switch (addr & hw_pal_address_mask) {
185 case hw_pal_cpu_nr_register:
186 val = cpu_nr(processor);
187 break;
188 case hw_pal_nr_cpu_register:
189 val = device_find_integer_property(me, "/openprom/options/smp");
190 break;
191 case hw_pal_read_fifo:
192 val = hw_pal->input.buffer;
193 break;
194 case hw_pal_read_status:
195 scan_hw_pal(hw_pal);
196 val = hw_pal->input.status;
197 break;
198 case hw_pal_write_fifo:
199 val = hw_pal->output.buffer;
200 break;
201 case hw_pal_write_status:
202 val = hw_pal->output.status;
203 break;
204 default:
205 val = 0;
206 }
207 memset(dest, 0, nr_bytes);
208 *(unsigned_1*)dest = val;
209 return nr_bytes;
210 }
211
212
213 static unsigned
214 hw_pal_io_write_buffer_callback(device *me,
215 const void *source,
216 int space,
217 unsigned_word addr,
218 unsigned nr_bytes,
219 cpu *processor,
220 unsigned_word cia)
221 {
222 hw_pal_device *hw_pal = (hw_pal_device*)device_data(me);
223 unsigned_1 *byte = (unsigned_1*)source;
224
225 switch (addr & hw_pal_address_mask) {
226 case hw_pal_reset_register:
227 cpu_halt(processor, cia, was_exited, byte[0]);
228 break;
229 case hw_pal_int_register:
230 device_interrupt_event(me,
231 byte[0], /*port*/
232 (nr_bytes > 1 ? byte[1] : 0), /* val */
233 processor, cia);
234 break;
235 case hw_pal_read_fifo:
236 hw_pal->input.buffer = byte[0];
237 break;
238 case hw_pal_read_status:
239 hw_pal->input.status = byte[0];
240 break;
241 case hw_pal_write_fifo:
242 write_hw_pal(hw_pal, byte[0]);
243 break;
244 case hw_pal_write_status:
245 hw_pal->output.status = byte[0];
246 break;
247 }
248 return nr_bytes;
249 }
250
251
252 /* instances of the hw_pal device */
253 static void *
254 hw_pal_instance_create_callback(device *me,
255 const char *args)
256 {
257 /* make life easier, attach the hw_pal data to the instance */
258 return device_data(me);
259 }
260
261 static void
262 hw_pal_instance_delete_callback(device_instance *instance)
263 {
264 /* nothing to delete, the hw_pal is attached to the device */
265 return;
266 }
267
268 static int
269 hw_pal_instance_read_callback(device_instance *instance,
270 void *buf,
271 unsigned_word len)
272 {
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));
278
279 } else {
280 return read(0, buf_char, len);
281 }
282 }
283
284 static int
285 hw_pal_instance_write_callback(device_instance *instance,
286 const void *buf,
287 unsigned_word len)
288 {
289 int i;
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]);
294
295 if (WITH_STDIO == DO_USE_STDIO) {
296 fflush (stdout);
297 }
298 return i;
299 }
300
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, },
306 { NULL, }, /* DMA */
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, },
313 };
314
315
316 static void *
317 hw_pal_create(const char *name,
318 const device_unit *unit_address,
319 const char *args,
320 device *parent)
321 {
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';
328 return hw_pal;
329 }
330
331
332 const device_descriptor hw_pal_device_descriptor[] = {
333 { "pal", hw_pal_create, &hw_pal_callbacks },
334 { NULL },
335 };
336
337 #endif /* _HW_PAL_C_ */
This page took 0.051041 seconds and 5 git commands to generate.