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 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
htab_decode_hash_table(device * me,unsigned32 * htaborg,unsigned32 * htabmask)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 if (htab_nr_bytes < 0x10000) {
221 device_error(parent, "htab size 0x%x less than 0x1000",
222 htab_nr_bytes);
223 }
224 for (n = htab_nr_bytes; n > 1; n = n / 2) {
225 if (n % 2 != 0)
226 device_error(parent, "htab size 0x%x not a power of two",
227 htab_nr_bytes);
228 }
229 *htaborg = htab_ra;
230 /* Position the HTABMASK ready for use against a hashed address and
231 not ready for insertion into SDR1.HTABMASK. */
232 *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
233 /* Check that the MASK and ADDRESS do not overlap. */
234 if ((htab_ra & (*htabmask)) != 0) {
235 device_error(parent, "htaborg 0x%lx not aligned to htabmask 0x%lx",
236 (unsigned long)*htaborg, (unsigned long)*htabmask);
237 }
238 DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
239 (unsigned long)*htaborg, (unsigned long)*htabmask));
240 }
241
242 static void
htab_map_page(device * me,unsigned_word ra,unsigned64 va,unsigned wimg,unsigned pp,unsigned32 htaborg,unsigned32 htabmask)243 htab_map_page(device *me,
244 unsigned_word ra,
245 unsigned64 va,
246 unsigned wimg,
247 unsigned pp,
248 unsigned32 htaborg,
249 unsigned32 htabmask)
250 {
251 /* keep everything left shifted so that the numbering is easier */
252 unsigned64 vpn = va << 12;
253 unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
254 unsigned32 vpage = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
255 unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
256 ^ EXTRACTED32(vpage, 0, 15),
257 7, 31-6);
258 int h;
259 for (h = 0; h < 2; h++) {
260 unsigned32 pteg = (htaborg | (hash & htabmask));
261 int pti;
262 for (pti = 0; pti < 8; pti++) {
263 unsigned32 pte = pteg + 8 * pti;
264 unsigned32 current_target_pte0;
265 unsigned32 current_pte0;
266 if (device_dma_read_buffer(device_parent(me),
267 ¤t_target_pte0,
268 0, /*space*/
269 pte,
270 sizeof(current_target_pte0)) != 4)
271 device_error(me, "failed to read a pte at 0x%lx", (unsigned long)pte);
272 current_pte0 = T2H_4(current_target_pte0);
273 if (MASKED32(current_pte0, 0, 0)) {
274 /* full pte, check it isn't already mapping the same virtual
275 address */
276 unsigned32 curr_vsid = INSERTED32(EXTRACTED32(current_pte0, 1, 24), 0, 23);
277 unsigned32 curr_api = INSERTED32(EXTRACTED32(current_pte0, 26, 31), 0, 5);
278 unsigned32 curr_h = EXTRACTED32(current_pte0, 25, 25);
279 if (curr_h == h
280 && curr_vsid == vsid
281 && curr_api == MASKED32(vpage, 0, 5))
282 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",
283 (unsigned long)va,
284 (unsigned long)ra,
285 (unsigned long)vsid,
286 h,
287 (unsigned long)vpage,
288 (unsigned long)hash,
289 (unsigned long)pteg,
290 pti * 8,
291 (unsigned long)current_pte0);
292 }
293 else {
294 /* empty pte fill it */
295 unsigned32 pte0 = (MASK32(0, 0)
296 | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
297 | INSERTED32(h, 25, 25)
298 | INSERTED32(EXTRACTED32(vpage, 0, 5), 26, 31));
299 unsigned32 target_pte0 = H2T_4(pte0);
300 unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
301 | INSERTED32(wimg, 25, 28)
302 | INSERTED32(pp, 30, 31));
303 unsigned32 target_pte1 = H2T_4(pte1);
304 if (device_dma_write_buffer(device_parent(me),
305 &target_pte0,
306 0, /*space*/
307 pte,
308 sizeof(target_pte0),
309 1/*ro?*/) != 4
310 || device_dma_write_buffer(device_parent(me),
311 &target_pte1,
312 0, /*space*/
313 pte + 4,
314 sizeof(target_pte1),
315 1/*ro?*/) != 4)
316 device_error(me, "failed to write a pte a 0x%lx", (unsigned long)pte);
317 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",
318 (unsigned long)va,
319 (unsigned long)ra,
320 (unsigned long)vsid,
321 h,
322 (unsigned long)vpage,
323 (unsigned long)hash,
324 (unsigned long)pteg,
325 pti * 8,
326 (unsigned long)pte0,
327 (unsigned long)pte1));
328 return;
329 }
330 }
331 /* re-hash */
332 hash = MASKED32(~hash, 0, 18);
333 }
334 }
335
336 static unsigned_word
claim_memory(device * me,device_instance * memory,unsigned_word ra,unsigned_word size)337 claim_memory(device *me,
338 device_instance *memory,
339 unsigned_word ra,
340 unsigned_word size)
341 {
342 unsigned32 args[3];
343 unsigned32 results[1];
344 int status;
345 args[0] = 0; /* alignment */
346 args[1] = size;
347 args[2] = ra;
348 status = device_instance_call_method(memory, "claim", 3, args, 1, results);
349 if (status != 0)
350 device_error(me, "failed to claim memory");
351 return results[0];
352 }
353
354 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)355 htab_map_region(device *me,
356 device_instance *memory,
357 unsigned_word pte_ra,
358 unsigned64 pte_va,
359 unsigned nr_bytes,
360 unsigned wimg,
361 unsigned pp,
362 unsigned32 htaborg,
363 unsigned32 htabmask)
364 {
365 unsigned_word ra;
366 unsigned64 va;
367 /* claim the memory */
368 if (memory != NULL)
369 claim_memory(me, memory, pte_ra, nr_bytes);
370 /* go through all pages and create a pte for each */
371 for (ra = pte_ra, va = pte_va;
372 ra < pte_ra + nr_bytes;
373 ra += 0x1000, va += 0x1000) {
374 htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
375 }
376 }
377
378 typedef struct _htab_binary_sizes {
379 unsigned_word text_ra;
380 unsigned_word text_base;
381 unsigned_word text_bound;
382 unsigned_word data_ra;
383 unsigned_word data_base;
384 unsigned data_bound;
385 device *me;
386 } htab_binary_sizes;
387
388 static void
htab_sum_binary(bfd * abfd,sec_ptr sec,PTR data)389 htab_sum_binary(bfd *abfd,
390 sec_ptr sec,
391 PTR data)
392 {
393 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
394 unsigned_word size = bfd_get_section_size (sec);
395 unsigned_word vma = bfd_get_section_vma (abfd, sec);
396 #define bfd_get_section_lma(abfd, sec) ((sec)->lma + 0)
397 unsigned_word ra = bfd_get_section_lma (abfd, sec);
398
399 /* skip the section if no memory to allocate */
400 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
401 return;
402
403 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
404 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
405 if (sizes->text_bound < vma + size)
406 sizes->text_bound = ALIGN_PAGE(vma + size);
407 if (sizes->text_base > vma)
408 sizes->text_base = FLOOR_PAGE(vma);
409 if (sizes->text_ra > ra)
410 sizes->text_ra = FLOOR_PAGE(ra);
411 }
412 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
413 || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
414 if (sizes->data_bound < vma + size)
415 sizes->data_bound = ALIGN_PAGE(vma + size);
416 if (sizes->data_base > vma)
417 sizes->data_base = FLOOR_PAGE(vma);
418 if (sizes->data_ra > ra)
419 sizes->data_ra = FLOOR_PAGE(ra);
420 }
421 }
422
423 static void
htab_dma_binary(bfd * abfd,sec_ptr sec,PTR data)424 htab_dma_binary(bfd *abfd,
425 sec_ptr sec,
426 PTR data)
427 {
428 htab_binary_sizes *sizes = (htab_binary_sizes*)data;
429 void *section_init;
430 unsigned_word section_vma;
431 unsigned_word section_size;
432 unsigned_word section_ra;
433 device *me = sizes->me;
434
435 /* skip the section if no memory to allocate */
436 if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
437 return;
438
439 /* check/ignore any sections of size zero */
440 section_size = bfd_get_section_size (sec);
441 if (section_size == 0)
442 return;
443
444 /* if nothing to load, ignore this one */
445 if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
446 return;
447
448 /* find where it is to go */
449 section_vma = bfd_get_section_vma(abfd, sec);
450 section_ra = 0;
451 if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
452 || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
453 section_ra = (section_vma - sizes->text_base + sizes->text_ra);
454 else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
455 section_ra = (section_vma - sizes->data_base + sizes->data_ra);
456 else
457 return; /* just ignore it */
458
459 DTRACE(htab,
460 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
461 bfd_get_section_name(abfd, sec),
462 (long)section_vma,
463 (long)section_size,
464 (long)section_ra,
465 (long)bfd_get_section_flags(abfd, sec),
466 bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
467 bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
468 bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
469 bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
470 bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
471 ));
472
473 /* dma in the sections data */
474 section_init = zalloc(section_size);
475 if (!bfd_get_section_contents(abfd,
476 sec,
477 section_init, 0,
478 section_size)) {
479 bfd_perror("devices/pte");
480 device_error(me, "no data loaded");
481 }
482 if (device_dma_write_buffer(device_parent(me),
483 section_init,
484 0 /*space*/,
485 section_ra,
486 section_size,
487 1 /*violate_read_only*/)
488 != section_size)
489 device_error(me, "broken dma transfer");
490 zfree(section_init); /* only free if load */
491 }
492
493 /* create a memory map from a binaries virtual addresses to a copy of
494 the binary laid out linearly in memory */
495
496 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)497 htab_map_binary(device *me,
498 device_instance *memory,
499 unsigned_word ra,
500 unsigned wimg,
501 unsigned pp,
502 const char *file_name,
503 unsigned32 htaborg,
504 unsigned32 htabmask)
505 {
506 htab_binary_sizes sizes;
507 bfd *image;
508 sizes.text_ra = -1;
509 sizes.data_ra = -1;
510 sizes.text_base = -1;
511 sizes.data_base = -1;
512 sizes.text_bound = 0;
513 sizes.data_bound = 0;
514 sizes.me = me;
515
516 /* open the file */
517 image = bfd_openr(file_name, NULL);
518 if (image == NULL) {
519 bfd_perror("devices/pte");
520 device_error(me, "the file %s not loaded", file_name);
521 }
522
523 /* check it is valid */
524 if (!bfd_check_format(image, bfd_object)) {
525 bfd_close(image);
526 device_error(me, "the file %s has an invalid binary format", file_name);
527 }
528
529 /* determine the size of each of the files regions */
530 bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
531
532 /* if needed, determine the real addresses of the sections */
533 if (ra != -1) {
534 sizes.text_ra = ra;
535 sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
536 (sizes.text_bound - sizes.text_base));
537 }
538
539 DTRACE(htab, ("text map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
540 (unsigned long)sizes.text_base,
541 (unsigned long)sizes.text_bound,
542 (unsigned long)sizes.text_ra));
543 DTRACE(htab, ("data map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
544 (unsigned long)sizes.data_base,
545 (unsigned long)sizes.data_bound,
546 (unsigned long)sizes.data_ra));
547
548 /* check for and fix a botched image (text and data segments
549 overlap) */
550 if ((sizes.text_base <= sizes.data_base
551 && sizes.text_bound >= sizes.data_bound)
552 || (sizes.data_base <= sizes.text_base
553 && sizes.data_bound >= sizes.data_bound)
554 || (sizes.text_bound > sizes.data_base
555 && sizes.text_bound <= sizes.data_bound)
556 || (sizes.text_base >= sizes.data_base
557 && sizes.text_base < sizes.data_bound)) {
558 DTRACE(htab, ("text and data segment overlaped - using just data segment\n"));
559 /* check va->ra linear */
560 if ((sizes.text_base - sizes.text_ra)
561 != (sizes.data_base - sizes.data_ra))
562 device_error(me, "overlapping but missaligned text and data segments");
563 /* enlarge the data segment */
564 if (sizes.text_base < sizes.data_base)
565 sizes.data_base = sizes.text_base;
566 if (sizes.text_bound > sizes.data_bound)
567 sizes.data_bound = sizes.text_bound;
568 if (sizes.text_ra < sizes.data_ra)
569 sizes.data_ra = sizes.text_ra;
570 /* zap the text segment */
571 sizes.text_base = 0;
572 sizes.text_bound = 0;
573 sizes.text_ra = 0;
574 DTRACE(htab, ("common map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
575 (unsigned long)sizes.data_base,
576 (unsigned long)sizes.data_bound,
577 (unsigned long)sizes.data_ra));
578 }
579
580 /* set up virtual memory maps for each of the regions */
581 if (sizes.text_bound - sizes.text_base > 0) {
582 htab_map_region(me, memory, sizes.text_ra, sizes.text_base,
583 sizes.text_bound - sizes.text_base,
584 wimg, pp,
585 htaborg, htabmask);
586 }
587
588 htab_map_region(me, memory, sizes.data_ra, sizes.data_base,
589 sizes.data_bound - sizes.data_base,
590 wimg, pp,
591 htaborg, htabmask);
592
593 /* dma the sections into physical memory */
594 bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
595 }
596
597 static void
htab_init_data_callback(device * me)598 htab_init_data_callback(device *me)
599 {
600 device_instance *memory = NULL;
601 if (WITH_TARGET_WORD_BITSIZE != 32)
602 device_error(me, "only 32bit targets currently suported");
603
604 /* find memory device */
605 if (device_find_property(me, "claim") != NULL)
606 memory = tree_find_ihandle_property(me, "/chosen/memory");
607
608 /* for the htab, just allocate space for it */
609 if (strcmp(device_name(me), "htab") == 0) {
610 unsigned_word address = device_find_integer_property(me, "real-address");
611 unsigned_word length = device_find_integer_property(me, "nr-bytes");
612 unsigned_word base = claim_memory(me, memory, address, length);
613 if (base == -1 || base != address)
614 device_error(me, "cannot allocate hash table");
615 }
616
617 /* for the pte, do all the real work */
618 if (strcmp(device_name(me), "pte") == 0) {
619 unsigned32 htaborg;
620 unsigned32 htabmask;
621
622 htab_decode_hash_table(me, &htaborg, &htabmask);
623
624 if (device_find_property(me, "file-name") != NULL) {
625 /* map in a binary */
626 unsigned pte_wimg = device_find_integer_property(me, "wimg");
627 unsigned pte_pp = device_find_integer_property(me, "pp");
628 const char *file_name = device_find_string_property(me, "file-name");
629 if (device_find_property(me, "real-address") != NULL) {
630 unsigned32 pte_ra = device_find_integer_property(me, "real-address");
631 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
632 (unsigned long)pte_ra,
633 (unsigned long)pte_wimg,
634 (long)pte_pp,
635 file_name));
636 htab_map_binary(me, memory, pte_ra, pte_wimg, pte_pp, file_name,
637 htaborg, htabmask);
638 }
639 else {
640 DTRACE(htab, ("pte - wimg=%ld, pp=%ld, file-name=%s\n",
641 (unsigned long)pte_wimg,
642 (long)pte_pp,
643 file_name));
644 htab_map_binary(me, memory, -1, pte_wimg, pte_pp, file_name,
645 htaborg, htabmask);
646 }
647 }
648 else {
649 /* handle a normal mapping definition */
650 unsigned64 pte_va = 0;
651 unsigned32 pte_ra = device_find_integer_property(me, "real-address");
652 unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
653 unsigned pte_wimg = device_find_integer_property(me, "wimg");
654 unsigned pte_pp = device_find_integer_property(me, "pp");
655 signed_cell partial_va;
656 int i;
657 for (i = 0;
658 device_find_integer_array_property(me, "virtual-address", i, &partial_va);
659 i++) {
660 pte_va = (pte_va << WITH_TARGET_WORD_BITSIZE) | (unsigned_cell)partial_va;
661 }
662 DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
663 (unsigned long)pte_ra,
664 (long)pte_wimg,
665 (long)pte_pp,
666 (unsigned long)pte_va,
667 (long)pte_nr_bytes));
668 htab_map_region(me, memory, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
669 htaborg, htabmask);
670 }
671 }
672 }
673
674
675 static device_callbacks const htab_callbacks = {
676 { NULL, htab_init_data_callback, },
677 { NULL, }, /* address */
678 { NULL, }, /* IO */
679 { passthrough_device_dma_read_buffer,
680 passthrough_device_dma_write_buffer, },
681 { NULL, }, /* interrupt */
682 { generic_device_unit_decode,
683 generic_device_unit_encode, },
684 };
685
686 const device_descriptor hw_htab_device_descriptor[] = {
687 { "htab", NULL, &htab_callbacks },
688 { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
689 { NULL },
690 };
691
692 #endif /* _HW_HTAB_C_ */
693