Subversion Repositories HelenOS-historic

Rev

Rev 1782 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (C) 2005 Martin Decky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include "ofw.h"
  30. #include <printf.h>
  31. #include <asm.h>
  32. #include <types.h>
  33.  
  34. uintptr_t ofw_cif;
  35.  
  36. phandle ofw_chosen;
  37. ihandle ofw_stdout;
  38. phandle ofw_root;
  39. ihandle ofw_mmu;
  40. phandle ofw_memory;
  41. phandle ofw_aliases;
  42.  
  43. static unsigned long ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...)
  44. {
  45.     va_list list;
  46.     ofw_args_t args;
  47.     int i;
  48.    
  49.     args.service = service;
  50.     args.nargs = nargs;
  51.     args.nret = nret;
  52.    
  53.     va_start(list, rets);
  54.     for (i = 0; i < nargs; i++)
  55.         args.args[i] = va_arg(list, ofw_arg_t);
  56.     va_end(list);
  57.    
  58.     for (i = 0; i < nret; i++)
  59.         args.args[i + nargs] = 0;
  60.    
  61.     (void) ofw(&args);
  62.  
  63.     for (i = 1; i < nret; i++)
  64.         rets[i - 1] = args.args[i + nargs];
  65.  
  66.     return args.args[nargs];
  67. }
  68.  
  69.  
  70. phandle ofw_find_device(const char *name)
  71. {
  72.     return ofw_call("finddevice", 1, 1, NULL, name);
  73. }
  74.  
  75.  
  76. int ofw_get_property(const phandle device, const char *name, const void *buf, const int buflen)
  77. {
  78.     return ofw_call("getprop", 4, 1, NULL, device, name, buf, buflen);
  79. }
  80.  
  81.  
  82. static unsigned int ofw_get_address_cells(const phandle device)
  83. {
  84.     unsigned int ret;
  85.    
  86.     if (ofw_get_property(device, "#address-cells", &ret, sizeof(ret)) <= 0)
  87.         if (ofw_get_property(ofw_root, "#address-cells", &ret, sizeof(ret)) <= 0)
  88.             ret = 1;
  89.    
  90.     return ret;
  91. }
  92.  
  93.  
  94. static unsigned int ofw_get_size_cells(const phandle device)
  95. {
  96.     unsigned int ret;
  97.    
  98.     if (ofw_get_property(device, "#size-cells", &ret, sizeof(ret)) <= 0)
  99.         if (ofw_get_property(ofw_root, "#size-cells", &ret, sizeof(ret)) <= 0)
  100.             ret = 1;
  101.    
  102.     return ret;
  103. }
  104.  
  105.  
  106. static ihandle ofw_open(const char *name)
  107. {
  108.     return ofw_call("open", 1, 1, NULL, name);
  109. }
  110.  
  111.  
  112. void init(void)
  113. {
  114.     ofw_chosen = ofw_find_device("/chosen");
  115.     if (ofw_chosen == -1)
  116.         halt();
  117.    
  118.     if (ofw_get_property(ofw_chosen, "stdout",  &ofw_stdout, sizeof(ofw_stdout)) <= 0)
  119.         ofw_stdout = 0;
  120.    
  121.     ofw_root = ofw_find_device("/");
  122.     if (ofw_root == -1) {
  123.         puts("\r\nError: Unable to find / device, halted.\r\n");
  124.         halt();
  125.     }
  126.    
  127.     if (ofw_get_property(ofw_chosen, "mmu",  &ofw_mmu, sizeof(ofw_mmu)) <= 0) {
  128.         puts("\r\nError: Unable to get mmu property, halted.\r\n");
  129.         halt();
  130.     }
  131.    
  132.     ofw_memory = ofw_find_device("/memory");
  133.     if (ofw_memory == -1) {
  134.         puts("\r\nError: Unable to find /memory device, halted.\r\n");
  135.         halt();
  136.     }
  137.    
  138.     ofw_aliases = ofw_find_device("/aliases");
  139.     if (ofw_aliases == -1) {
  140.         puts("\r\nError: Unable to find /aliases device, halted.\r\n");
  141.         halt();
  142.     }
  143. }
  144.  
  145.  
  146. void ofw_write(const char *str, const int len)
  147. {
  148.     if (ofw_stdout == 0)
  149.         return;
  150.    
  151.     ofw_call("write", 3, 1, NULL, ofw_stdout, str, len);
  152. }
  153.  
  154.  
  155. void *ofw_translate(const void *virt)
  156. {
  157.     ofw_arg_t result[4];
  158.     int shift;
  159.  
  160.     if (ofw_call("call-method", 3, 5, result, "translate", ofw_mmu, virt) != 0) {
  161.         puts("Error: MMU method translate() failed, halting.\n");
  162.         halt();
  163.     }
  164.  
  165.     if (ofw_translate_failed(result[0]))
  166.         return NULL;
  167.  
  168.     if (sizeof(unative_t) == 8)
  169.         shift = 32;
  170.     else
  171.         shift = 0;
  172.        
  173.     return (void *) ((result[2]<<shift)|result[3]);
  174. }
  175.  
  176. void *ofw_claim(const void *virt, const int len)
  177. {
  178.     ofw_arg_t retaddr;
  179.     int shift;
  180.  
  181.     if (ofw_call("call-method", 5, 2, &retaddr, "claim", ofw_mmu, 0, len, virt) != 0) {
  182.         puts("Error: MMU method claim() failed, halting.\n");
  183.         halt();
  184.     }
  185.  
  186.     return (void *) retaddr;
  187. }
  188.  
  189. int ofw_map(const void *phys, const void *virt, const int size, const int mode)
  190. {
  191.     uintptr_t phys_hi, phys_lo;
  192.  
  193.     if (sizeof(unative_t) == 8) {
  194.         int shift = 32;
  195.         phys_hi = (uintptr_t) phys >> shift;
  196.         phys_lo = (uintptr_t) phys & 0xffffffff;
  197.     } else {
  198.         phys_hi = 0;
  199.         phys_lo = (uintptr_t) phys;
  200.     }
  201.  
  202.     return ofw_call("call-method", 7, 1, NULL, "map", ofw_mmu, mode, size, virt,
  203.         phys_hi, phys_lo);
  204. }
  205.  
  206.  
  207. int ofw_memmap(memmap_t *map)
  208. {
  209.     unsigned long buf[BUF_SIZE];
  210.     int ret = ofw_get_property(ofw_memory, "reg", buf, sizeof(buf));
  211.     if (ret <= 0)
  212.         return false;
  213.        
  214.     unsigned int ac = ofw_get_address_cells(ofw_memory);
  215.     unsigned int sc = ofw_get_size_cells(ofw_memory);
  216.    
  217.     int pos;
  218.     map->total = 0;
  219.     map->count = 0;
  220.     for (pos = 0; (pos < ret / sizeof(unsigned long)) && (map->count < MEMMAP_MAX_RECORDS); pos += ac + sc) {
  221.         void * start = (void *) buf[pos + ac - 1];
  222.         unsigned int size = buf[pos + ac + sc - 1];
  223.        
  224.         if (size > 0) {
  225.             map->zones[map->count].start = start;
  226.             map->zones[map->count].size = size;
  227.             map->count++;
  228.             map->total += size;
  229.         }
  230.     }
  231. }
  232.  
  233.  
  234. int ofw_screen(screen_t *screen)
  235. {
  236.     char device_name[BUF_SIZE];
  237.    
  238.     if (ofw_get_property(ofw_aliases, "screen", device_name, sizeof(device_name)) <= 0)
  239.         return false;
  240.    
  241.     phandle device = ofw_find_device(device_name);
  242.     if (device == -1)
  243.         return false;
  244.    
  245.     if (ofw_get_property(device, "address", &screen->addr, sizeof(screen->addr)) <= 0)
  246.         return false;
  247.    
  248.     if (ofw_get_property(device, "width", &screen->width, sizeof(screen->width)) <= 0)
  249.         return false;
  250.    
  251.     if (ofw_get_property(device, "height", &screen->height, sizeof(screen->height)) <= 0)
  252.         return false;
  253.    
  254.     if (ofw_get_property(device, "depth", &screen->bpp, sizeof(screen->bpp)) <= 0)
  255.         return false;
  256.    
  257.     if (ofw_get_property(device, "linebytes", &screen->scanline, sizeof(screen->scanline)) <= 0)
  258.         return false;
  259.    
  260.     return true;
  261. }
  262.