sim: mn10300: fix typo in if check
[deliverable/binutils-gdb.git] / sim / mn10300 / dv-mn103iop.c
CommitLineData
c906108c
SS
1/* This file is part of the program GDB, the GNU debugger.
2
7b6bb8da
JB
3 Copyright (C) 1998, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
c906108c
SS
5 Contributed by Cygnus Solutions.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
4744ac1b 9 the Free Software Foundation; either version 3 of the License, or
c906108c 10 (at your option) any later version.
4744ac1b 11
c906108c
SS
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
4744ac1b 16
c906108c 17 You should have received a copy of the GNU General Public License
4744ac1b 18 along with this program. If not, see <http://www.gnu.org/licenses/>.
c906108c
SS
19
20 */
21
22#include "sim-main.h"
23#include "hw-main.h"
24
25/* DEVICE
26
27
28 mn103iop - mn103002 I/O ports 0-3.
29
30
31 DESCRIPTION
32
33 Implements the mn103002 i/o ports as described in the mn103002 user guide.
34
35
36 PROPERTIES
37
38 reg = <ioport-addr> <ioport-size> ...
39
40
41 BUGS
42
43 */
44
45
46/* The I/O ports' registers' address block */
47
48struct mn103iop_block {
49 unsigned_word base;
50 unsigned_word bound;
51};
52
53
54
55enum io_port_register_types {
56 P0OUT,
57 P1OUT,
58 P2OUT,
59 P3OUT,
60 P0MD,
61 P1MD,
62 P2MD,
63 P3MD,
64 P2SS,
65 P4SS,
66 P0DIR,
67 P1DIR,
68 P2DIR,
69 P3DIR,
70 P0IN,
71 P1IN,
72 P2IN,
73 P3IN,
74};
75
76#define NR_PORTS 4
77
78enum {
79 OUTPUT_BLOCK,
80 MODE_BLOCK,
81 DED_CTRL_BLOCK,
82 CTRL_BLOCK,
83 PIN_BLOCK,
84 NR_BLOCKS
85};
86
87typedef struct _mn10300_ioport {
88 unsigned8 output, output_mode, control, pin;
89 struct hw_event *event;
90} mn10300_ioport;
91
92
93
94struct mn103iop {
95 struct mn103iop_block block[NR_BLOCKS];
96 mn10300_ioport port[NR_PORTS];
97 unsigned8 p2ss, p4ss;
98};
99
100
101/* Finish off the partially created hw device. Attach our local
102 callbacks. Wire up our port names etc */
103
104static hw_io_read_buffer_method mn103iop_io_read_buffer;
105static hw_io_write_buffer_method mn103iop_io_write_buffer;
106
107static void
108attach_mn103iop_regs (struct hw *me,
109 struct mn103iop *io_port)
110{
111 int i;
112 unsigned_word attach_address;
113 int attach_space;
114 unsigned attach_size;
115 reg_property_spec reg;
116
117 if (hw_find_property (me, "reg") == NULL)
118 hw_abort (me, "Missing \"reg\" property");
119
120 for (i=0; i < NR_BLOCKS; ++i )
121 {
122 if (!hw_find_reg_array_property (me, "reg", i, &reg))
123 hw_abort (me, "\"reg\" property must contain five addr/size entries");
124 hw_unit_address_to_attach_address (hw_parent (me),
125 &reg.address,
126 &attach_space,
127 &attach_address,
128 me);
129 io_port->block[i].base = attach_address;
130 hw_unit_size_to_attach_size (hw_parent (me),
131 &reg.size,
132 &attach_size, me);
133 io_port->block[i].bound = attach_address + (attach_size - 1);
134 hw_attach_address (hw_parent (me),
135 0,
136 attach_space, attach_address, attach_size,
137 me);
138 }
139}
140
141static void
142mn103iop_finish (struct hw *me)
143{
144 struct mn103iop *io_port;
145 int i;
146
147 io_port = HW_ZALLOC (me, struct mn103iop);
148 set_hw_data (me, io_port);
149 set_hw_io_read_buffer (me, mn103iop_io_read_buffer);
150 set_hw_io_write_buffer (me, mn103iop_io_write_buffer);
151
152 /* Attach ourself to our parent bus */
153 attach_mn103iop_regs (me, io_port);
154
155 /* Initialize the i/o port registers. */
156 for ( i=0; i<NR_PORTS; ++i )
157 {
158 io_port->port[i].output = 0;
159 io_port->port[i].output_mode = 0;
160 io_port->port[i].control = 0;
161 io_port->port[i].pin = 0;
162 }
163 io_port->port[2].output_mode = 0xff;
164 io_port->p2ss = 0;
165 io_port->p4ss = 0x0f;
166}
167
168
169/* read and write */
170
171static int
172decode_addr (struct hw *me,
173 struct mn103iop *io_port,
174 unsigned_word address)
175{
176 unsigned_word offset;
177 offset = address - io_port->block[0].base;
178 switch (offset)
179 {
180 case 0x00: return P0OUT;
181 case 0x01: return P1OUT;
182 case 0x04: return P2OUT;
183 case 0x05: return P3OUT;
184 case 0x20: return P0MD;
185 case 0x21: return P1MD;
186 case 0x24: return P2MD;
187 case 0x25: return P3MD;
188 case 0x44: return P2SS;
189 case 0x48: return P4SS;
190 case 0x60: return P0DIR;
191 case 0x61: return P1DIR;
192 case 0x64: return P2DIR;
193 case 0x65: return P3DIR;
194 case 0x80: return P0IN;
195 case 0x81: return P1IN;
196 case 0x84: return P2IN;
197 case 0x85: return P3IN;
198 default:
199 {
200 hw_abort (me, "bad address");
201 return -1;
202 }
203 }
204}
205
206
207static void
208read_output_reg (struct hw *me,
209 struct mn103iop *io_port,
210 unsigned_word io_port_reg,
211 const void *dest,
212 unsigned nr_bytes)
213{
214 if ( nr_bytes == 1 )
215 {
216 *(unsigned8 *)dest = io_port->port[io_port_reg].output;
217 }
218 else
219 {
220 hw_abort (me, "bad read size of %d bytes from P%dOUT.", nr_bytes,
221 io_port_reg);
222 }
223}
224
225
226static void
227read_output_mode_reg (struct hw *me,
228 struct mn103iop *io_port,
229 unsigned_word io_port_reg,
230 const void *dest,
231 unsigned nr_bytes)
232{
233 if ( nr_bytes == 1 )
234 {
235 /* check if there are fields which can't be written and
236 take appropriate action depending what bits are set */
237 *(unsigned8 *)dest = io_port->port[io_port_reg].output_mode;
238 }
239 else
240 {
241 hw_abort (me, "bad read size of %d bytes to P%dMD.", nr_bytes,
242 io_port_reg);
243 }
244}
245
246
247static void
248read_control_reg (struct hw *me,
249 struct mn103iop *io_port,
250 unsigned_word io_port_reg,
251 const void *dest,
252 unsigned nr_bytes)
253{
254 if ( nr_bytes == 1 )
255 {
256 *(unsigned8 *)dest = io_port->port[io_port_reg].control;
257 }
258 else
259 {
260 hw_abort (me, "bad read size of %d bytes to P%dDIR.", nr_bytes,
261 io_port_reg);
262 }
263}
264
265
266static void
267read_pin_reg (struct hw *me,
268 struct mn103iop *io_port,
269 unsigned_word io_port_reg,
270 const void *dest,
271 unsigned nr_bytes)
272{
273 if ( nr_bytes == 1 )
274 {
275 *(unsigned8 *)dest = io_port->port[io_port_reg].pin;
276 }
277 else
278 {
279 hw_abort (me, "bad read size of %d bytes to P%dIN.", nr_bytes,
280 io_port_reg);
281 }
282}
283
284
285static void
286read_dedicated_control_reg (struct hw *me,
287 struct mn103iop *io_port,
288 unsigned_word io_port_reg,
289 const void *dest,
290 unsigned nr_bytes)
291{
292 if ( nr_bytes == 1 )
293 {
294 /* select on io_port_reg: */
295 if ( io_port_reg == P2SS )
296 {
297 *(unsigned8 *)dest = io_port->p2ss;
298 }
299 else
300 {
301 *(unsigned8 *)dest = io_port->p4ss;
302 }
303 }
304 else
305 {
306 hw_abort (me, "bad read size of %d bytes to PSS.", nr_bytes);
307 }
308}
309
310
311static unsigned
312mn103iop_io_read_buffer (struct hw *me,
313 void *dest,
314 int space,
315 unsigned_word base,
316 unsigned nr_bytes)
317{
318 struct mn103iop *io_port = hw_data (me);
319 enum io_port_register_types io_port_reg;
320 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
321
322 io_port_reg = decode_addr (me, io_port, base);
323 switch (io_port_reg)
324 {
325 /* Port output registers */
326 case P0OUT:
327 case P1OUT:
328 case P2OUT:
329 case P3OUT:
330 read_output_reg(me, io_port, io_port_reg-P0OUT, dest, nr_bytes);
331 break;
332
333 /* Port output mode registers */
334 case P0MD:
335 case P1MD:
336 case P2MD:
337 case P3MD:
338 read_output_mode_reg(me, io_port, io_port_reg-P0MD, dest, nr_bytes);
339 break;
340
341 /* Port control registers */
342 case P0DIR:
343 case P1DIR:
344 case P2DIR:
345 case P3DIR:
346 read_control_reg(me, io_port, io_port_reg-P0DIR, dest, nr_bytes);
347 break;
348
349 /* Port pin registers */
350 case P0IN:
351 case P1IN:
352 case P2IN:
353 read_pin_reg(me, io_port, io_port_reg-P0IN, dest, nr_bytes);
354 break;
355
356 case P2SS:
357 case P4SS:
358 read_dedicated_control_reg(me, io_port, io_port_reg, dest, nr_bytes);
359 break;
360
361 default:
362 hw_abort(me, "invalid address");
363 }
364
365 return nr_bytes;
366}
367
368
369static void
370write_output_reg (struct hw *me,
371 struct mn103iop *io_port,
372 unsigned_word io_port_reg,
373 const void *source,
374 unsigned nr_bytes)
375{
376 unsigned8 buf = *(unsigned8 *)source;
377 if ( nr_bytes == 1 )
378 {
379 if ( io_port_reg == 3 && (buf & 0xfc) != 0 )
380 {
381 hw_abort(me, "Cannot write to read-only bits of P3OUT.");
382 }
383 else
384 {
385 io_port->port[io_port_reg].output = buf;
386 }
387 }
388 else
389 {
390 hw_abort (me, "bad read size of %d bytes from P%dOUT.", nr_bytes,
391 io_port_reg);
392 }
393}
394
395
396static void
397write_output_mode_reg (struct hw *me,
398 struct mn103iop *io_port,
399 unsigned_word io_port_reg,
400 const void *source,
401 unsigned nr_bytes)
402{
403 unsigned8 buf = *(unsigned8 *)source;
404 if ( nr_bytes == 1 )
405 {
406 /* check if there are fields which can't be written and
407 take appropriate action depending what bits are set */
408 if ( ( io_port_reg == 3 && (buf & 0xfc) != 0 )
409 || ( (io_port_reg == 0 || io_port_reg == 1) && (buf & 0xfe) != 0 ) )
410 {
411 hw_abort(me, "Cannot write to read-only bits of output mode register.");
412 }
413 else
414 {
415 io_port->port[io_port_reg].output_mode = buf;
416 }
417 }
418 else
419 {
420 hw_abort (me, "bad write size of %d bytes to P%dMD.", nr_bytes,
421 io_port_reg);
422 }
423}
424
425
426static void
427write_control_reg (struct hw *me,
428 struct mn103iop *io_port,
429 unsigned_word io_port_reg,
430 const void *source,
431 unsigned nr_bytes)
432{
433 unsigned8 buf = *(unsigned8 *)source;
434 if ( nr_bytes == 1 )
435 {
436 if ( io_port_reg == 3 && (buf & 0xfc) != 0 )
437 {
438 hw_abort(me, "Cannot write to read-only bits of P3DIR.");
439 }
440 else
441 {
442 io_port->port[io_port_reg].control = buf;
443 }
444 }
445 else
446 {
447 hw_abort (me, "bad write size of %d bytes to P%dDIR.", nr_bytes,
448 io_port_reg);
449 }
450}
451
452
453static void
454write_dedicated_control_reg (struct hw *me,
455 struct mn103iop *io_port,
456 unsigned_word io_port_reg,
457 const void *source,
458 unsigned nr_bytes)
459{
460 unsigned8 buf = *(unsigned8 *)source;
461 if ( nr_bytes == 1 )
462 {
463 /* select on io_port_reg: */
464 if ( io_port_reg == P2SS )
465 {
481d7981 466 if ( (buf & 0xfc) != 0 )
c906108c
SS
467 {
468 hw_abort(me, "Cannot write to read-only bits in p2ss.");
469 }
470 else
471 {
472 io_port->p2ss = buf;
473 }
474 }
475 else
476 {
481d7981 477 if ( (buf & 0xf0) != 0 )
c906108c
SS
478 {
479 hw_abort(me, "Cannot write to read-only bits in p4ss.");
480 }
481 else
482 {
483 io_port->p4ss = buf;
484 }
485 }
486 }
487 else
488 {
489 hw_abort (me, "bad write size of %d bytes to PSS.", nr_bytes);
490 }
491}
492
493
494static unsigned
495mn103iop_io_write_buffer (struct hw *me,
496 const void *source,
497 int space,
498 unsigned_word base,
499 unsigned nr_bytes)
500{
501 struct mn103iop *io_port = hw_data (me);
502 enum io_port_register_types io_port_reg;
503 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
504
505 io_port_reg = decode_addr (me, io_port, base);
506 switch (io_port_reg)
507 {
508 /* Port output registers */
509 case P0OUT:
510 case P1OUT:
511 case P2OUT:
512 case P3OUT:
513 write_output_reg(me, io_port, io_port_reg-P0OUT, source, nr_bytes);
514 break;
515
516 /* Port output mode registers */
517 case P0MD:
518 case P1MD:
519 case P2MD:
520 case P3MD:
521 write_output_mode_reg(me, io_port, io_port_reg-P0MD, source, nr_bytes);
522 break;
523
524 /* Port control registers */
525 case P0DIR:
526 case P1DIR:
527 case P2DIR:
528 case P3DIR:
529 write_control_reg(me, io_port, io_port_reg-P0DIR, source, nr_bytes);
530 break;
531
532 /* Port pin registers */
533 case P0IN:
534 case P1IN:
535 case P2IN:
536 hw_abort(me, "Cannot write to pin register.");
537 break;
538
539 case P2SS:
540 case P4SS:
541 write_dedicated_control_reg(me, io_port, io_port_reg, source, nr_bytes);
542 break;
543
544 default:
545 hw_abort(me, "invalid address");
546 }
547
548 return nr_bytes;
549}
550
551
552const struct hw_descriptor dv_mn103iop_descriptor[] = {
553 { "mn103iop", mn103iop_finish, },
554 { NULL },
555};
This page took 0.537806 seconds and 4 git commands to generate.