The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/vt/hw/fb/vt_early_fb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2013 The FreeBSD Foundation
    5  *
    6  * This software was developed by Aleksandr Rybalko under sponsorship from the
    7  * FreeBSD Foundation.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/fbio.h>
   38 
   39 #include "opt_platform.h"
   40 
   41 #ifdef  FDT
   42 #include <dev/fdt/fdt_common.h>
   43 #include <dev/ofw/ofw_bus.h>
   44 #include <dev/ofw/ofw_bus_subr.h>
   45 #include <dev/ofw/ofw_pci.h>
   46 #include <machine/fdt.h>
   47 #endif
   48 
   49 #include <dev/vt/vt.h>
   50 #include <dev/vt/hw/fb/vt_fb.h>
   51 #include <dev/vt/colors/vt_termcolors.h>
   52 
   53 static vd_init_t vt_efb_init;
   54 static vd_probe_t vt_efb_probe;
   55 
   56 static struct vt_driver vt_fb_early_driver = {
   57         .vd_name = "efb",
   58         .vd_probe = vt_efb_probe,
   59         .vd_init = vt_efb_init,
   60         .vd_blank = vt_fb_blank,
   61         .vd_bitblt_text = vt_fb_bitblt_text,
   62         .vd_invalidate_text = vt_fb_invalidate_text,
   63         .vd_bitblt_bmp = vt_fb_bitblt_bitmap,
   64         .vd_drawrect = vt_fb_drawrect,
   65         .vd_setpixel = vt_fb_setpixel,
   66         .vd_priority = VD_PRIORITY_GENERIC,
   67 };
   68 
   69 static struct fb_info local_info;
   70 VT_DRIVER_DECLARE(vt_efb, vt_fb_early_driver);
   71 
   72 static void
   73 #ifdef  FDT
   74 vt_efb_initialize(struct fb_info *info, phandle_t node)
   75 #else
   76 vt_efb_initialize(struct fb_info *info)
   77 #endif
   78 {
   79 #ifdef  FDT
   80         char name[64];
   81         cell_t retval;
   82         ihandle_t ih;
   83         int i;
   84 
   85         /* Open display device, thereby initializing it */
   86         memset(name, 0, sizeof(name));
   87         OF_package_to_path(node, name, sizeof(name));
   88         ih = OF_open(name);
   89 #endif
   90 
   91         /*
   92          * Set up the color map
   93          */
   94         switch (info->fb_depth) {
   95         case 8:
   96                 vt_config_cons_colors(info, COLOR_FORMAT_RGB,
   97                     0x7, 5, 0x7, 2, 0x3, 0);
   98                 break;
   99         case 15:
  100                 vt_config_cons_colors(info, COLOR_FORMAT_RGB,
  101                     0x1f, 10, 0x1f, 5, 0x1f, 0);
  102                 break;
  103         case 16:
  104                 vt_config_cons_colors(info, COLOR_FORMAT_RGB,
  105                     0x1f, 11, 0x3f, 5, 0x1f, 0);
  106                 break;
  107         case 24:
  108         case 32:
  109 #if BYTE_ORDER == BIG_ENDIAN
  110                 vt_config_cons_colors(info,
  111                     COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
  112 #else
  113                 vt_config_cons_colors(info,
  114                     COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
  115 #endif
  116 #ifdef  FDT
  117                 for (i = 0; i < 16; i++) {
  118                         OF_call_method("color!", ih, 4, 1,
  119                             (cell_t)((info->fb_cmap[i] >> 16) & 0xff),
  120                             (cell_t)((info->fb_cmap[i] >> 8) & 0xff),
  121                             (cell_t)((info->fb_cmap[i] >> 0) & 0xff),
  122                             (cell_t)i, &retval);
  123                 }
  124 #endif
  125                 break;
  126 
  127         default:
  128                 panic("Unknown color space fb_depth %d", info->fb_depth);
  129                 break;
  130         }
  131 }
  132 
  133 static phandle_t
  134 vt_efb_get_fbnode()
  135 {
  136         phandle_t chosen, node;
  137         ihandle_t stdout;
  138         char type[64];
  139 
  140         chosen = OF_finddevice("/chosen");
  141         OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
  142         node = OF_instance_to_package(stdout);
  143         if (node != -1) {
  144                 /* The "/chosen/stdout" present. */
  145                 OF_getprop(node, "device_type", type, sizeof(type));
  146                 /* Check if it has "display" type. */
  147                 if (strcmp(type, "display") == 0)
  148                         return (node);
  149         }
  150         /* Try device with name "screen". */
  151         node = OF_finddevice("screen");
  152 
  153         return (node);
  154 }
  155 
  156 static int
  157 vt_efb_probe(struct vt_device *vd)
  158 {
  159         phandle_t node;
  160 
  161         node = vt_efb_get_fbnode();
  162         if (node == -1)
  163                 return (CN_DEAD);
  164 
  165         if ((OF_getproplen(node, "height") <= 0) ||
  166             (OF_getproplen(node, "width") <= 0) ||
  167             (OF_getproplen(node, "depth") <= 0) ||
  168             (OF_getproplen(node, "linebytes") <= 0))
  169                 return (CN_DEAD);
  170 
  171         return (CN_INTERNAL);
  172 }
  173 
  174 static int
  175 vt_efb_init(struct vt_device *vd)
  176 {
  177         struct ofw_pci_register pciaddrs[8];
  178         struct fb_info *info;
  179         int i, len, n_pciaddrs;
  180         phandle_t node;
  181 
  182         if (vd->vd_softc == NULL)
  183                 vd->vd_softc = (void *)&local_info;
  184 
  185         info = vd->vd_softc;
  186 
  187         node = vt_efb_get_fbnode();
  188         if (node == -1)
  189                 return (CN_DEAD);
  190 
  191 #define GET(name, var)                                                  \
  192         if (OF_getproplen(node, (name)) != sizeof(info->fb_##var))      \
  193                 return (CN_DEAD);                                       \
  194         OF_getencprop(node, (name), &info->fb_##var, sizeof(info->fb_##var)); \
  195         if (info->fb_##var == 0)                                        \
  196                 return (CN_DEAD);
  197 
  198         GET("height", height)
  199         GET("width", width)
  200         GET("depth", depth)
  201         GET("linebytes", stride)
  202 #undef GET
  203 
  204         info->fb_size = info->fb_height * info->fb_stride;
  205 
  206         /*
  207          * Get the PCI addresses of the adapter, if present. The node may be the
  208          * child of the PCI device: in that case, try the parent for
  209          * the assigned-addresses property.
  210          */
  211         len = OF_getprop(node, "assigned-addresses", pciaddrs,
  212             sizeof(pciaddrs));
  213         if (len == -1) {
  214                 len = OF_getprop(OF_parent(node), "assigned-addresses",
  215                     pciaddrs, sizeof(pciaddrs));
  216         }
  217         if (len == -1)
  218                 len = 0;
  219         n_pciaddrs = len / sizeof(struct ofw_pci_register);
  220 
  221         /*
  222          * Grab the physical address of the framebuffer, and then map it
  223          * into our memory space. If the MMU is not yet up, it will be
  224          * remapped for us when relocation turns on.
  225          */
  226         if (OF_getproplen(node, "address") == sizeof(info->fb_pbase)) {
  227                 /* XXX We assume #address-cells is 1 at this point. */
  228                 OF_getencprop(node, "address", &info->fb_pbase,
  229                     sizeof(info->fb_pbase));
  230 
  231         #if defined(__powerpc__)
  232                 sc->sc_memt = &bs_be_tag;
  233                 bus_space_map(sc->sc_memt, info->fb_pbase, info->fb_size,
  234                     BUS_SPACE_MAP_PREFETCHABLE, &info->fb_vbase);
  235         #else
  236                 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
  237                     BUS_SPACE_MAP_PREFETCHABLE,
  238                     (bus_space_handle_t *)&info->fb_vbase);
  239         #endif
  240         } else {
  241                 /*
  242                  * Some IBM systems don't have an address property. Try to
  243                  * guess the framebuffer region from the assigned addresses.
  244                  * This is ugly, but there doesn't seem to be an alternative.
  245                  * Linux does the same thing.
  246                  */
  247 
  248                 info->fb_pbase = n_pciaddrs;
  249                 for (i = 0; i < n_pciaddrs; i++) {
  250                         /* If it is too small, not the framebuffer */
  251                         if (pciaddrs[i].size_lo < info->fb_size)
  252                                 continue;
  253                         /* If it is not memory, it isn't either */
  254                         if (!(pciaddrs[i].phys_hi &
  255                             OFW_PCI_PHYS_HI_SPACE_MEM32))
  256                                 continue;
  257 
  258                         /* This could be the framebuffer */
  259                         info->fb_pbase = i;
  260 
  261                         /* If it is prefetchable, it certainly is */
  262                         if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
  263                                 break;
  264                 }
  265 
  266                 if (info->fb_pbase == n_pciaddrs) /* No candidates found */
  267                         return (CN_DEAD);
  268 
  269         #if defined(__powerpc__)
  270                 OF_decode_addr(node, info->fb_pbase, &sc->sc_memt,
  271                     &info->fb_vbase);
  272         #else
  273                 bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
  274                     BUS_SPACE_MAP_PREFETCHABLE,
  275                     (bus_space_handle_t *)&info->fb_vbase);
  276         #endif
  277         }
  278 
  279         /* blank full size */
  280         len = info->fb_size / 4;
  281         for (i = 0; i < len; i++) {
  282                 ((uint32_t *)info->fb_vbase)[i] = 0;
  283         }
  284 
  285         /* Get pixel storage size. */
  286         info->fb_bpp = info->fb_stride / info->fb_width * 8;
  287 
  288 #ifdef  FDT
  289         vt_efb_initialize(info, node);
  290 #else
  291         vt_efb_initialize(info);
  292 #endif
  293         vt_fb_init(vd);
  294 
  295         return (CN_INTERNAL);
  296 }

Cache object: 77963bdf415154a172201db294e01df8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.