This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / ppc / hw_htab.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_HTAB_C_
23 #define _HW_HTAB_C_
24
25 #include "device_table.h"
26
27 #include "bfd.h"
28
29
30 /* DEVICE
31
32
33 htab - pseudo-device describing a PowerPC hash table
34
35
36 DESCRIPTION
37
38
39 During the initialization of the device tree, the pseudo-device
40 <<htab>>, in conjunction with any child <<pte>> pseudo-devices,
41 will create a PowerPC hash table in memory. The hash table values
42 are written using dma transfers.
43
44 The size and address of the hash table are determined by properties
45 of the htab node.
46
47 By convention, the htab device is made a child of the
48 <</openprom/init>> node.
49
50 By convention, the real address of the htab is used as the htab
51 nodes unit address.
52
53
54 PROPERTIES
55
56
57 real-address = <address> (required)
58
59 The physical address of the hash table. The PowerPC architecture
60 places limitations on what is a valid hash table real-address.
61
62
63 nr-bytes = <size> (required)
64
65 The size of the hash table (in bytes) that is to be created at
66 <<real-address>>. The PowerPC architecture places limitations on
67 what is a valid hash table size.
68
69
70 claim = <anything> (optional)
71
72 If this property is present, the memory used to construct the hash
73 table will be claimed from the memory device. The memory device
74 being specified by the <</chosen/memory>> ihandle property.
75
76
77 EXAMPLES
78
79 Enable tracing.
80
81 | $ psim -t htab-device \
82
83
84 Create a htab specifying the base address and minimum size.
85
86 | -o '/openprom/init/htab@0x10000/real-address 0x10000' \
87 | -o '/openprom/init/htab@0x10000/claim 0' \
88 | -o '/openprom/init/htab@0x10000/nr-bytes 65536' \
89
90
91 BUGS
92
93
94 See the <<pte>> device.
95
96
97 */
98
99
100 /* DEVICE
101
102
103 pte - pseudo-device describing a htab entry
104
105
106 DESCRIPTION
107
108
109 The <<pte>> pseudo-device, which must be a child of a <<htabl>>
110 node, describes a virtual to physical mapping that is to be entered
111 into the parents hash table.
112
113 Two alternative specifications of the mapping are allowed. Either
114 a section of physical memory can be mapped to a virtual address, or
115 the header of an executible image can be used to define the
116 mapping.
117
118 By convention, the real address of the map is specified as the pte
119 devices unit address.
120
121
122 PROPERTIES
123
124
125 real-address = <address> (required)
126
127 The starting physical address that is to be mapped by the hash
128 table.
129
130
131 wimg = <int> (required)
132 pp = <int> (required)
133
134 The value of hash table protection bits that are to be used when
135 creating the virtual to physical address map.
136
137
138 claim = <anything> (optional)
139
140 If this property is present, the real memory that is being mapped by the
141 hash table will be claimed from the memory node (specified by the
142 ihandle <</chosen/memory>>).
143
144
145 virtual-address = <integer> [ <integer> ] (option A)
146 nr-bytes = <size> (option A)
147
148 Option A - Virtual virtual address (and size) at which the physical
149 address is to be mapped. If multiple values are specified for the
150 virtual address then they are concatenated to gether to form a
151 longer virtual address.
152
153
154 file-name = <string> (option B)
155
156 Option B - An executable image that is to be loaded (starting at
157 the physical address specified above) and then mapped in using
158 informatioin taken from the executables header. information found
159 in the files header.
160
161
162 EXAMPLES
163
164
165 Enable tracing (note that both the <<htab>> and <<pte>> device use the
166 same trace option).
167
168 | -t htab-device \
169
170
171 Map a block of physical memory into a specified virtual address:
172
173 | -o '/openprom/init/htab/pte@0x0/real-address 0' \
174 | -o '/openprom/init/htab/pte@0x0/nr-bytes 4096' \
175 | -o '/openprom/init/htab/pte@0x0/virtual-address 0x1000000' \
176 | -o '/openprom/init/htab/pte@0x0/claim 0' \
177 | -o '/openprom/init/htab/pte@0x0/wimg 0x7' \
178 | -o '/openprom/init/htab/pte@0x0/pp 0x2' \
179
180
181 Map a file into memory.
182
183 | -o '/openprom/init/htab/pte@0x10000/real-address 0x10000' \
184 | -o '/openprom/init/htab/pte@0x10000/file-name "netbsd.elf' \
185 | -o '/openprom/init/htab/pte@0x10000/wimg 0x7' \
186 | -o '/openprom/init/htab/pte@0x10000/pp 0x2' \
187
188
189 BUGS
190
191
192 For an ELF executable, the header defines both the virtual and real
193 address at which each file section should be loaded. At present, the
194 real addresses that are specified in the header are ignored, the file
195 instead being loaded in to physical memory in a linear fashion.
196
197 When claiming memory, this device assumes that the #address-cells
198 and #size-cells is one. For future implementations, this may not
199 be the case.
200
201 */
202
203
204
205 static void
206 htab_decode_hash_table(device *me,
207 unsigned32 *htaborg,
208 unsigned32 *htabmask)
209 {
210 unsigned_word htab_ra;
211 unsigned htab_nr_bytes;
212 unsigned n;
213 device *parent = device_parent(me);
214 /* determine the location/size of the hash table */
215 if (parent == NULL
216 || strcmp(device_name(parent), "htab") != 0)
217 device_error(parent, "must be a htab device");
218 htab_ra = device_find_integer_property(parent, "real-address");
219 htab_nr_bytes = device_find_integer_property(parent, "nr-bytes");
220 for (n = htab_nr_bytes; n > 1; n = n / 2) {
221 if (n % 2 != 0)
222 device_error(parent, "htab size 0x%x not a power of two",
223 htab_nr_bytes);
224 }
225 *htaborg = htab_ra;
226 *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
227 if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
228 device_error(parent, "htaborg 0x%lx not aligned to htabmask 0x%lx",
229 (unsigned long)*htaborg, (unsigned long)*htabmask);
230 }
231 DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
232 (unsigned long)*htaborg, (unsigned long)*htabmask));
233 }
234
235 static void
236 htab_map_page(device *me,
237 unsigned_word ra,
238 unsigned64 va,
239 unsigned wimg,
240 unsigned pp,
241 unsigned32 htaborg,
242 unsigned32 htabmask)
243 {
244 /* keep everything left shifted so that the numbering is easier */
245 unsigned64 vpn = va << 12;
246 unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
247 unsigned32 vpage = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
248 unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
249 ^ EXTRACTED32(vpage, 0, 15),
250 7, 31-6);
251 int h;
252 for (h = 0; h < 2; h++) {
253 unsigned32 pteg = (htaborg | (hash & htabmask));
254 int pti;
255 for (pti = 0; pti < 8; pti++) {
256 unsigned32 pte = pteg + 8 * pti;
257 unsigned32 current_target_pte0;
258 unsigned32 current_pte0;
259 if (device_dma_read_buffer(device_parent(me),
260 &current_target_pte0,
261 0, /*space*/
262 pte,
263 sizeof(current_target_pte0)) != 4)
264 device_error(me, "failed to read a pte at 0x%lx", (unsigned long)pte);
265 current_pte0 = T2H_4(current_target_pte0);
266 if (MASKED32(current_pte0, 0, 0)) {
267 /* full pte, check it isn't already mapping the same virtual
268 address */
269 unsigned32 curr_vsid = INSERTED32(EXTRACTED32(current_pte0, 1, 24), 0, 23);
270 unsigned32 curr_api = INSERTED32(EXTRACTED32(current_pte0, 26, 31), 0, 5);
271 unsigned32 curr_h = EXTRACTED32(current_pte0, 25, 25);
272 if (curr_h == h
273 && curr_vsid == vsid
274 && curr_api == MASKED32(vpage, 0, 5))
275 device_error(me, "duplicate map - va=0x%08lx ra=0x%lx vsid=0x%lx h=%d vpage=0x%lx hash=0x%lx pteg=0x%lx+%2d pte0=0x%lx",
276 (unsigned long)va,
277 (unsigned long)ra,
278 (unsigned long)vsid,
279 h,
280 (unsigned long)vpage,
281 (unsigned long)hash,
282 (unsigned long)pteg,
283 pti * 8,
284 (unsigned long)current_pte0);
285 }
286 else {
287 /* empty pte fill it */
288 unsigned32 pte0 = (MASK32(0, 0)
289 | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
290 | INSERTED32(h, 25, 25)
291 | INSERTED32(EXTRACTED32(vpage, 0, 5), 26, 31));
292 unsigned32 target_pte0 = H2T_4(pte0);
293 unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
294 | INSERTED32(wimg, 25, 28)
295 | INSERTED32(pp, 30, 31));
296 unsigned32 target_pte1 = H2T_4(pte1);
297 if (device_dma_write_buffer(device_parent(me),
298 &target_pte0,
299 0, /*space*/
300 pte,
301 sizeof(target_pte0),
302 1/*ro?*/) != 4
303 || device_dma_write_buffer(device_parent(me),
304 &target_pte1,
305 0, /*space*/
306 pte + 4,
307 sizeof(target_pte1),
308 1/*ro?*/) != 4)
309 device_error(me, "failed to write a pte a 0x%lx", (unsigned long)pte);
310 DTRACE(htab, ("map - va=0x%08lx ra=0x%lx vsid=0x%lx h=%d vpage=0x%lx hash=0x%lx pteg=0x%lx+%2d pte0=0x%lx pte1=0x%lx\n",
311 (unsigned long)va,
312 (unsigned long)ra,
313 (unsigned long)vsid,
314 h,
315 (unsigned long)vpage,
316 (unsigned long)hash,
317 (unsigned long)pteg,
318 pti * 8,
319 (unsigned long)pte0,
320 (unsigned long)pte1));
321 return;
322 }
323 }
324 /* re-hash */
325 hash = MASKED32(~hash, 0, 18);
326 }
327 }
328
329 static unsigned_word
330 claim_memory(device *me,
331 device_instance *memory,
332 unsigned_word ra,
333 unsigned_word size)
334 {
335 unsigned32 args[3];
336 unsigned32 results[1];
337 int status;
338 args[0] = 0; /* alignment */
339 args[1] = size;
340 args[2] = ra;
341 status = device_instance_call_method(memory, "claim", 3, args, 1, results);
342 if (status != 0)
343 device_error(me, "failed to claim memory");
344 return results[0];
345 }
346
347 static void
348 htab_map_region(device *me,
349 device_instance *memory,
350 unsigned_word pte_ra,
351 unsigned64 pte_va,
352 unsigned nr_bytes,
353 unsigned wimg,
354 unsigned pp,
355 unsigned32 htaborg,
356 unsigned32 htabmask)
357 {
358 unsigned_word ra;
359 unsigned64 va;
360 /* claim the memory */
361 if (memory != NULL)
362 claim_memory(me, memory, pte_ra, nr_bytes);
363 /* go through all pages and create a pte for each */
364 for (ra = pte_ra, va = pte_va;
365 ra < pte_ra + nr_bytes;
366 ra += 0x1000, va += 0x1000) {
367 htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
368 }
369 }
370
371 typedef struct _htab_binary_sizes {
372 unsigned_word text_ra;
373 unsigned_word text_base;
374 unsigned_word text_bound;
375 unsigned_word data_ra;
376 unsigned_word data_base;
377 unsigned data_bound;
378 device *me;
379 } htab_binary_sizes;
380
381 static void
382 htab_sum_binary(bfd *abfd,
383 sec_ptr sec,
384 PTR data)
385 {
386 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
387 unsigned_word size = bfd_get_section_size_before_reloc (sec);
388 unsigned_word vma = bfd_get_section_vma (abfd, sec);
389 #define bfd_get_section_lma(abfd, sec) ((sec)->lma + 0)
390 unsigned_word ra = bfd_get_section_lma (abfd, sec);
391
392 /* skip the section if no memory to allocate */
393 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
394 return;
395
396 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
397 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
398 if (sizes->text_bound < vma + size)
399 sizes->text_bound = ALIGN_PAGE(vma + size);
400 if (sizes->text_base > vma)
401 sizes->text_base = FLOOR_PAGE(vma);
402 if (sizes->text_ra > ra)
403 sizes->text_ra = FLOOR_PAGE(ra);
404 }
405 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
406 || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
407 if (sizes->data_bound < vma + size)
408 sizes->data_bound = ALIGN_PAGE(vma + size);
409 if (sizes->data_base > vma)
410 sizes->data_base = FLOOR_PAGE(vma);
411 if (sizes->data_ra > ra)
412 sizes->data_ra = FLOOR_PAGE(ra);
413 }
414 }
415
416 static void
417 htab_dma_binary(bfd *abfd,
418 sec_ptr sec,
419 PTR data)
420 {
421 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
422 void *section_init;
423 unsigned_word section_vma;
424 unsigned_word section_size;
425 unsigned_word section_ra;
426 device *me = sizes->me;
427
428 /* skip the section if no memory to allocate */
429 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
430 return;
431
432 /* check/ignore any sections of size zero */
433 section_size = bfd_get_section_size_before_reloc(sec);
434 if (section_size == 0)
435 return;
436
437 /* if nothing to load, ignore this one */
438 if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
439 return;
440
441 /* find where it is to go */
442 section_vma = bfd_get_section_vma(abfd, sec);
443 section_ra = 0;
444 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
445 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
446 section_ra = (section_vma - sizes->text_base + sizes->text_ra);
447 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
448 section_ra = (section_vma - sizes->data_base + sizes->data_ra);
449 else
450 return; /* just ignore it */
451
452 DTRACE(htab,
453 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
454 bfd_get_section_name(abfd, sec),
455 (long)section_vma,
456 (long)section_size,
457 (long)section_ra,
458 (long)bfd_get_section_flags(abfd, sec),
459 bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
460 bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
461 bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
462 bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
463 bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
464 ));
465
466 /* dma in the sections data */
467 section_init = zalloc(section_size);
468 if (!bfd_get_section_contents(abfd,
469 sec,
470 section_init, 0,
471 section_size)) {
472 bfd_perror("devices/pte");
473 device_error(me, "no data loaded");
474 }
475 if (device_dma_write_buffer(device_parent(me),
476 section_init,
477 0 /*space*/,
478 section_ra,
479 section_size,
480 1 /*violate_read_only*/)
481 != section_size)
482 device_error(me, "broken dma transfer");
483 zfree(section_init); /* only free if load */
484 }
485
486 /* create a memory map from a binaries virtual addresses to a copy of
487 the binary laid out linearly in memory */
488
489 static void
490 htab_map_binary(device *me,
491 device_instance *memory,
492 unsigned_word ra,
493 unsigned wimg,
494 unsigned pp,
495 const char *file_name,
496 unsigned32 htaborg,
497 unsigned32 htabmask)
498 {
499 htab_binary_sizes sizes;
500 bfd *image;
501 sizes.text_ra = -1;
502 sizes.data_ra = -1;
503 sizes.text_base = -1;
504 sizes.data_base = -1;
505 sizes.text_bound = 0;
506 sizes.data_bound = 0;
507 sizes.me = me;
508
509 /* open the file */
510 image = bfd_openr(file_name, NULL);
511 if (image == NULL) {
512 bfd_perror("devices/pte");
513 device_error(me, "the file %s not loaded", file_name);
514 }
515
516 /* check it is valid */
517 if (!bfd_check_format(image, bfd_object)) {
518 bfd_close(image);
519 device_error(me, "the file %s has an invalid binary format", file_name);
520 }
521
522 /* determine the size of each of the files regions */
523 bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
524
525 /* if needed, determine the real addresses of the sections */
526 if (ra != -1) {
527 sizes.text_ra = ra;
528 sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
529 (sizes.text_bound - sizes.text_base));
530 }
531
532 DTRACE(htab, ("text map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
533 (unsigned long)sizes.text_base,
534 (unsigned long)sizes.text_bound,
535 (unsigned long)sizes.text_ra));
536 DTRACE(htab, ("data map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
537 (unsigned long)sizes.data_base,
538 (unsigned long)sizes.data_bound,
539 (unsigned long)sizes.data_ra));
540
541 /* check for and fix a botched image (text and data segments
542 overlap) */
543 if ((sizes.text_base <= sizes.data_base
544 && sizes.text_bound >= sizes.data_bound)
545 || (sizes.data_base <= sizes.text_base
546 && sizes.data_bound >= sizes.data_bound)
547 || (sizes.text_bound > sizes.data_base
548 && sizes.text_bound <= sizes.data_bound)
549 || (sizes.text_base >= sizes.data_base
550 && sizes.text_base < sizes.data_bound)) {
551 DTRACE(htab, ("text and data segment overlaped - using just data segment\n"));
552 /* check va->ra linear */
553 if ((sizes.text_base - sizes.text_ra)
554 != (sizes.data_base - sizes.data_ra))
555 device_error(me, "overlapping but missaligned text and data segments");
556 /* enlarge the data segment */
557 if (sizes.text_base < sizes.data_base)
558 sizes.data_base = sizes.text_base;
559 if (sizes.text_bound > sizes.data_bound)
560 sizes.data_bound = sizes.text_bound;
561 if (sizes.text_ra < sizes.data_ra)
562 sizes.data_ra = sizes.text_ra;
563 /* zap the text segment */
564 sizes.text_base = 0;
565 sizes.text_bound = 0;
566 sizes.text_ra = 0;
567 DTRACE(htab, ("common map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
568 (unsigned long)sizes.data_base,
569 (unsigned long)sizes.data_bound,
570 (unsigned long)sizes.data_ra));
571 }
572
573 /* set up virtual memory maps for each of the regions */
574 htab_map_region(me, memory, sizes.text_ra, sizes.text_base,
575 sizes.text_bound - sizes.text_base,
576 wimg, pp,
577 htaborg, htabmask);
578
579 htab_map_region(me, memory, sizes.data_ra, sizes.data_base,
580 sizes.data_bound - sizes.data_base,
581 wimg, pp,
582 htaborg, htabmask);
583
584 /* dma the sections into physical memory */
585 bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
586 }
587
588 static void
589 htab_init_data_callback(device *me)
590 {
591 device_instance *memory = NULL;
592 if (WITH_TARGET_WORD_BITSIZE != 32)
593 device_error(me, "only 32bit targets currently suported");
594
595 /* find memory device */
596 if (device_find_property(me, "claim") != NULL)
597 memory = tree_find_ihandle_property(me, "/chosen/memory");
598
599 /* for the htab, just allocate space for it */
600 if (strcmp(device_name(me), "htab") == 0) {
601 unsigned_word address = device_find_integer_property(me, "real-address");
602 unsigned_word length = device_find_integer_property(me, "nr-bytes");
603 unsigned_word base = claim_memory(me, memory, address, length);
604 if (base == -1 || base != address)
605 device_error(me, "cannot allocate hash table");
606 }
607
608 /* for the pte, do all the real work */
609 if (strcmp(device_name(me), "pte") == 0) {
610 unsigned32 htaborg;
611 unsigned32 htabmask;
612
613 htab_decode_hash_table(me, &htaborg, &htabmask);
614
615 if (device_find_property(me, "file-name") != NULL) {
616 /* map in a binary */
617 unsigned pte_wimg = device_find_integer_property(me, "wimg");
618 unsigned pte_pp = device_find_integer_property(me, "pp");
619 const char *file_name = device_find_string_property(me, "file-name");
620 if (device_find_property(me, "real-address") != NULL) {
621 unsigned32 pte_ra = device_find_integer_property(me, "real-address");
622 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
623 (unsigned long)pte_ra,
624 (unsigned long)pte_wimg,
625 (long)pte_pp,
626 file_name));
627 htab_map_binary(me, memory, pte_ra, pte_wimg, pte_pp, file_name,
628 htaborg, htabmask);
629 }
630 else {
631 DTRACE(htab, ("pte - wimg=%ld, pp=%ld, file-name=%s\n",
632 (unsigned long)pte_wimg,
633 (long)pte_pp,
634 file_name));
635 htab_map_binary(me, memory, -1, pte_wimg, pte_pp, file_name,
636 htaborg, htabmask);
637 }
638 }
639 else {
640 /* handle a normal mapping definition */
641 unsigned64 pte_va = 0;
642 unsigned32 pte_ra = device_find_integer_property(me, "real-address");
643 unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
644 unsigned pte_wimg = device_find_integer_property(me, "wimg");
645 unsigned pte_pp = device_find_integer_property(me, "pp");
646 signed_cell partial_va;
647 int i;
648 for (i = 0;
649 device_find_integer_array_property(me, "virtual-address", i, &partial_va);
650 i++) {
651 pte_va = (pte_va << WITH_TARGET_WORD_BITSIZE) | (unsigned_cell)partial_va;
652 }
653 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
654 (unsigned long)pte_ra,
655 (long)pte_wimg,
656 (long)pte_pp,
657 (unsigned long)pte_va,
658 (long)pte_nr_bytes));
659 htab_map_region(me, memory, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
660 htaborg, htabmask);
661 }
662 }
663 }
664
665
666 static device_callbacks const htab_callbacks = {
667 { NULL, htab_init_data_callback, },
668 { NULL, }, /* address */
669 { NULL, }, /* IO */
670 { passthrough_device_dma_read_buffer,
671 passthrough_device_dma_write_buffer, },
672 { NULL, }, /* interrupt */
673 { generic_device_unit_decode,
674 generic_device_unit_encode, },
675 };
676
677 const device_descriptor hw_htab_device_descriptor[] = {
678 { "htab", NULL, &htab_callbacks },
679 { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
680 { NULL },
681 };
682
683 #endif /* _HW_HTAB_C_ */
This page took 0.057551 seconds and 5 git commands to generate.