Commit | Line | Data |
---|---|---|
7cb5d426 JJ |
1 | /* This file is part of the program GDB, the GNU debugger. |
2 | ||
3 | Copyright (C) 1998 Free Software Foundation, Inc. | |
4 | Contributed by Cygnus Solutions. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
19 | ||
20 | */ | |
21 | ||
22 | #include "sim-main.h" | |
23 | #include "hw-main.h" | |
24 | ||
25 | /* DEVICE | |
26 | ||
27 | ||
28 | mn103ser - mn103002 serial devices 0, 1 and 2. | |
29 | ||
30 | ||
31 | DESCRIPTION | |
32 | ||
33 | Implements the mn103002 serial interfaces as described in the | |
34 | mn103002 user guide. | |
35 | ||
36 | ||
37 | PROPERTIES | |
38 | ||
39 | reg = <serial-addr> <serial-size> | |
40 | ||
41 | ||
42 | BUGS | |
43 | ||
44 | */ | |
45 | ||
46 | ||
47 | /* The serial devices' registers' address block */ | |
48 | ||
49 | struct mn103ser_block { | |
50 | unsigned_word base; | |
51 | unsigned_word bound; | |
52 | }; | |
53 | ||
54 | ||
55 | ||
56 | enum serial_register_types { | |
57 | SC0CTR, | |
58 | SC0ICR, | |
59 | SC0TXB, | |
60 | SC0RXB, | |
61 | SC0STR, | |
62 | SC1CTR, | |
63 | SC1ICR, | |
64 | SC1TXB, | |
65 | SC1RXB, | |
66 | SC1STR, | |
67 | SC2CTR, | |
68 | SC2ICR, | |
69 | SC2TXB, | |
70 | SC2RXB, | |
71 | SC2STR, | |
72 | }; | |
73 | ||
74 | ||
75 | struct mn103ser { | |
76 | struct mn103ser_block block; | |
77 | }; | |
78 | ||
79 | /* output port ID's */ | |
80 | ||
81 | /* for mn103002 */ | |
82 | enum { | |
83 | SERIAL0_RECEIVE, | |
84 | SERIAL0_SEND, | |
85 | SERIAL1_RECEIVE, | |
86 | SERIAL1_SEND, | |
87 | SERIAL2_RECEIVE, | |
88 | SERIAL2_SEND, | |
89 | }; | |
90 | ||
91 | ||
92 | static const struct hw_port_descriptor mn103ser_ports[] = { | |
93 | ||
94 | { "serial-0-receive", SERIAL0_RECEIVE, 0, output_port, }, | |
95 | { "serial-0-transmit", SERIAL0_SEND, 0, output_port, }, | |
96 | { "serial-1-receive", SERIAL1_RECEIVE, 0, output_port, }, | |
97 | { "serial-1-transmit", SERIAL1_SEND, 0, output_port, }, | |
98 | { "serial-2-receive", SERIAL2_RECEIVE, 0, output_port, }, | |
99 | { "serial-2-transmit", SERIAL2_SEND, 0, output_port, }, | |
100 | ||
101 | { NULL, }, | |
102 | }; | |
103 | ||
104 | ||
105 | ||
106 | /* Finish off the partially created hw device. Attach our local | |
107 | callbacks. Wire up our port names etc */ | |
108 | ||
109 | static hw_io_read_buffer_method mn103ser_io_read_buffer; | |
110 | static hw_io_write_buffer_method mn103ser_io_write_buffer; | |
111 | ||
112 | static void | |
113 | attach_mn103ser_regs (struct hw *me, | |
114 | struct mn103ser *serial) | |
115 | { | |
116 | unsigned_word attach_address; | |
117 | int attach_space; | |
118 | unsigned attach_size; | |
119 | reg_property_spec reg; | |
120 | ||
121 | if (hw_find_property (me, "reg") == NULL) | |
122 | hw_abort (me, "Missing \"reg\" property"); | |
123 | ||
124 | if (!hw_find_reg_array_property (me, "reg", 0, ®)) | |
125 | hw_abort (me, "\"reg\" property must contain three addr/size entries"); | |
126 | hw_unit_address_to_attach_address (hw_parent (me), | |
127 | ®.address, | |
128 | &attach_space, | |
129 | &attach_address, | |
130 | me); | |
131 | serial->block.base = attach_address; | |
132 | hw_unit_size_to_attach_size (hw_parent (me), | |
133 | ®.size, | |
134 | &attach_size, me); | |
135 | serial->block.bound = attach_address + (attach_size - 1); | |
136 | hw_attach_address (hw_parent (me), | |
137 | 0, | |
138 | attach_space, attach_address, attach_size, | |
139 | me); | |
140 | } | |
141 | ||
142 | static void | |
143 | mn103ser_finish (struct hw *me) | |
144 | { | |
145 | struct mn103ser *serial; | |
146 | int i; | |
147 | ||
148 | serial = HW_ZALLOC (me, struct mn103ser); | |
149 | set_hw_data (me, serial); | |
150 | set_hw_io_read_buffer (me, mn103ser_io_read_buffer); | |
151 | set_hw_io_write_buffer (me, mn103ser_io_write_buffer); | |
152 | set_hw_ports (me, mn103ser_ports); | |
153 | ||
154 | /* Attach ourself to our parent bus */ | |
155 | attach_mn103ser_regs (me, serial); | |
156 | ||
157 | /* Initialize the serial device registers. */ | |
158 | } | |
159 | ||
160 | ||
161 | /* read and write */ | |
162 | ||
163 | static int | |
164 | decode_addr (struct hw *me, | |
165 | struct mn103ser *serial, | |
166 | unsigned_word address) | |
167 | { | |
168 | unsigned_word offset; | |
169 | offset = address - serial->block.base; | |
170 | ||
171 | switch (offset) | |
172 | { | |
173 | case 0x00: return SC0CTR; | |
174 | case 0x04: return SC0ICR; | |
175 | case 0x08: return SC0TXB; | |
176 | case 0x09: return SC0RXB; | |
177 | case 0x0C: return SC0STR; | |
178 | case 0x10: return SC1CTR; | |
179 | case 0x14: return SC1ICR; | |
180 | case 0x18: return SC1TXB; | |
181 | case 0x19: return SC1RXB; | |
182 | case 0x1C: return SC1STR; | |
183 | case 0x20: return SC2CTR; | |
184 | case 0x24: return SC2ICR; | |
185 | case 0x28: return SC2TXB; | |
186 | case 0x29: return SC2RXB; | |
187 | case 0x2C: return SC2STR; | |
188 | default: | |
189 | { | |
190 | hw_abort (me, "bad address"); | |
191 | return -1; | |
192 | } | |
193 | } | |
194 | } | |
195 | ||
196 | static void | |
197 | read_control_reg (struct hw *me, | |
198 | struct mn103ser *serial, | |
199 | unsigned_word addr, | |
200 | void *dest, | |
201 | unsigned nr_bytes) | |
202 | { | |
203 | } | |
204 | ||
205 | ||
206 | static void | |
207 | read_intmode_reg (struct hw *me, | |
208 | struct mn103ser *serial, | |
209 | unsigned_word addr, | |
210 | void *dest, | |
211 | unsigned nr_bytes) | |
212 | { | |
213 | } | |
214 | ||
215 | ||
216 | static void | |
217 | read_txb (struct hw *me, | |
218 | struct mn103ser *serial, | |
219 | unsigned_word addr, | |
220 | void *dest, | |
221 | unsigned nr_bytes) | |
222 | { | |
223 | } | |
224 | ||
225 | ||
226 | static void | |
227 | read_rxb (struct hw *me, | |
228 | struct mn103ser *serial, | |
229 | unsigned_word addr, | |
230 | void *dest, | |
231 | unsigned nr_bytes) | |
232 | { | |
233 | } | |
234 | ||
235 | ||
236 | static void | |
237 | read_status_reg (struct hw *me, | |
238 | struct mn103ser *serial, | |
239 | unsigned_word addr, | |
240 | void *dest, | |
241 | unsigned nr_bytes) | |
242 | { | |
243 | } | |
244 | ||
245 | ||
246 | static unsigned | |
247 | mn103ser_io_read_buffer (struct hw *me, | |
248 | void *dest, | |
249 | int space, | |
250 | unsigned_word base, | |
251 | unsigned nr_bytes) | |
252 | { | |
253 | struct mn103ser *serial = hw_data (me); | |
254 | enum serial_register_types serial_reg; | |
255 | HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); | |
256 | ||
257 | serial_reg = decode_addr (me, serial, base); | |
258 | switch (serial_reg) | |
259 | { | |
260 | /* control registers */ | |
261 | case SC0CTR: | |
262 | case SC1CTR: | |
263 | case SC2CTR: | |
264 | read_control_reg(me, serial, base, dest, nr_bytes); | |
265 | break; | |
266 | ||
267 | /* interrupt mode registers */ | |
268 | case SC0ICR: | |
269 | case SC1ICR: | |
270 | case SC2ICR: | |
271 | read_intmode_reg(me, serial, base, dest, nr_bytes); | |
272 | break; | |
273 | ||
274 | /* transmission buffers */ | |
275 | case SC0TXB: | |
276 | case SC1TXB: | |
277 | case SC2TXB: | |
278 | read_txb(me, serial, base, dest, nr_bytes); | |
279 | break; | |
280 | ||
281 | /* reception buffers */ | |
282 | case SC0RXB: | |
283 | case SC1RXB: | |
284 | case SC2RXB: | |
285 | read_rxb(me, serial, base, dest, nr_bytes); | |
286 | break; | |
287 | ||
288 | /* status registers */ | |
289 | case SC0STR: | |
290 | case SC1STR: | |
291 | case SC2STR: | |
292 | read_status_reg(me, serial, base, dest, nr_bytes); | |
293 | break; | |
294 | ||
295 | default: | |
296 | hw_abort(me, "invalid address"); | |
297 | } | |
298 | ||
299 | return nr_bytes; | |
300 | } | |
301 | ||
302 | ||
303 | static void | |
304 | write_control_reg (struct hw *me, | |
305 | struct mn103ser *serial, | |
306 | unsigned_word addr, | |
307 | const void *source, | |
308 | unsigned nr_bytes) | |
309 | { | |
310 | } | |
311 | ||
312 | ||
313 | static void | |
314 | write_intmode_reg (struct hw *me, | |
315 | struct mn103ser *serial, | |
316 | unsigned_word addr, | |
317 | const void *source, | |
318 | unsigned nr_bytes) | |
319 | { | |
320 | } | |
321 | ||
322 | ||
323 | static void | |
324 | write_txb (struct hw *me, | |
325 | struct mn103ser *serial, | |
326 | unsigned_word addr, | |
327 | const void *source, | |
328 | unsigned nr_bytes) | |
329 | { | |
330 | } | |
331 | ||
332 | ||
333 | static void | |
334 | write_rxb (struct hw *me, | |
335 | struct mn103ser *serial, | |
336 | unsigned_word addr, | |
337 | const void *source, | |
338 | unsigned nr_bytes) | |
339 | { | |
340 | } | |
341 | ||
342 | ||
343 | static void | |
344 | write_status_reg (struct hw *me, | |
345 | struct mn103ser *serial, | |
346 | unsigned_word addr, | |
347 | const void *source, | |
348 | unsigned nr_bytes) | |
349 | { | |
350 | } | |
351 | ||
352 | ||
353 | static unsigned | |
354 | mn103ser_io_write_buffer (struct hw *me, | |
355 | const void *source, | |
356 | int space, | |
357 | unsigned_word base, | |
358 | unsigned nr_bytes) | |
359 | { | |
360 | struct mn103ser *serial = hw_data (me); | |
361 | enum serial_register_types serial_reg; | |
362 | HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); | |
363 | ||
364 | serial_reg = decode_addr (me, serial, base); | |
365 | switch (serial_reg) | |
366 | { | |
367 | /* control registers */ | |
368 | case SC0CTR: | |
369 | case SC1CTR: | |
370 | case SC2CTR: | |
371 | write_control_reg(me, serial, base, source, nr_bytes); | |
372 | break; | |
373 | ||
374 | /* interrupt mode registers */ | |
375 | case SC0ICR: | |
376 | case SC1ICR: | |
377 | case SC2ICR: | |
378 | write_intmode_reg(me, serial, base, source, nr_bytes); | |
379 | break; | |
380 | ||
381 | /* transmission buffers */ | |
382 | case SC0TXB: | |
383 | case SC1TXB: | |
384 | case SC2TXB: | |
385 | write_txb(me, serial, base, source, nr_bytes); | |
386 | break; | |
387 | ||
388 | /* reception buffers */ | |
389 | case SC0RXB: | |
390 | case SC1RXB: | |
391 | case SC2RXB: | |
392 | write_rxb(me, serial, base, source, nr_bytes); | |
393 | break; | |
394 | ||
395 | /* status registers */ | |
396 | case SC0STR: | |
397 | case SC1STR: | |
398 | case SC2STR: | |
399 | write_status_reg(me, serial, base, source, nr_bytes); | |
400 | break; | |
401 | ||
402 | default: | |
403 | hw_abort(me, "invalid address"); | |
404 | } | |
405 | ||
406 | return nr_bytes; | |
407 | } | |
408 | ||
409 | ||
410 | const struct hw_descriptor dv_mn103ser_descriptor[] = { | |
411 | { "mn103ser", mn103ser_finish, }, | |
412 | { NULL }, | |
413 | }; |