Changeset 1787e527 in mainline for boot/genarch/ofw.c


Ignore:
Timestamp:
2009-11-16T21:22:54Z (14 years ago)
Author:
Lenka Trochtova <trochtova.lenka@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5ebdf94
Parents:
fcbd1be (diff), 9c70ed6 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merged with head (unstable)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • boot/genarch/ofw.c

    rfcbd1be r1787e527  
    3232#include <asm.h>
    3333#include <types.h>
     34#include <string.h>
     35
     36#define RED(i)    (((i) >> 5) & ((1 << 3) - 1))
     37#define GREEN(i)  (((i) >> 3) & ((1 << 2) - 1))
     38#define BLUE(i)   ((i) & ((1 << 3) - 1))
     39#define CLIP(i)   ((i) <= 255 ? (i) : 255)
    3440
    3541uintptr_t ofw_cif;
     
    4147ihandle ofw_memory_prop;
    4248phandle ofw_memory;
    43 phandle ofw_aliases;
    4449
    4550void ofw_init(void)
     
    6974                halt();
    7075        }
    71 
     76       
    7277        ofw_memory = ofw_find_device("/memory");
    7378        if (ofw_memory == -1) {
     
    7580                halt();
    7681        }
    77        
    78         ofw_aliases = ofw_find_device("/aliases");
    79         if (ofw_aliases == -1) {
    80                 puts("\r\nError: Unable to find /aliases device, halted.\r\n");
    81                 halt();
    82         }
    8382}
    8483
    8584/** Perform a call to OpenFirmware client interface.
    8685 *
    87  * @param service       String identifying the service requested.
    88  * @param nargs         Number of input arguments.
    89  * @param nret          Number of output arguments. This includes the return
    90  *                      value.
    91  * @param rets          Buffer for output arguments or NULL. The buffer must
    92  *                      accommodate nret - 1 items.
    93  *
    94  * @return              Return value returned by the client interface.
     86 * @param service String identifying the service requested.
     87 * @param nargs   Number of input arguments.
     88 * @param nret    Number of output arguments. This includes the return
     89 *                value.
     90 * @param rets    Buffer for output arguments or NULL. The buffer must
     91 *                accommodate nret - 1 items.
     92 *
     93 * @return Return value returned by the client interface.
     94 *
    9595 */
    9696unsigned long
     
    127127}
    128128
    129 int
    130 ofw_get_property(const phandle device, const char *name, void *buf,
     129int ofw_get_property(const phandle device, const char *name, void *buf,
    131130    const int buflen)
    132131{
     
    161160}
    162161
    163 
    164162unsigned int ofw_get_size_cells(const phandle device)
    165163{
     
    221219}
    222220
    223 void *ofw_claim_virt(const void *virt, const int len)
     221void *ofw_claim_virt(const void *virt, const unsigned int len)
    224222{
    225223        ofw_arg_t retaddr;
     
    234232}
    235233
    236 void *ofw_claim_phys(const void *phys, const int len)
    237 {
    238         ofw_arg_t retaddr[2];
    239         int shift;
    240 
     234static void *ofw_claim_phys_internal(const void *phys, const unsigned int len, const unsigned int alignment)
     235{
     236        /*
     237         * Note that the return value check will help
     238         * us to discover conflicts between OpenFirmware
     239         * allocations and our use of physical memory.
     240         * It is better to detect collisions here
     241         * than to cope with weird errors later.
     242         *
     243         * So this is really not to make the loader
     244         * more generic; it is here for debugging
     245         * purposes.
     246         */
     247       
    241248        if (sizeof(unative_t) == 8) {
    242                 shift = 32;
     249                ofw_arg_t retaddr[2];
     250                int shift = 32;
     251               
    243252                if (ofw_call("call-method", 6, 3, retaddr, "claim",
    244                     ofw_memory_prop, 0, len, ((uintptr_t) phys) >> shift,
     253                    ofw_memory_prop, alignment, len, ((uintptr_t) phys) >> shift,
    245254                    ((uintptr_t) phys) & ((uint32_t) -1)) != 0) {
    246                         /*
    247                          * Note that this will help us to discover
    248                          * conflicts between OpenFirmware allocations
    249                          * and our use of physical memory.
    250                          * It is better to detect collisions here
    251                          * than to cope with weird errors later.
    252                          *
    253                          * So this is really not to make the loader
    254                          * more generic; it is here for debugging
    255                          * purposes.
    256                          */
    257255                        puts("Error: memory method claim() failed, halting.\n");
    258256                        halt();
    259257                }
     258               
     259                return (void *) ((retaddr[0] << shift) | retaddr[1]);
    260260        } else {
    261                 shift = 0;
    262                 /*
    263                  * FIXME: the number of arguments is probably different...
    264                  */
    265                 puts("Error: 32-bit ofw_claim_phys not implemented.\n");
    266                 halt();
    267         }
    268 
    269         return (void *) ((retaddr[0] << shift) | retaddr[1]);
    270 }
    271 
    272 int ofw_map(const void *phys, const void *virt, const int size, const int mode)
     261                ofw_arg_t retaddr[1];
     262               
     263                if (ofw_call("call-method", 5, 2, retaddr, "claim",
     264                    ofw_memory_prop, alignment, len, (uintptr_t) phys) != 0) {
     265                        puts("Error: memory method claim() failed, halting.\n");
     266                        halt();
     267                }
     268               
     269                return (void *) retaddr[0];
     270        }
     271}
     272
     273void *ofw_claim_phys(const void *phys, const unsigned int len)
     274{
     275        return ofw_claim_phys_internal(phys, len, 0);
     276}
     277
     278void *ofw_claim_phys_any(const unsigned int len, const unsigned int alignment)
     279{
     280        return ofw_claim_phys_internal(NULL, len, alignment);
     281}
     282
     283int ofw_map(const void *phys, const void *virt, const unsigned int size, const int mode)
    273284{
    274285        uintptr_t phys_hi, phys_lo;
     
    314325
    315326                /*
    316                  * This is a hot fix of the issue which occurs on machines
    317                  * where there are holes in the physical memory (such as
    318                  * SunBlade 1500). Should we detect a hole in the physical
    319                  * memory, we will ignore any memory detected behind
    320                  * the hole and pretend the hole does not exist.
     327                 * This is a hot fix of the issue which occurs on machines
     328                 * where there are holes in the physical memory (such as
     329                 * SunBlade 1500). Should we detect a hole in the physical
     330                 * memory, we will ignore any memory detected behind
     331                 * the hole and pretend the hole does not exist.
    321332                 */
    322333                if ((map->count > 0) && (map->zones[map->count - 1].start +
     
    335346}
    336347
    337 int ofw_screen(screen_t *screen)
    338 {
    339         char device_name[BUF_SIZE];
    340         uint32_t virtaddr;
    341        
    342         if (ofw_get_property(ofw_aliases, "screen", device_name,
    343             sizeof(device_name)) <= 0)
    344                 return false;
    345        
    346         phandle device = ofw_find_device(device_name);
    347         if (device == -1)
    348                 return false;
    349        
    350         if (ofw_get_property(device, "address", &virtaddr,
    351             sizeof(virtaddr)) <= 0)
    352                 return false;
    353 
    354         screen->addr = (void *) ((uintptr_t) virtaddr);
    355 
    356         if (ofw_get_property(device, "width", &screen->width,
    357             sizeof(screen->width)) <= 0)
    358                 return false;
    359        
    360         if (ofw_get_property(device, "height", &screen->height,
    361             sizeof(screen->height)) <= 0)
    362                 return false;
    363        
    364         if (ofw_get_property(device, "depth", &screen->bpp,
    365             sizeof(screen->bpp)) <= 0)
    366                 return false;
    367        
    368         if (ofw_get_property(device, "linebytes", &screen->scanline,
    369             sizeof(screen->scanline)) <= 0)
    370                 return false;
    371        
    372         return true;
    373 }
    374 
    375 #define RED(i)    (((i) >> 5) & ((1 << 3) - 1))
    376 #define GREEN(i)  (((i) >> 3) & ((1 << 2) - 1))
    377 #define BLUE(i)   ((i) & ((1 << 3) - 1))
    378 #define CLIP(i)   ((i) <= 255 ? (i) : 255)
    379 
    380 
    381 /**
    382  * Sets up the palette for the 8-bit color depth configuration so that the
    383  * 3:2:3 color scheme can be used. Checks that setting the palette makes sense
    384  * (appropriate nodes exist in the OBP tree and the color depth is not greater
     348static void ofw_setup_screen(phandle handle)
     349{
     350        /* Check for device type */
     351        char device_type[OFW_TREE_PROPERTY_MAX_VALUELEN];
     352        if (ofw_get_property(handle, "device_type", device_type, OFW_TREE_PROPERTY_MAX_VALUELEN) <= 0)
     353                return;
     354       
     355        device_type[OFW_TREE_PROPERTY_MAX_VALUELEN - 1] = '\0';
     356        if (strcmp(device_type, "display") != 0)
     357                return;
     358       
     359        /* Check for 8 bit depth */
     360        uint32_t depth;
     361        if (ofw_get_property(handle, "depth", &depth, sizeof(uint32_t)) <= 0)
     362                depth = 0;
     363       
     364        /* Get device path */
     365        static char path[OFW_TREE_PATH_MAX_LEN + 1];
     366        size_t len = ofw_package_to_path(handle, path, OFW_TREE_PATH_MAX_LEN);
     367        if (len == -1)
     368                return;
     369       
     370        path[len] = '\0';
     371       
     372        /* Open the display to initialize it */
     373        ihandle screen = ofw_open(path);
     374        if (screen == -1)
     375                return;
     376       
     377        if (depth == 8) {
     378                /* Setup the palette so that the (inverted) 3:2:3 scheme is usable */
     379                unsigned int i;
     380                for (i = 0; i < 256; i++) {
     381                        ofw_call("call-method", 6, 1, NULL, "color!", screen,
     382                            255 - i, CLIP(BLUE(i) * 37), GREEN(i) * 85, CLIP(RED(i) * 37));
     383                }
     384        }
     385}
     386
     387static void ofw_setup_screens_internal(phandle current)
     388{
     389        while ((current != 0) && (current != -1)) {
     390                ofw_setup_screen(current);
     391               
     392                /*
     393                 * Recursively process the potential child node.
     394                 */
     395                phandle child = ofw_get_child_node(current);
     396                if ((child != 0) && (child != -1))
     397                        ofw_setup_screens_internal(child);
     398               
     399                /*
     400                 * Iteratively process the next peer node.
     401                 * Note that recursion is a bad idea here.
     402                 * Due to the topology of the OpenFirmware device tree,
     403                 * the nesting of peer nodes could be to wide and the
     404                 * risk of overflowing the stack is too real.
     405                 */
     406                phandle peer = ofw_get_peer_node(current);
     407                if ((peer != 0) && (peer != -1)) {
     408                        current = peer;
     409                        /*
     410                         * Process the peer in next iteration.
     411                         */
     412                        continue;
     413                }
     414               
     415                /*
     416                 * No more peers on this level.
     417                 */
     418                break;
     419        }
     420}
     421
     422/** Setup all screens which can be detected.
     423 *
     424 * Open all screens which can be detected and set up the palette for the 8-bit
     425 * color depth configuration so that the 3:2:3 color scheme can be used.
     426 * Check that setting the palette makes sense (the color depth is not greater
    385427 * than 8).
    386428 *
    387  * @return true if the palette has been set, false otherwise
    388  *
    389429 */
    390 int ofw_setup_palette(void)
    391 {
    392         char device_name[BUF_SIZE];
    393        
    394         /* resolve alias */
    395         if (ofw_get_property(ofw_aliases, "screen", device_name,
    396             sizeof(device_name)) <= 0)
    397                 return false;
    398        
    399         /* for depth greater than 8 it makes no sense to set up the palette */
    400         uint32_t depth;
    401         phandle device = ofw_find_device(device_name);
    402         if (device == -1)
    403                 return false;
    404         if (ofw_get_property(device, "depth", &depth, sizeof(uint32_t)) <= 0)
    405                 return false;
    406         if (depth != 8)
    407                 return false;
    408        
    409         /* required in order to be able to make a method call */
    410         ihandle screen = ofw_open(device_name);
    411         if (screen == -1)
    412                 return false;
    413        
    414         /* setup the palette so that the (inverted) 3:2:3 scheme is usable */
    415         unsigned int i;
    416         for (i = 0; i < 256; i++)
    417                 ofw_call("call-method", 6, 1, NULL, "color!", screen,
    418                     255 - i, CLIP(BLUE(i) * 37), GREEN(i) * 85, CLIP(RED(i) * 37));
    419         return true;
     430void ofw_setup_screens(void)
     431{
     432        ofw_setup_screens_internal(ofw_root);
    420433}
    421434
Note: See TracChangeset for help on using the changeset viewer.