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