Home | History | Annotate | Line # | Download | only in ppc
hw_htab.c revision 1.3.2.1
      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 #include "device.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   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
    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
    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
    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
    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   unsigned_word ra = bfd_get_section_lma (abfd, sec);
    397 
    398   /* skip the section if no memory to allocate */
    399   if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
    400     return;
    401 
    402   if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
    403       || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
    404     if (sizes->text_bound < vma + size)
    405       sizes->text_bound = ALIGN_PAGE(vma + size);
    406     if (sizes->text_base > vma)
    407       sizes->text_base = FLOOR_PAGE(vma);
    408     if (sizes->text_ra > ra)
    409       sizes->text_ra = FLOOR_PAGE(ra);
    410   }
    411   else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
    412 	   || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
    413     if (sizes->data_bound < vma + size)
    414       sizes->data_bound = ALIGN_PAGE(vma + size);
    415     if (sizes->data_base > vma)
    416       sizes->data_base = FLOOR_PAGE(vma);
    417     if (sizes->data_ra > ra)
    418       sizes->data_ra = FLOOR_PAGE(ra);
    419   }
    420 }
    421 
    422 static void
    423 htab_dma_binary(bfd *abfd,
    424 		sec_ptr sec,
    425 		PTR data)
    426 {
    427   htab_binary_sizes *sizes = (htab_binary_sizes*)data;
    428   void *section_init;
    429   unsigned_word section_vma;
    430   unsigned_word section_size;
    431   unsigned_word section_ra;
    432   device *me = sizes->me;
    433 
    434   /* skip the section if no memory to allocate */
    435   if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
    436     return;
    437 
    438   /* check/ignore any sections of size zero */
    439   section_size = bfd_get_section_size (sec);
    440   if (section_size == 0)
    441     return;
    442 
    443   /* if nothing to load, ignore this one */
    444   if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
    445     return;
    446 
    447   /* find where it is to go */
    448   section_vma = bfd_get_section_vma(abfd, sec);
    449   section_ra = 0;
    450   if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
    451       || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
    452     section_ra = (section_vma - sizes->text_base + sizes->text_ra);
    453   else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
    454     section_ra = (section_vma - sizes->data_base + sizes->data_ra);
    455   else
    456     return; /* just ignore it */
    457 
    458   DTRACE(htab,
    459 	 ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
    460 	  bfd_get_section_name(abfd, sec),
    461 	  (long)section_vma,
    462 	  (long)section_size,
    463 	  (long)section_ra,
    464 	  (long)bfd_get_section_flags(abfd, sec),
    465 	  bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
    466 	  bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
    467 	  bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
    468 	  bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
    469 	  bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
    470 	  ));
    471 
    472   /* dma in the sections data */
    473   section_init = zalloc(section_size);
    474   if (!bfd_get_section_contents(abfd,
    475 				sec,
    476 				section_init, 0,
    477 				section_size)) {
    478     bfd_perror("devices/pte");
    479     device_error(me, "no data loaded");
    480   }
    481   if (device_dma_write_buffer(device_parent(me),
    482 			      section_init,
    483 			      0 /*space*/,
    484 			      section_ra,
    485 			      section_size,
    486 			      1 /*violate_read_only*/)
    487       != section_size)
    488     device_error(me, "broken dma transfer");
    489   free(section_init); /* only free if load */
    490 }
    491 
    492 /* create a memory map from a binaries virtual addresses to a copy of
    493    the binary laid out linearly in memory */
    494 
    495 static void
    496 htab_map_binary(device *me,
    497 		device_instance *memory,
    498 		unsigned_word ra,
    499 		unsigned wimg,
    500 		unsigned pp,
    501 		const char *file_name,
    502 		unsigned32 htaborg,
    503 		unsigned32 htabmask)
    504 {
    505   htab_binary_sizes sizes;
    506   bfd *image;
    507   sizes.text_ra = -1;
    508   sizes.data_ra = -1;
    509   sizes.text_base = -1;
    510   sizes.data_base = -1;
    511   sizes.text_bound = 0;
    512   sizes.data_bound = 0;
    513   sizes.me = me;
    514 
    515   /* open the file */
    516   image = bfd_openr(file_name, NULL);
    517   if (image == NULL) {
    518     bfd_perror("devices/pte");
    519     device_error(me, "the file %s not loaded", file_name);
    520   }
    521 
    522   /* check it is valid */
    523   if (!bfd_check_format(image, bfd_object)) {
    524     bfd_close(image);
    525     device_error(me, "the file %s has an invalid binary format", file_name);
    526   }
    527 
    528   /* determine the size of each of the files regions */
    529   bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
    530 
    531   /* if needed, determine the real addresses of the sections */
    532   if (ra != -1) {
    533     sizes.text_ra = ra;
    534     sizes.data_ra = ALIGN_PAGE(sizes.text_ra +
    535 			       (sizes.text_bound - sizes.text_base));
    536   }
    537 
    538   DTRACE(htab, ("text map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
    539 		(unsigned long)sizes.text_base,
    540 		(unsigned long)sizes.text_bound,
    541 		(unsigned long)sizes.text_ra));
    542   DTRACE(htab, ("data map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
    543 		(unsigned long)sizes.data_base,
    544 		(unsigned long)sizes.data_bound,
    545 		(unsigned long)sizes.data_ra));
    546 
    547   /* check for and fix a botched image (text and data segments
    548      overlap) */
    549   if ((sizes.text_base <= sizes.data_base
    550        && sizes.text_bound >= sizes.data_bound)
    551       || (sizes.data_base <= sizes.text_base
    552 	  && sizes.data_bound >= sizes.text_bound)
    553       || (sizes.text_bound > sizes.data_base
    554 	  && sizes.text_bound <= sizes.data_bound)
    555       || (sizes.text_base >= sizes.data_base
    556 	  && sizes.text_base < sizes.data_bound)) {
    557     DTRACE(htab, ("text and data segment overlaped - using just data segment\n"));
    558     /* check va->ra linear */
    559     if ((sizes.text_base - sizes.text_ra)
    560 	!= (sizes.data_base - sizes.data_ra))
    561       device_error(me, "overlapping but missaligned text and data segments");
    562     /* enlarge the data segment */
    563     if (sizes.text_base < sizes.data_base)
    564       sizes.data_base = sizes.text_base;
    565     if (sizes.text_bound > sizes.data_bound)
    566       sizes.data_bound = sizes.text_bound;
    567     if (sizes.text_ra < sizes.data_ra)
    568       sizes.data_ra = sizes.text_ra;
    569     /* zap the text segment */
    570     sizes.text_base = 0;
    571     sizes.text_bound = 0;
    572     sizes.text_ra = 0;
    573     DTRACE(htab, ("common map - base=0x%lx bound=0x%lx-1 ra=0x%lx\n",
    574 		  (unsigned long)sizes.data_base,
    575 		  (unsigned long)sizes.data_bound,
    576 		  (unsigned long)sizes.data_ra));
    577   }
    578 
    579   /* set up virtual memory maps for each of the regions */
    580   if (sizes.text_bound - sizes.text_base > 0) {
    581     htab_map_region(me, memory, sizes.text_ra, sizes.text_base,
    582 		    sizes.text_bound - sizes.text_base,
    583 		    wimg, pp,
    584 		    htaborg, htabmask);
    585   }
    586 
    587   htab_map_region(me, memory, sizes.data_ra, sizes.data_base,
    588 		  sizes.data_bound - sizes.data_base,
    589 		  wimg, pp,
    590 		  htaborg, htabmask);
    591 
    592   /* dma the sections into physical memory */
    593   bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
    594 }
    595 
    596 static void
    597 htab_init_data_callback(device *me)
    598 {
    599   device_instance *memory = NULL;
    600   if (WITH_TARGET_WORD_BITSIZE != 32)
    601     device_error(me, "only 32bit targets currently suported");
    602 
    603   /* find memory device */
    604   if (device_find_property(me, "claim") != NULL)
    605     memory = tree_find_ihandle_property(me, "/chosen/memory");
    606 
    607   /* for the htab, just allocate space for it */
    608   if (strcmp(device_name(me), "htab") == 0) {
    609     unsigned_word address = device_find_integer_property(me, "real-address");
    610     unsigned_word length = device_find_integer_property(me, "nr-bytes");
    611     unsigned_word base = claim_memory(me, memory, address, length);
    612     if (base == -1 || base != address)
    613       device_error(me, "cannot allocate hash table");
    614   }
    615 
    616   /* for the pte, do all the real work */
    617   if (strcmp(device_name(me), "pte") == 0) {
    618     unsigned32 htaborg;
    619     unsigned32 htabmask;
    620 
    621     htab_decode_hash_table(me, &htaborg, &htabmask);
    622 
    623     if (device_find_property(me, "file-name") != NULL) {
    624       /* map in a binary */
    625       unsigned pte_wimg = device_find_integer_property(me, "wimg");
    626       unsigned pte_pp = device_find_integer_property(me, "pp");
    627       const char *file_name = device_find_string_property(me, "file-name");
    628       if (device_find_property(me, "real-address") != NULL) {
    629 	unsigned32 pte_ra = device_find_integer_property(me, "real-address");
    630 	DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, file-name=%s\n",
    631 		      (unsigned long)pte_ra,
    632 		      (unsigned long)pte_wimg,
    633 		      (long)pte_pp,
    634 		      file_name));
    635 	htab_map_binary(me, memory, pte_ra, pte_wimg, pte_pp, file_name,
    636 			htaborg, htabmask);
    637       }
    638       else {
    639 	DTRACE(htab, ("pte - wimg=%ld, pp=%ld, file-name=%s\n",
    640 		      (unsigned long)pte_wimg,
    641 		      (long)pte_pp,
    642 		      file_name));
    643 	htab_map_binary(me, memory, -1, pte_wimg, pte_pp, file_name,
    644 			htaborg, htabmask);
    645       }
    646     }
    647     else {
    648       /* handle a normal mapping definition */
    649       unsigned64 pte_va = 0;
    650       unsigned32 pte_ra = device_find_integer_property(me, "real-address");
    651       unsigned pte_nr_bytes = device_find_integer_property(me, "nr-bytes");
    652       unsigned pte_wimg = device_find_integer_property(me, "wimg");
    653       unsigned pte_pp = device_find_integer_property(me, "pp");
    654       signed_cell partial_va;
    655       int i;
    656       for (i = 0;
    657 	   device_find_integer_array_property(me, "virtual-address", i, &partial_va);
    658 	   i++) {
    659 	pte_va = (pte_va << WITH_TARGET_WORD_BITSIZE) | (unsigned_cell)partial_va;
    660       }
    661       DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
    662 		    (unsigned long)pte_ra,
    663 		    (long)pte_wimg,
    664 		    (long)pte_pp,
    665 		    (unsigned long)pte_va,
    666 		    (long)pte_nr_bytes));
    667       htab_map_region(me, memory, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
    668 		      htaborg, htabmask);
    669     }
    670   }
    671 }
    672 
    673 
    674 static device_callbacks const htab_callbacks = {
    675   { NULL, htab_init_data_callback, },
    676   { NULL, }, /* address */
    677   { NULL, }, /* IO */
    678   { passthrough_device_dma_read_buffer,
    679     passthrough_device_dma_write_buffer, },
    680   { NULL, }, /* interrupt */
    681   { generic_device_unit_decode,
    682     generic_device_unit_encode, },
    683 };
    684 
    685 const device_descriptor hw_htab_device_descriptor[] = {
    686   { "htab", NULL, &htab_callbacks },
    687   { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
    688   { NULL },
    689 };
    690 
    691 #endif /* _HW_HTAB_C_ */
    692