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 				 &current_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