Subversion Repositories HelenOS-historic

Rev

Rev 1395 | Rev 1771 | Go to most recent revision | 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 "asm.h"
  31. #include "printf.h"
  32.  
  33. #define MAX_OFW_ARGS    10
  34. #define BUF_SIZE        1024
  35.  
  36. typedef unsigned int ofw_arg_t;
  37. typedef unsigned int ihandle;
  38. typedef unsigned int phandle;
  39.  
  40. /** OpenFirmware command structure
  41.  *
  42.  */
  43. typedef struct {
  44.     const char *service;          /**< Command name */
  45.     unsigned int nargs;           /**< Number of in arguments */
  46.     unsigned int nret;            /**< Number of out arguments */
  47.     ofw_arg_t args[MAX_OFW_ARGS]; /**< List of arguments */
  48. } ofw_args_t;
  49.  
  50. typedef void (*ofw_entry)(ofw_args_t *);
  51.  
  52.  
  53. ofw_entry ofw;
  54.  
  55. phandle ofw_chosen;
  56. ihandle ofw_stdout;
  57. phandle ofw_root;
  58. ihandle ofw_mmu;
  59. phandle ofw_memory;
  60. phandle ofw_aliases;
  61.  
  62.  
  63. static int ofw_call(const char *service, const int nargs, const int nret, ofw_arg_t *rets, ...)
  64. {
  65.     va_list list;
  66.     ofw_args_t args;
  67.     int i;
  68.    
  69.     args.service = service;
  70.     args.nargs = nargs;
  71.     args.nret = nret;
  72.    
  73.     va_start(list, rets);
  74.     for (i = 0; i < nargs; i++)
  75.         args.args[i] = va_arg(list, ofw_arg_t);
  76.     va_end(list);
  77.    
  78.     for (i = 0; i < nret; i++)
  79.         args.args[i + nargs] = 0;
  80.    
  81.     ofw(&args);
  82.    
  83.     for (i = 1; i < nret; i++)
  84.         rets[i - 1] = args.args[i + nargs];
  85.    
  86.     return args.args[nargs];
  87. }
  88.  
  89.  
  90. static phandle ofw_find_device(const char *name)
  91. {
  92.     return ofw_call("finddevice", 1, 1, NULL, name);
  93. }
  94.  
  95.  
  96. static int ofw_get_property(const phandle device, const char *name, const void *buf, const int buflen)
  97. {
  98.     return ofw_call("getprop", 4, 1, NULL, device, name, buf, buflen);
  99. }
  100.  
  101.  
  102. static unsigned int ofw_get_address_cells(const phandle device)
  103. {
  104.     unsigned int ret;
  105.    
  106.     if (ofw_get_property(device, "#address-cells", &ret, sizeof(ret)) <= 0)
  107.         if (ofw_get_property(ofw_root, "#address-cells", &ret, sizeof(ret)) <= 0)
  108.             ret = 1;
  109.    
  110.     return ret;
  111. }
  112.  
  113.  
  114. static unsigned int ofw_get_size_cells(const phandle device)
  115. {
  116.     unsigned int ret;
  117.    
  118.     if (ofw_get_property(device, "#size-cells", &ret, sizeof(ret)) <= 0)
  119.         if (ofw_get_property(ofw_root, "#size-cells", &ret, sizeof(ret)) <= 0)
  120.             ret = 1;
  121.    
  122.     return ret;
  123. }
  124.  
  125.  
  126. static ihandle ofw_open(const char *name)
  127. {
  128.     return ofw_call("open", 1, 1, NULL, name);
  129. }
  130.  
  131.  
  132. void init(void)
  133. {
  134.     ofw_chosen = ofw_find_device("/chosen");
  135.     if (ofw_chosen == -1)
  136.         halt();
  137.    
  138.     if (ofw_get_property(ofw_chosen, "stdout",  &ofw_stdout, sizeof(ofw_stdout)) <= 0)
  139.         ofw_stdout = 0;
  140.    
  141.     ofw_root = ofw_find_device("/");
  142.     if (ofw_root == -1) {
  143.         puts("\r\nError: Unable to find / device, halted.\r\n");
  144.         halt();
  145.     }
  146.    
  147.     if (ofw_get_property(ofw_chosen, "mmu",  &ofw_mmu, sizeof(ofw_mmu)) <= 0) {
  148.         puts("\r\nError: Unable to get mmu property, halted.\r\n");
  149.         halt();
  150.     }
  151.    
  152.     ofw_memory = ofw_find_device("/memory");
  153.     if (ofw_memory == -1) {
  154.         puts("\r\nError: Unable to find /memory device, halted.\r\n");
  155.         halt();
  156.     }
  157.    
  158.     ofw_aliases = ofw_find_device("/aliases");
  159.     if (ofw_aliases == -1) {
  160.         puts("\r\nError: Unable to find /aliases device, halted.\r\n");
  161.         halt();
  162.     }
  163. }
  164.  
  165.  
  166. void ofw_write(const char *str, const long len)
  167. {
  168.     if (ofw_stdout == 0)
  169.         return;
  170.    
  171.     ofw_call("write", 3, 1, NULL, ofw_stdout, str, len);
  172. }
  173.  
  174.  
  175. void *ofw_translate(const void *virt)
  176. {
  177.     ofw_arg_t result[3];
  178.    
  179.     if (ofw_call("call-method", 4, 4, result, "translate", ofw_mmu, (unsigned long) virt, 1) != 0) {
  180.         puts("Error: MMU method translate() failed, halting.\n");
  181.         halt();
  182.     }
  183.     return (void *) (unsigned long) result[2];
  184. }
  185.  
  186.  
  187. int ofw_map(const void *phys, const void *virt, const long size, const int mode)
  188. {
  189.     return ofw_call("call-method", 6, 1, NULL, "map", ofw_mmu, mode, size, virt, phys);
  190. }
  191.  
  192.  
  193. int ofw_memmap(memmap_t *map)
  194. {
  195.     unsigned int buf[BUF_SIZE];
  196.     int ret = ofw_get_property(ofw_memory, "reg", buf, sizeof(unsigned int) * BUF_SIZE);
  197.     if (ret <= 0)
  198.         return false;
  199.        
  200.     unsigned int ac = ofw_get_address_cells(ofw_memory);
  201.     unsigned int sc = ofw_get_size_cells(ofw_memory);
  202.    
  203.     int pos;
  204.     map->total = 0;
  205.     map->count = 0;
  206.     for (pos = 0; (pos < ret / sizeof(unsigned int)) && (map->count < MEMMAP_MAX_RECORDS); pos += ac + sc) {
  207.         void * start = (void *) (unsigned long) buf[pos + ac - 1];
  208.         unsigned int size = buf[pos + ac + sc - 1];
  209.        
  210.         if (size > 0) {
  211.             map->zones[map->count].start = start;
  212.             map->zones[map->count].size = size;
  213.             map->count++;
  214.             map->total += size;
  215.         }
  216.     }
  217. }
  218.  
  219.  
  220. int ofw_screen(screen_t *screen)
  221. {
  222.     char device_name[BUF_SIZE];
  223.    
  224.     if (ofw_get_property(ofw_aliases, "screen", device_name, sizeof(char) * BUF_SIZE) <= 0)
  225.         return false;
  226.    
  227.     phandle device = ofw_find_device(device_name);
  228.     if (device == -1)
  229.         return false;
  230.    
  231.     if (ofw_get_property(device, "address", &screen->addr, sizeof(screen->addr)) <= 0)
  232.         return false;
  233.    
  234.     if (ofw_get_property(device, "width", &screen->width, sizeof(screen->width)) <= 0)
  235.         return false;
  236.    
  237.     if (ofw_get_property(device, "height", &screen->height, sizeof(screen->height)) <= 0)
  238.         return false;
  239.    
  240.     if (ofw_get_property(device, "depth", &screen->bpp, sizeof(screen->bpp)) <= 0)
  241.         return false;
  242.    
  243.     if (ofw_get_property(device, "linebytes", &screen->scanline, sizeof(screen->scanline)) <= 0)
  244.         return false;
  245.    
  246.     return true;
  247. }
  248.