]>
Commit | Line | Data |
---|---|---|
93fac324 MM |
1 | /* This file is part of the program psim. |
2 | ||
30c87b55 | 3 | Copyright (C) 1994-1996, Andrew Cagney <[email protected]> |
93fac324 MM |
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 | ||
30c87b55 MM |
22 | #ifndef _DEVICE_H_ |
23 | #define _DEVICE_H_ | |
93fac324 MM |
24 | |
25 | #ifndef INLINE_DEVICE | |
26 | #define INLINE_DEVICE | |
27 | #endif | |
28 | ||
93fac324 MM |
29 | /* declared in basics.h, this object is used everywhere */ |
30 | /* typedef struct _device device; */ | |
31 | ||
32 | ||
30c87b55 | 33 | /* Introduction: |
93fac324 | 34 | |
30c87b55 MM |
35 | As explained in earlier sections, the device, device instance, |
36 | property and interrupts lie at the heart of PSIM's device model. | |
93fac324 | 37 | |
30c87b55 MM |
38 | In the below a synopsis of the device object and the operations it |
39 | supports are given. Details of this object can be found in the | |
40 | files <<device.h>> and <<device.c>>. | |
93fac324 | 41 | |
30c87b55 | 42 | */ |
93fac324 | 43 | |
979c3c25 | 44 | |
5c04f4f7 | 45 | /* Device creation: */ |
979c3c25 | 46 | |
5c04f4f7 MM |
47 | INLINE_DEVICE\ |
48 | (device *) device_create | |
49 | (device *parent, | |
50 | const char *base, | |
51 | const char *name, | |
52 | const char *unit_address, | |
53 | const char *args); | |
93fac324 | 54 | |
5c04f4f7 MM |
55 | INLINE_DEVICE\ |
56 | (void) device_usage | |
57 | (int verbose); | |
93fac324 | 58 | |
93fac324 | 59 | |
5c04f4f7 | 60 | /* Device initialization: */ |
93fac324 | 61 | |
5c04f4f7 MM |
62 | INLINE_DEVICE\ |
63 | (void) device_clean | |
64 | (device *root, | |
65 | void *data); | |
93fac324 | 66 | |
5c04f4f7 MM |
67 | INLINE_DEVICE\ |
68 | (void) device_init_static_properties | |
69 | (device *me, | |
70 | void *data); | |
93fac324 | 71 | |
5c04f4f7 MM |
72 | INLINE_DEVICE\ |
73 | (void) device_init_address | |
74 | (device *me, | |
75 | void *data); | |
93fac324 | 76 | |
5c04f4f7 MM |
77 | INLINE_DEVICE\ |
78 | (void) device_init_runtime_properties | |
79 | (device *me, | |
80 | void *data); | |
93fac324 | 81 | |
30c87b55 | 82 | INLINE_DEVICE\ |
5c04f4f7 MM |
83 | (void) device_init_data |
84 | (device *me, | |
85 | void *data); | |
93fac324 | 86 | |
93fac324 | 87 | |
30c87b55 | 88 | /* Relationships: |
93fac324 | 89 | |
30c87b55 MM |
90 | A device is able to determine its relationship to other devices |
91 | within the tree. Operations include querying for a devices parent, | |
92 | sibling, child, name, and path (from the root). | |
93fac324 | 93 | |
30c87b55 | 94 | */ |
93fac324 | 95 | |
30c87b55 MM |
96 | INLINE_DEVICE\ |
97 | (device *) device_parent | |
98 | (device *me); | |
93fac324 | 99 | |
5c04f4f7 MM |
100 | INLINE_DEVICE\ |
101 | (device *) device_root | |
102 | (device *me); | |
103 | ||
30c87b55 MM |
104 | INLINE_DEVICE\ |
105 | (device *) device_sibling | |
106 | (device *me); | |
93fac324 | 107 | |
30c87b55 MM |
108 | INLINE_DEVICE\ |
109 | (device *) device_child | |
110 | (device *me); | |
93fac324 | 111 | |
30c87b55 MM |
112 | INLINE_DEVICE\ |
113 | (const char *) device_name | |
114 | (device *me); | |
93fac324 | 115 | |
5c04f4f7 MM |
116 | INLINE_DEVICE\ |
117 | (const char *) device_base | |
118 | (device *me); | |
119 | ||
30c87b55 MM |
120 | INLINE_DEVICE\ |
121 | (const char *) device_path | |
122 | (device *me); | |
93fac324 | 123 | |
30c87b55 MM |
124 | INLINE_DEVICE\ |
125 | (void *) device_data | |
126 | (device *me); | |
93fac324 | 127 | |
30c87b55 MM |
128 | INLINE_DEVICE\ |
129 | (psim *) device_system | |
130 | (device *me); | |
93fac324 | 131 | |
30c87b55 MM |
132 | typedef struct _device_unit { |
133 | int nr_cells; | |
5c04f4f7 | 134 | unsigned_cell cells[4]; /* unused cells are zero */ |
30c87b55 | 135 | } device_unit; |
93fac324 | 136 | |
30c87b55 MM |
137 | INLINE_DEVICE\ |
138 | (const device_unit *) device_unit_address | |
139 | (device *me); | |
93fac324 | 140 | |
5c04f4f7 MM |
141 | INLINE_DEVICE\ |
142 | (int) device_decode_unit | |
143 | (device *bus, | |
144 | const char *unit, | |
145 | device_unit *address); | |
146 | ||
147 | INLINE_DEVICE\ | |
148 | (int) device_encode_unit | |
149 | (device *bus, | |
150 | const device_unit *unit_address, | |
151 | char *buf, | |
152 | int sizeof_buf); | |
153 | ||
154 | ||
155 | /* Convert an Open Firmware size into a form suitable for attach | |
156 | address calls. | |
157 | ||
158 | Return a zero result if the address should be ignored when looking | |
159 | for attach addresses */ | |
160 | ||
161 | INLINE_DEVICE\ | |
162 | (int) device_address_to_attach_address | |
163 | (device *me, | |
164 | const device_unit *address, | |
165 | int *attach_space, | |
166 | unsigned_word *attach_address, | |
167 | device *client); | |
168 | ||
169 | ||
170 | /* Convert an Open Firmware size into a form suitable for attach | |
171 | address calls | |
172 | ||
173 | Return a zero result if the address should be ignored */ | |
174 | ||
175 | INLINE_DEVICE\ | |
176 | (int) device_size_to_attach_size | |
177 | (device *me, | |
178 | const device_unit *size, | |
179 | unsigned *nr_bytes, | |
180 | device *client); | |
181 | ||
182 | ||
183 | INLINE_DEVICE\ | |
184 | (unsigned) device_nr_address_cells | |
185 | (device *me); | |
186 | ||
187 | INLINE_DEVICE\ | |
188 | (unsigned) device_nr_size_cells | |
189 | (device *me); | |
190 | ||
93fac324 | 191 | |
30c87b55 | 192 | /* Properties: |
93fac324 | 193 | |
30c87b55 MM |
194 | Attached to a device are a number of properties. Each property has |
195 | a size and type (both of which can be queried). A device is able | |
196 | to iterate over or query and set a properties value. | |
93fac324 | 197 | |
30c87b55 | 198 | */ |
93fac324 | 199 | |
5c04f4f7 | 200 | /* The following are valid property types. The property `array' is |
30c87b55 | 201 | for generic untyped data. */ |
93fac324 MM |
202 | |
203 | typedef enum { | |
30c87b55 | 204 | array_property, |
93fac324 | 205 | boolean_property, |
5c04f4f7 | 206 | ihandle_property, /*runtime*/ |
30c87b55 | 207 | integer_property, |
5c04f4f7 MM |
208 | range_array_property, |
209 | reg_array_property, | |
93fac324 | 210 | string_property, |
5c04f4f7 | 211 | string_array_property, |
93fac324 MM |
212 | } device_property_type; |
213 | ||
214 | typedef struct _device_property device_property; | |
215 | struct _device_property { | |
216 | device *owner; | |
30c87b55 | 217 | const char *name; |
93fac324 MM |
218 | device_property_type type; |
219 | unsigned sizeof_array; | |
220 | const void *array; | |
30c87b55 MM |
221 | const device_property *original; |
222 | object_disposition disposition; | |
93fac324 MM |
223 | }; |
224 | ||
225 | ||
30c87b55 MM |
226 | /* iterate through the properties attached to a device */ |
227 | ||
228 | INLINE_DEVICE\ | |
229 | (const device_property *) device_next_property | |
230 | (const device_property *previous); | |
93fac324 | 231 | |
30c87b55 MM |
232 | INLINE_DEVICE\ |
233 | (const device_property *) device_find_property | |
93fac324 | 234 | (device *me, |
30c87b55 MM |
235 | const char *property); /* NULL for first property */ |
236 | ||
237 | ||
238 | /* Manipulate the properties belonging to a given device. | |
239 | ||
240 | SET on the other hand will force the properties value. The | |
241 | simulation is aborted if the property was present but of a | |
242 | conflicting type. | |
243 | ||
244 | FIND returns the specified properties value, aborting the | |
245 | simulation if the property is missing. Code locating a property | |
246 | should first check its type (using device_find_property above) and | |
5c04f4f7 MM |
247 | then obtain its value using the below. |
248 | ||
249 | void device_add_<type>_property(device *, const char *, <type>) | |
250 | void device_add_*_array_property(device *, const char *, const <type>*, int) | |
251 | void device_set_*_property(device *, const char *, <type>) | |
252 | void device_set_*_array_property(device *, const char *, const <type>*, int) | |
253 | <type> device_find_*_property(device *, const char *) | |
254 | int device_find_*_array_property(device *, const char *, int, <type>*) | |
255 | ||
256 | */ | |
93fac324 | 257 | |
93fac324 | 258 | |
5c04f4f7 MM |
259 | INLINE_DEVICE\ |
260 | (void) device_add_array_property | |
261 | (device *me, | |
262 | const char *property, | |
263 | const void *array, | |
264 | int sizeof_array); | |
265 | ||
30c87b55 MM |
266 | INLINE_DEVICE\ |
267 | (void) device_set_array_property | |
93fac324 MM |
268 | (device *me, |
269 | const char *property, | |
270 | const void *array, | |
271 | int sizeof_array); | |
272 | ||
30c87b55 MM |
273 | INLINE_DEVICE\ |
274 | (const device_property *) device_find_array_property | |
93fac324 | 275 | (device *me, |
30c87b55 MM |
276 | const char *property); |
277 | ||
93fac324 | 278 | |
5c04f4f7 | 279 | |
30c87b55 | 280 | INLINE_DEVICE\ |
5c04f4f7 | 281 | (void) device_add_boolean_property |
93fac324 MM |
282 | (device *me, |
283 | const char *property, | |
284 | int bool); | |
285 | ||
30c87b55 MM |
286 | INLINE_DEVICE\ |
287 | (int) device_find_boolean_property | |
93fac324 MM |
288 | (device *me, |
289 | const char *property); | |
290 | ||
30c87b55 | 291 | |
5c04f4f7 MM |
292 | |
293 | typedef struct _ihandle_runtime_property_spec { | |
294 | device *phandle; | |
295 | const char *full_path; | |
296 | const char *args; | |
297 | } ihandle_runtime_property_spec; | |
298 | ||
299 | INLINE_DEVICE\ | |
300 | (void) device_add_ihandle_runtime_property | |
301 | (device *me, | |
302 | const char *property, | |
303 | const ihandle_runtime_property_spec *ihandle); | |
304 | ||
305 | INLINE_DEVICE\ | |
306 | (void) device_find_ihandle_runtime_property | |
307 | (device *me, | |
308 | const char *property, | |
309 | ihandle_runtime_property_spec *ihandle); | |
310 | ||
30c87b55 MM |
311 | INLINE_DEVICE\ |
312 | (void) device_set_ihandle_property | |
93fac324 MM |
313 | (device *me, |
314 | const char *property, | |
30c87b55 | 315 | device_instance *ihandle); |
93fac324 | 316 | |
30c87b55 MM |
317 | INLINE_DEVICE\ |
318 | (device_instance *) device_find_ihandle_property | |
93fac324 MM |
319 | (device *me, |
320 | const char *property); | |
321 | ||
322 | ||
5c04f4f7 | 323 | |
30c87b55 | 324 | INLINE_DEVICE\ |
5c04f4f7 | 325 | (void) device_add_integer_property |
93fac324 | 326 | (device *me, |
30c87b55 | 327 | const char *property, |
5c04f4f7 | 328 | signed_cell integer); |
93fac324 | 329 | |
30c87b55 | 330 | INLINE_DEVICE\ |
5c04f4f7 | 331 | (signed_cell) device_find_integer_property |
93fac324 MM |
332 | (device *me, |
333 | const char *property); | |
334 | ||
5c04f4f7 MM |
335 | INLINE_DEVICE\ |
336 | (int) device_find_integer_array_property | |
337 | (device *me, | |
338 | const char *property, | |
339 | unsigned index, | |
340 | signed_word *integer); | |
341 | ||
342 | ||
343 | ||
344 | typedef struct _range_property_spec { | |
345 | device_unit child_address; | |
346 | device_unit parent_address; | |
347 | device_unit size; | |
348 | } range_property_spec; | |
93fac324 | 349 | |
30c87b55 | 350 | INLINE_DEVICE\ |
5c04f4f7 MM |
351 | (void) device_add_range_array_property |
352 | (device *me, | |
353 | const char *property, | |
354 | const range_property_spec *ranges, | |
355 | unsigned nr_ranges); | |
356 | ||
357 | INLINE_DEVICE\ | |
358 | (int) device_find_range_array_property | |
359 | (device *me, | |
360 | const char *property, | |
361 | unsigned index, | |
362 | range_property_spec *range); | |
363 | ||
364 | ||
365 | ||
366 | typedef struct _reg_property_spec { | |
367 | device_unit address; | |
368 | device_unit size; | |
369 | } reg_property_spec; | |
370 | ||
371 | INLINE_DEVICE\ | |
372 | (void) device_add_reg_array_property | |
373 | (device *me, | |
374 | const char *property, | |
375 | const reg_property_spec *reg, | |
376 | unsigned nr_regs); | |
377 | ||
378 | INLINE_DEVICE\ | |
379 | (int) device_find_reg_array_property | |
380 | (device *me, | |
381 | const char *property, | |
382 | unsigned index, | |
383 | reg_property_spec *reg); | |
384 | ||
385 | ||
386 | ||
387 | INLINE_DEVICE\ | |
388 | (void) device_add_string_property | |
93fac324 | 389 | (device *me, |
30c87b55 MM |
390 | const char *property, |
391 | const char *string); | |
93fac324 | 392 | |
30c87b55 MM |
393 | INLINE_DEVICE\ |
394 | (const char *) device_find_string_property | |
93fac324 MM |
395 | (device *me, |
396 | const char *property); | |
397 | ||
398 | ||
5c04f4f7 MM |
399 | |
400 | typedef const char *string_property_spec; | |
401 | ||
402 | INLINE_DEVICE\ | |
403 | (void) device_add_string_array_property | |
404 | (device *me, | |
405 | const char *property, | |
406 | const string_property_spec *strings, | |
407 | unsigned nr_strings); | |
408 | ||
409 | INLINE_DEVICE\ | |
410 | (int) device_find_string_array_property | |
411 | (device *me, | |
412 | const char *property, | |
413 | unsigned index, | |
414 | string_property_spec *string); | |
415 | ||
416 | ||
417 | ||
418 | INLINE_DEVICE\ | |
419 | (void) device_add_duplicate_property | |
420 | (device *me, | |
421 | const char *property, | |
422 | const device_property *original); | |
423 | ||
424 | ||
425 | ||
30c87b55 | 426 | /* Instances: |
93fac324 | 427 | |
30c87b55 MM |
428 | As with IEEE1275, a device can be opened, creating an instance. |
429 | Instances provide more abstract interfaces to the underlying | |
430 | hardware. For example, the instance methods for a disk may include | |
431 | code that is able to interpret file systems found on disks. Such | |
432 | methods would there for allow the manipulation of files on the | |
433 | disks file system. The operations would be implemented using the | |
434 | basic block I/O model provided by the disk. | |
93fac324 | 435 | |
30c87b55 MM |
436 | This model includes methods that faciliate the creation of device |
437 | instance and (should a given device support it) standard operations | |
438 | on those instances. | |
93fac324 MM |
439 | |
440 | */ | |
441 | ||
30c87b55 | 442 | typedef struct _device_instance_callbacks device_instance_callbacks; |
93fac324 | 443 | |
30c87b55 MM |
444 | INLINE_DEVICE\ |
445 | (device_instance *) device_create_instance_from | |
446 | (device *me, /*OR*/ device_instance *parent, | |
93fac324 | 447 | void *data, |
30c87b55 MM |
448 | const char *path, |
449 | const char *args, | |
450 | const device_instance_callbacks *callbacks); | |
93fac324 | 451 | |
30c87b55 MM |
452 | INLINE_DEVICE\ |
453 | (device_instance *) device_create_instance | |
93fac324 | 454 | (device *me, |
5c04f4f7 MM |
455 | const char *full_path, |
456 | const char *args); | |
93fac324 | 457 | |
30c87b55 MM |
458 | INLINE_DEVICE\ |
459 | (void) device_instance_delete | |
460 | (device_instance *instance); | |
93fac324 | 461 | |
30c87b55 MM |
462 | INLINE_DEVICE\ |
463 | (int) device_instance_read | |
464 | (device_instance *instance, | |
465 | void *addr, | |
466 | unsigned_word len); | |
93fac324 | 467 | |
30c87b55 MM |
468 | INLINE_DEVICE\ |
469 | (int) device_instance_write | |
470 | (device_instance *instance, | |
471 | const void *addr, | |
472 | unsigned_word len); | |
93fac324 | 473 | |
30c87b55 MM |
474 | INLINE_DEVICE\ |
475 | (int) device_instance_seek | |
476 | (device_instance *instance, | |
477 | unsigned_word pos_hi, | |
478 | unsigned_word pos_lo); | |
93fac324 | 479 | |
30c87b55 | 480 | INLINE_DEVICE\ |
5c04f4f7 | 481 | (int) device_instance_call_method |
30c87b55 | 482 | (device_instance *instance, |
5c04f4f7 MM |
483 | const char *method, |
484 | int n_stack_args, | |
485 | unsigned_cell stack_args[/*n_stack_args*/], | |
486 | int n_stack_returns, | |
487 | unsigned_cell stack_returns[/*n_stack_returns*/]); | |
93fac324 | 488 | |
30c87b55 MM |
489 | INLINE_DEVICE\ |
490 | (device *) device_instance_device | |
491 | (device_instance *instance); | |
93fac324 | 492 | |
30c87b55 MM |
493 | INLINE_DEVICE\ |
494 | (const char *) device_instance_path | |
495 | (device_instance *instance); | |
93fac324 | 496 | |
30c87b55 MM |
497 | INLINE_DEVICE\ |
498 | (void *) device_instance_data | |
499 | (device_instance *instance); | |
93fac324 | 500 | |
93fac324 | 501 | |
30c87b55 | 502 | /* Interrupts: |
93fac324 | 503 | |
30c87b55 | 504 | */ |
93fac324 | 505 | |
30c87b55 | 506 | /* Interrupt Source |
93fac324 | 507 | |
30c87b55 | 508 | A device drives its interrupt line using the call |
93fac324 | 509 | |
30c87b55 | 510 | */ |
93fac324 | 511 | |
30c87b55 MM |
512 | INLINE_DEVICE\ |
513 | (void) device_interrupt_event | |
514 | (device *me, | |
515 | int my_port, | |
516 | int value, | |
517 | cpu *processor, | |
518 | unsigned_word cia); | |
93fac324 | 519 | |
30c87b55 MM |
520 | /* This interrupt event will then be propogated to any attached |
521 | interrupt destinations. | |
93fac324 | 522 | |
30c87b55 MM |
523 | Any interpretation of PORT and VALUE is model dependant. However |
524 | as guidelines the following are recommended: PCI interrupts a-d | |
525 | correspond to lines 0-3; level sensative interrupts be requested | |
526 | with a value of one and withdrawn with a value of 0; edge sensative | |
527 | interrupts always have a value of 1, the event its self is treated | |
528 | as the interrupt. | |
93fac324 | 529 | |
93fac324 | 530 | |
30c87b55 | 531 | Interrupt Destinations |
93fac324 | 532 | |
30c87b55 MM |
533 | Attached to each interrupt line of a device can be zero or more |
534 | desitinations. These destinations consist of a device/port pair. | |
535 | A destination is attached/detached to a device line using the | |
536 | attach and detach calls. */ | |
93fac324 | 537 | |
30c87b55 MM |
538 | INLINE_DEVICE\ |
539 | (void) device_interrupt_attach | |
540 | (device *me, | |
541 | int my_port, | |
542 | device *dest, | |
543 | int dest_port, | |
544 | object_disposition disposition); | |
545 | ||
546 | INLINE_DEVICE\ | |
547 | (void) device_interrupt_detach | |
548 | (device *me, | |
549 | int my_port, | |
550 | device *dest, | |
551 | int dest_port); | |
93fac324 | 552 | |
5c04f4f7 MM |
553 | typedef void (device_interrupt_traverse_function) |
554 | (device *me, | |
555 | int my_port, | |
556 | device *dest, | |
557 | int my_dest, | |
558 | void *data); | |
559 | ||
560 | INLINE_DEVICE\ | |
561 | (void) device_interrupt_traverse | |
562 | (device *me, | |
563 | device_interrupt_traverse_function *handler, | |
564 | void *data); | |
565 | ||
566 | ||
30c87b55 | 567 | /* DESTINATION is attached (detached) to LINE of the device ME |
93fac324 | 568 | |
93fac324 | 569 | |
30c87b55 | 570 | Interrupt conversion |
93fac324 | 571 | |
30c87b55 MM |
572 | Users refer to interrupt port numbers symbolically. For instance a |
573 | device may refer to its `INT' signal which is internally | |
574 | represented by port 3. | |
93fac324 | 575 | |
30c87b55 MM |
576 | To convert to/from the symbolic and internal representation of a |
577 | port name/number. The following functions are available. */ | |
578 | ||
579 | INLINE_DEVICE\ | |
580 | (int) device_interrupt_decode | |
93fac324 | 581 | (device *me, |
5c04f4f7 MM |
582 | const char *symbolic_name, |
583 | port_direction direction); | |
93fac324 | 584 | |
30c87b55 MM |
585 | INLINE_DEVICE\ |
586 | (int) device_interrupt_encode | |
93fac324 | 587 | (device *me, |
30c87b55 MM |
588 | int port_number, |
589 | char *buf, | |
5c04f4f7 MM |
590 | int sizeof_buf, |
591 | port_direction direction); | |
30c87b55 | 592 | |
93fac324 | 593 | |
30c87b55 MM |
594 | /* Hardware operations: |
595 | ||
596 | */ | |
597 | ||
598 | INLINE_DEVICE\ | |
599 | (unsigned) device_io_read_buffer | |
93fac324 MM |
600 | (device *me, |
601 | void *dest, | |
602 | int space, | |
603 | unsigned_word addr, | |
604 | unsigned nr_bytes, | |
605 | cpu *processor, | |
606 | unsigned_word cia); | |
607 | ||
30c87b55 MM |
608 | INLINE_DEVICE\ |
609 | (unsigned) device_io_write_buffer | |
93fac324 MM |
610 | (device *me, |
611 | const void *source, | |
612 | int space, | |
613 | unsigned_word addr, | |
614 | unsigned nr_bytes, | |
615 | cpu *processor, | |
616 | unsigned_word cia); | |
617 | ||
30c87b55 MM |
618 | |
619 | /* Conversly, the device pci1000,1@1 my need to perform a dma transfer | |
620 | into the cpu/memory core. Just as I/O moves towards the leaves, | |
621 | dma transfers move towards the core via the initiating devices | |
622 | parent nodes. The root device (special) converts the DMA transfer | |
623 | into reads/writes to memory */ | |
624 | ||
625 | INLINE_DEVICE\ | |
626 | (unsigned) device_dma_read_buffer | |
93fac324 MM |
627 | (device *me, |
628 | void *dest, | |
629 | int space, | |
630 | unsigned_word addr, | |
631 | unsigned nr_bytes); | |
632 | ||
30c87b55 MM |
633 | INLINE_DEVICE\ |
634 | (unsigned) device_dma_write_buffer | |
93fac324 MM |
635 | (device *me, |
636 | const void *source, | |
637 | int space, | |
638 | unsigned_word addr, | |
639 | unsigned nr_bytes, | |
640 | int violate_read_only_section); | |
641 | ||
30c87b55 MM |
642 | /* To avoid the need for an intermediate (bridging) node to ask each |
643 | of its child devices in turn if an IO access is intended for them, | |
644 | parent nodes maintain a table mapping addresses directly to | |
645 | specific devices. When a device is `connected' to its bus it | |
646 | attaches its self to its parent. */ | |
93fac324 | 647 | |
30c87b55 MM |
648 | /* Address access attributes */ |
649 | typedef enum _access_type { | |
650 | access_invalid = 0, | |
651 | access_read = 1, | |
652 | access_write = 2, | |
653 | access_read_write = 3, | |
654 | access_exec = 4, | |
655 | access_read_exec = 5, | |
656 | access_write_exec = 6, | |
657 | access_read_write_exec = 7, | |
658 | } access_type; | |
93fac324 | 659 | |
30c87b55 MM |
660 | /* Address attachement types */ |
661 | typedef enum _attach_type { | |
662 | attach_invalid, | |
663 | attach_raw_memory, | |
664 | attach_callback, | |
665 | /* ... */ | |
666 | } attach_type; | |
93fac324 | 667 | |
30c87b55 MM |
668 | INLINE_DEVICE\ |
669 | (void) device_attach_address | |
670 | (device *me, | |
30c87b55 MM |
671 | attach_type attach, |
672 | int space, | |
673 | unsigned_word addr, | |
674 | unsigned nr_bytes, | |
675 | access_type access, | |
5c04f4f7 | 676 | device *client); /*callback/default*/ |
93fac324 | 677 | |
30c87b55 MM |
678 | INLINE_DEVICE\ |
679 | (void) device_detach_address | |
680 | (device *me, | |
30c87b55 MM |
681 | attach_type attach, |
682 | int space, | |
683 | unsigned_word addr, | |
684 | unsigned nr_bytes, | |
685 | access_type access, | |
5c04f4f7 | 686 | device *client); /*callback/default*/ |
93fac324 | 687 | |
30c87b55 | 688 | /* Utilities: |
93fac324 MM |
689 | |
690 | */ | |
691 | ||
30c87b55 | 692 | /* IOCTL:: |
93fac324 | 693 | |
30c87b55 MM |
694 | Often devices require `out of band' operations to be performed. |
695 | For instance a pal device may need to notify a PCI bridge device | |
696 | that an interrupt ack cycle needs to be performed on the PCI bus. | |
697 | Within PSIM such operations are performed by using the generic | |
698 | ioctl call <<device_ioctl()>>. | |
93fac324 | 699 | |
30c87b55 MM |
700 | */ |
701 | ||
5c04f4f7 MM |
702 | typedef enum { |
703 | device_ioctl_break, /* unsigned_word requested_break */ | |
704 | device_ioctl_set_trace, /* void */ | |
705 | device_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */ | |
706 | device_ioctl_change_media, /* const char *new_image (possibly NULL) */ | |
707 | nr_device_ioctl_requests, | |
708 | } device_ioctl_request; | |
709 | ||
30c87b55 MM |
710 | EXTERN_DEVICE\ |
711 | (int) device_ioctl | |
93fac324 | 712 | (device *me, |
93fac324 | 713 | cpu *processor, |
30c87b55 | 714 | unsigned_word cia, |
5c04f4f7 | 715 | device_ioctl_request request, |
30c87b55 | 716 | ...); |
93fac324 | 717 | |
93fac324 | 718 | |
30c87b55 | 719 | /* Error reporting:: |
93fac324 | 720 | |
30c87b55 MM |
721 | So that errors originating from devices appear in a consistent |
722 | format, the <<device_error()>> function can be used. Formats and | |
723 | outputs the error message before aborting the simulation | |
93fac324 | 724 | |
30c87b55 MM |
725 | Devices should use this function to abort the simulation except |
726 | when the abort reason leaves the simulation in a hazardous | |
727 | condition (for instance a failed malloc). | |
728 | ||
729 | */ | |
93fac324 | 730 | |
979c3c25 | 731 | EXTERN_DEVICE\ |
30c87b55 | 732 | (void volatile) device_error |
93fac324 | 733 | (device *me, |
30c87b55 MM |
734 | const char *fmt, |
735 | ...) __attribute__ ((format (printf, 2, 3))); | |
93fac324 | 736 | |
30c87b55 | 737 | INLINE_DEVICE\ |
5c04f4f7 MM |
738 | (int) device_trace |
739 | (device *me); | |
30c87b55 | 740 | |
30c87b55 MM |
741 | |
742 | ||
743 | /* External representation: | |
744 | ||
745 | Both device nodes and device instances, in OpenBoot firmware have | |
746 | an external representation (phandles and ihandles) and these values | |
747 | are both stored in the device tree in property nodes and passed | |
748 | between the client program and the simulator during emulation | |
749 | calls. | |
750 | ||
751 | To limit the potential risk associated with trusing `data' from the | |
752 | client program, the following mapping operators `safely' convert | |
753 | between the two representations | |
754 | ||
755 | */ | |
756 | ||
757 | INLINE_DEVICE\ | |
758 | (device *) external_to_device | |
759 | (device *tree_member, | |
5c04f4f7 | 760 | unsigned_cell phandle); |
30c87b55 MM |
761 | |
762 | INLINE_DEVICE\ | |
5c04f4f7 | 763 | (unsigned_cell) device_to_external |
30c87b55 MM |
764 | (device *me); |
765 | ||
766 | INLINE_DEVICE\ | |
767 | (device_instance *) external_to_device_instance | |
768 | (device *tree_member, | |
5c04f4f7 | 769 | unsigned_cell ihandle); |
30c87b55 MM |
770 | |
771 | INLINE_DEVICE\ | |
5c04f4f7 | 772 | (unsigned_cell) device_instance_to_external |
30c87b55 MM |
773 | (device_instance *me); |
774 | ||
5c04f4f7 MM |
775 | |
776 | /* Event queue: | |
777 | ||
778 | The device inherets certain event queue operations from the main | |
779 | simulation. */ | |
780 | ||
781 | typedef void device_event_handler(void *data); | |
782 | ||
783 | INLINE_DEVICE\ | |
784 | (event_entry_tag) device_event_queue_schedule | |
785 | (device *me, | |
786 | signed64 delta_time, | |
787 | device_event_handler *handler, | |
788 | void *data); | |
789 | ||
790 | INLINE_EVENTS\ | |
791 | (void) device_event_queue_deschedule | |
792 | (device *me, | |
793 | event_entry_tag event_to_remove); | |
794 | ||
795 | INLINE_EVENTS\ | |
796 | (signed64) device_event_queue_time | |
797 | (device *me); | |
798 | ||
30c87b55 | 799 | #endif /* _DEVICE_H_ */ |