Home | History | Annotate | Line # | Download | only in ppc
hw_htab.c revision 1.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 
     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
    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
    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 				 &current_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
    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
    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
    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
    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
    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
    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