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/arm/broadcom/bcm2835/bcm2835_mbox.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) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/bus.h>
   35 #include <sys/kernel.h>
   36 #include <sys/lock.h>
   37 #include <sys/module.h>
   38 #include <sys/mutex.h>
   39 #include <sys/sx.h>
   40 #include <sys/rman.h>
   41 #include <machine/bus.h>
   42 
   43 #include <dev/ofw/ofw_bus.h>
   44 #include <dev/ofw/ofw_bus_subr.h>
   45 
   46 #include <arm/broadcom/bcm2835/bcm2835_firmware.h>
   47 #include <arm/broadcom/bcm2835/bcm2835_mbox.h>
   48 #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
   49 #include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
   50 
   51 #include "mbox_if.h"
   52 
   53 #define REG_READ        0x00
   54 #define REG_POL         0x10
   55 #define REG_SENDER      0x14
   56 #define REG_STATUS      0x18
   57 #define         STATUS_FULL     0x80000000
   58 #define         STATUS_EMPTY    0x40000000
   59 #define REG_CONFIG      0x1C
   60 #define         CONFIG_DATA_IRQ 0x00000001
   61 #define REG_WRITE       0x20 /* This is Mailbox 1 address */
   62 
   63 #define MBOX_MSG(chan, data)    (((data) & ~0xf) | ((chan) & 0xf))
   64 #define MBOX_CHAN(msg)          ((msg) & 0xf)
   65 #define MBOX_DATA(msg)          ((msg) & ~0xf)
   66 
   67 #define MBOX_LOCK(sc)   do {    \
   68         mtx_lock(&(sc)->lock);  \
   69 } while(0)
   70 
   71 #define MBOX_UNLOCK(sc) do {            \
   72         mtx_unlock(&(sc)->lock);        \
   73 } while(0)
   74 
   75 #ifdef  DEBUG
   76 #define dprintf(fmt, args...) printf(fmt, ##args)
   77 #else
   78 #define dprintf(fmt, args...)
   79 #endif
   80 
   81 struct bcm_mbox_softc {
   82         struct mtx              lock;
   83         struct resource *       mem_res;
   84         struct resource *       irq_res;
   85         void*                   intr_hl;
   86         bus_space_tag_t         bst;
   87         bus_space_handle_t      bsh;
   88         int                     msg[BCM2835_MBOX_CHANS];
   89         int                     have_message[BCM2835_MBOX_CHANS];
   90         struct sx               property_chan_lock;
   91 };
   92 
   93 #define mbox_read_4(sc, reg)            \
   94     bus_space_read_4((sc)->bst, (sc)->bsh, reg)
   95 #define mbox_write_4(sc, reg, val)              \
   96     bus_space_write_4((sc)->bst, (sc)->bsh, reg, val)
   97 
   98 static struct ofw_compat_data compat_data[] = {
   99         {"broadcom,bcm2835-mbox",       1},
  100         {"brcm,bcm2835-mbox",           1},
  101         {NULL,                          0}
  102 };
  103 
  104 static int
  105 bcm_mbox_read_msg(struct bcm_mbox_softc *sc, int *ochan)
  106 {
  107 #ifdef DEBUG
  108         uint32_t data;
  109 #endif
  110         uint32_t msg;
  111         int chan;
  112 
  113         msg = mbox_read_4(sc, REG_READ);
  114         dprintf("bcm_mbox_intr: raw data %08x\n", msg);
  115         chan = MBOX_CHAN(msg);
  116 #ifdef DEBUG
  117         data = MBOX_DATA(msg);
  118 #endif
  119         if (sc->msg[chan]) {
  120                 printf("bcm_mbox_intr: channel %d oveflow\n", chan);
  121                 return (1);
  122         }
  123         dprintf("bcm_mbox_intr: chan %d, data %08x\n", chan, data);
  124         sc->msg[chan] = msg;
  125 
  126         if (ochan != NULL)
  127                 *ochan = chan;
  128 
  129         return (0);
  130 }
  131 
  132 static void
  133 bcm_mbox_intr(void *arg)
  134 {
  135         struct bcm_mbox_softc *sc = arg;
  136         int chan;
  137 
  138         MBOX_LOCK(sc);
  139         while (!(mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY))
  140                 if (bcm_mbox_read_msg(sc, &chan) == 0) {
  141                         sc->have_message[chan] = 1;
  142                         wakeup(&sc->have_message[chan]);
  143                 }
  144         MBOX_UNLOCK(sc);
  145 }
  146 
  147 static int
  148 bcm_mbox_probe(device_t dev)
  149 {
  150 
  151         if (!ofw_bus_status_okay(dev))
  152                 return (ENXIO);
  153 
  154         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  155                 return (ENXIO);
  156 
  157         device_set_desc(dev, "BCM2835 VideoCore Mailbox");
  158 
  159         return (BUS_PROBE_DEFAULT);
  160 }
  161 
  162 static int
  163 bcm_mbox_attach(device_t dev)
  164 {
  165         struct bcm_mbox_softc *sc = device_get_softc(dev);
  166         int i;
  167         int rid = 0;
  168 
  169         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
  170         if (sc->mem_res == NULL) {
  171                 device_printf(dev, "could not allocate memory resource\n");
  172                 return (ENXIO);
  173         }
  174 
  175         sc->bst = rman_get_bustag(sc->mem_res);
  176         sc->bsh = rman_get_bushandle(sc->mem_res);
  177 
  178         rid = 0;
  179         sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
  180         if (sc->irq_res == NULL) {
  181                 device_printf(dev, "could not allocate interrupt resource\n");
  182                 return (ENXIO);
  183         }
  184 
  185         /* Setup and enable the timer */
  186         if (bus_setup_intr(dev, sc->irq_res, INTR_MPSAFE | INTR_TYPE_MISC, 
  187             NULL, bcm_mbox_intr, sc, &sc->intr_hl) != 0) {
  188                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->irq_res);
  189                 device_printf(dev, "Unable to setup the clock irq handler.\n");
  190                 return (ENXIO);
  191         }
  192 
  193         mtx_init(&sc->lock, "vcio mbox", NULL, MTX_DEF);
  194         for (i = 0; i < BCM2835_MBOX_CHANS; i++) {
  195                 sc->msg[i] = 0;
  196                 sc->have_message[i] = 0;
  197         }
  198 
  199         sx_init(&sc->property_chan_lock, "mboxprop");
  200 
  201         /* Read all pending messages */
  202         while ((mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY) == 0)
  203                 (void)mbox_read_4(sc, REG_READ);
  204 
  205         mbox_write_4(sc, REG_CONFIG, CONFIG_DATA_IRQ);
  206 
  207         return (0);
  208 }
  209 
  210 /* 
  211  * Mailbox API
  212  */
  213 static int
  214 bcm_mbox_write(device_t dev, int chan, uint32_t data)
  215 {
  216         int limit = 1000;
  217         struct bcm_mbox_softc *sc = device_get_softc(dev);
  218 
  219         dprintf("bcm_mbox_write: chan %d, data %08x\n", chan, data);
  220         MBOX_LOCK(sc);
  221         sc->have_message[chan] = 0;
  222         while ((mbox_read_4(sc, REG_STATUS) & STATUS_FULL) && --limit)
  223                 DELAY(5);
  224         if (limit == 0) {
  225                 printf("bcm_mbox_write: STATUS_FULL stuck");
  226                 MBOX_UNLOCK(sc);
  227                 return (EAGAIN);
  228         }
  229         mbox_write_4(sc, REG_WRITE, MBOX_MSG(chan, data));
  230         MBOX_UNLOCK(sc);
  231 
  232         return (0);
  233 }
  234 
  235 static int
  236 bcm_mbox_read(device_t dev, int chan, uint32_t *data)
  237 {
  238         struct bcm_mbox_softc *sc = device_get_softc(dev);
  239         int err, read_chan;
  240 
  241         dprintf("bcm_mbox_read: chan %d\n", chan);
  242 
  243         err = 0;
  244         MBOX_LOCK(sc);
  245         if (!cold) {
  246                 if (sc->have_message[chan] == 0) {
  247                         if (mtx_sleep(&sc->have_message[chan], &sc->lock, 0,
  248                             "mbox", 10*hz) != 0) {
  249                                 device_printf(dev, "timeout waiting for message on chan %d\n", chan);
  250                                 err = ETIMEDOUT;
  251                         }
  252                 }
  253         } else {
  254                 do {
  255                         /* Wait for a message */
  256                         while ((mbox_read_4(sc, REG_STATUS) & STATUS_EMPTY))
  257                                 ;
  258                         /* Read the message */
  259                         if (bcm_mbox_read_msg(sc, &read_chan) != 0) {
  260                                 err = EINVAL;
  261                                 goto out;
  262                         }
  263                 } while (read_chan != chan);
  264         }
  265         /*
  266          *  get data from intr handler, the same channel is never coming
  267          *  because of holding sc lock.
  268          */
  269         *data = MBOX_DATA(sc->msg[chan]);
  270         sc->msg[chan] = 0;
  271         sc->have_message[chan] = 0;
  272 out:
  273         MBOX_UNLOCK(sc);
  274         dprintf("bcm_mbox_read: chan %d, data %08x\n", chan, *data);
  275 
  276         return (err);
  277 }
  278 
  279 static device_method_t bcm_mbox_methods[] = {
  280         DEVMETHOD(device_probe,         bcm_mbox_probe),
  281         DEVMETHOD(device_attach,        bcm_mbox_attach),
  282 
  283         DEVMETHOD(mbox_read,            bcm_mbox_read),
  284         DEVMETHOD(mbox_write,           bcm_mbox_write),
  285 
  286         DEVMETHOD_END
  287 };
  288 
  289 static driver_t bcm_mbox_driver = {
  290         "mbox",
  291         bcm_mbox_methods,
  292         sizeof(struct bcm_mbox_softc),
  293 };
  294 
  295 EARLY_DRIVER_MODULE(mbox, simplebus, bcm_mbox_driver, 0, 0,
  296     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
  297 
  298 static void
  299 bcm2835_mbox_dma_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
  300 {
  301         bus_addr_t *addr;
  302 
  303         if (err)
  304                 return;
  305         addr = (bus_addr_t *)arg;
  306         *addr = ARMC_TO_VCBUS(segs[0].ds_addr);
  307 }
  308 
  309 static void *
  310 bcm2835_mbox_init_dma(device_t dev, size_t len, bus_dma_tag_t *tag,
  311     bus_dmamap_t *map, bus_addr_t *phys)
  312 {
  313         void *buf;
  314         int err;
  315 
  316         err = bus_dma_tag_create(bus_get_dma_tag(dev), 16, 0,
  317             bcm283x_dmabus_peripheral_lowaddr(), BUS_SPACE_MAXADDR, NULL, NULL,
  318             len, 1, len, 0, NULL, NULL, tag);
  319         if (err != 0) {
  320                 device_printf(dev, "can't create DMA tag\n");
  321                 return (NULL);
  322         }
  323 
  324         err = bus_dmamem_alloc(*tag, &buf, 0, map);
  325         if (err != 0) {
  326                 bus_dma_tag_destroy(*tag);
  327                 device_printf(dev, "can't allocate dmamem\n");
  328                 return (NULL);
  329         }
  330 
  331         err = bus_dmamap_load(*tag, *map, buf, len, bcm2835_mbox_dma_cb,
  332             phys, 0);
  333         if (err != 0) {
  334                 bus_dmamem_free(*tag, buf, *map);
  335                 bus_dma_tag_destroy(*tag);
  336                 device_printf(dev, "can't load DMA map\n");
  337                 return (NULL);
  338         }
  339 
  340         return (buf);
  341 }
  342 
  343 static int
  344 bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys,
  345         struct bcm2835_mbox_hdr *msg, size_t len)
  346 {
  347         int idx;
  348         struct bcm2835_mbox_tag_hdr *tag;
  349         uint8_t *last;
  350 
  351         if ((uint32_t)msg_phys != resp_phys) {
  352                 device_printf(dev, "response channel mismatch\n");
  353                 return (EIO);
  354         }
  355         if (msg->code != BCM2835_MBOX_CODE_RESP_SUCCESS) {
  356                 device_printf(dev, "mbox response error\n");
  357                 return (EIO);
  358         }
  359 
  360         /* Loop until the end tag. */
  361         tag = (struct bcm2835_mbox_tag_hdr *)(msg + 1);
  362         last = (uint8_t *)msg + len;
  363         for (idx = 0; tag->tag != 0; idx++) {
  364                 /*
  365                  * When setting the GPIO config or state the firmware doesn't
  366                  * set tag->val_len correctly.
  367                  */
  368                 if ((tag->tag == BCM2835_FIRMWARE_TAG_SET_GPIO_CONFIG ||
  369                      tag->tag == BCM2835_FIRMWARE_TAG_SET_GPIO_STATE) &&
  370                     tag->val_len == 0) {
  371                         tag->val_len = BCM2835_MBOX_TAG_VAL_LEN_RESPONSE |
  372                             tag->val_buf_size;
  373                 }
  374                 if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) {
  375                         device_printf(dev, "tag %d response error\n", idx);
  376                         return (EIO);
  377                 }
  378                 /* Clear the response bit. */
  379                 tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
  380 
  381                 /* Next tag. */
  382                 tag = (struct bcm2835_mbox_tag_hdr *)((uint8_t *)tag +
  383                     sizeof(*tag) + tag->val_buf_size);
  384 
  385                 if ((uint8_t *)tag > last) {
  386                         device_printf(dev, "mbox buffer size error\n");
  387                         return (EIO);
  388                 }
  389         }
  390 
  391         return (0);
  392 }
  393 
  394 int
  395 bcm2835_mbox_property(void *msg, size_t msg_size)
  396 {
  397         struct bcm_mbox_softc *sc;
  398         bus_dma_tag_t msg_tag;
  399         bus_dmamap_t msg_map;
  400         bus_addr_t msg_phys;
  401         char *buf;
  402         uint32_t reg;
  403         device_t mbox;
  404         int err;
  405 
  406         /* get mbox device */
  407         mbox = devclass_get_device(devclass_find("mbox"), 0);
  408         if (mbox == NULL)
  409                 return (ENXIO);
  410 
  411         sc = device_get_softc(mbox);
  412         sx_xlock(&sc->property_chan_lock);
  413 
  414         /* Allocate memory for the message */
  415         buf = bcm2835_mbox_init_dma(mbox, msg_size, &msg_tag, &msg_map,
  416             &msg_phys);
  417         if (buf == NULL) {
  418                 err = ENOMEM;
  419                 goto out;
  420         }
  421 
  422         memcpy(buf, msg, msg_size);
  423 
  424         bus_dmamap_sync(msg_tag, msg_map,
  425             BUS_DMASYNC_PREWRITE);
  426 
  427         MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys);
  428         MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, &reg);
  429 
  430         bus_dmamap_sync(msg_tag, msg_map,
  431             BUS_DMASYNC_PREREAD);
  432 
  433         memcpy(msg, buf, msg_size);
  434 
  435         err = bcm2835_mbox_err(mbox, msg_phys, reg,
  436             (struct bcm2835_mbox_hdr *)msg, msg_size);
  437 
  438         bus_dmamap_unload(msg_tag, msg_map);
  439         bus_dmamem_free(msg_tag, buf, msg_map);
  440         bus_dma_tag_destroy(msg_tag);
  441 out:
  442         sx_xunlock(&sc->property_chan_lock);
  443         return (err);
  444 }
  445 
  446 int
  447 bcm2835_mbox_set_power_state(uint32_t device_id, boolean_t on)
  448 {
  449         struct msg_set_power_state msg;
  450         int err;
  451 
  452         memset(&msg, 0, sizeof(msg));
  453         msg.hdr.buf_size = sizeof(msg);
  454         msg.hdr.code = BCM2835_MBOX_CODE_REQ;
  455         msg.tag_hdr.tag = BCM2835_MBOX_TAG_SET_POWER_STATE;
  456         msg.tag_hdr.val_buf_size = sizeof(msg.body);
  457         msg.tag_hdr.val_len = sizeof(msg.body.req);
  458         msg.body.req.device_id = device_id;
  459         msg.body.req.state = (on ? BCM2835_MBOX_POWER_ON : 0) |
  460             BCM2835_MBOX_POWER_WAIT;
  461         msg.end_tag = 0;
  462 
  463         err = bcm2835_mbox_property(&msg, sizeof(msg));
  464 
  465         return (err);
  466 }
  467 
  468 int
  469 bcm2835_mbox_notify_xhci_reset(uint32_t pci_dev_addr)
  470 {
  471         struct msg_notify_xhci_reset msg;
  472         int err;
  473 
  474         memset(&msg, 0, sizeof(msg));
  475         msg.hdr.buf_size = sizeof(msg);
  476         msg.hdr.code = BCM2835_MBOX_CODE_REQ;
  477         msg.tag_hdr.tag = BCM2835_MBOX_TAG_NOTIFY_XHCI_RESET;
  478         msg.tag_hdr.val_buf_size = sizeof(msg.body);
  479         msg.tag_hdr.val_len = sizeof(msg.body.req);
  480         msg.body.req.pci_device_addr = pci_dev_addr;
  481         msg.end_tag = 0;
  482 
  483         err = bcm2835_mbox_property(&msg, sizeof(msg));
  484 
  485         return (err);
  486 }
  487 
  488 int
  489 bcm2835_mbox_get_clock_rate(uint32_t clock_id, uint32_t *hz)
  490 {
  491         struct msg_get_clock_rate msg;
  492         int err;
  493 
  494         memset(&msg, 0, sizeof(msg));
  495         msg.hdr.buf_size = sizeof(msg);
  496         msg.hdr.code = BCM2835_MBOX_CODE_REQ;
  497         msg.tag_hdr.tag = BCM2835_MBOX_TAG_GET_CLOCK_RATE;
  498         msg.tag_hdr.val_buf_size = sizeof(msg.body);
  499         msg.tag_hdr.val_len = sizeof(msg.body.req);
  500         msg.body.req.clock_id = clock_id;
  501         msg.end_tag = 0;
  502 
  503         err = bcm2835_mbox_property(&msg, sizeof(msg));
  504         *hz = msg.body.resp.rate_hz;
  505 
  506         return (err);
  507 }
  508 
  509 int
  510 bcm2835_mbox_fb_get_w_h(struct bcm2835_fb_config *fb)
  511 {
  512         int err;
  513         struct msg_fb_get_w_h msg;
  514 
  515         memset(&msg, 0, sizeof(msg));
  516         msg.hdr.buf_size = sizeof(msg);
  517         msg.hdr.code = BCM2835_MBOX_CODE_REQ;
  518         BCM2835_MBOX_INIT_TAG(&msg.physical_w_h, GET_PHYSICAL_W_H);
  519         msg.physical_w_h.tag_hdr.val_len = 0;
  520         msg.end_tag = 0;
  521 
  522         err = bcm2835_mbox_property(&msg, sizeof(msg));
  523         if (err == 0) {
  524                 fb->xres = msg.physical_w_h.body.resp.width;
  525                 fb->yres = msg.physical_w_h.body.resp.height;
  526         }
  527 
  528         return (err);
  529 }
  530 
  531 int
  532 bcm2835_mbox_fb_get_bpp(struct bcm2835_fb_config *fb)
  533 {
  534         int err;
  535         struct msg_fb_get_bpp msg;
  536 
  537         memset(&msg, 0, sizeof(msg));
  538         msg.hdr.buf_size = sizeof(msg);
  539         msg.hdr.code = BCM2835_MBOX_CODE_REQ;
  540         BCM2835_MBOX_INIT_TAG(&msg.bpp, GET_DEPTH);
  541         msg.bpp.tag_hdr.val_len = 0;
  542         msg.end_tag = 0;
  543 
  544         err = bcm2835_mbox_property(&msg, sizeof(msg));
  545         if (err == 0)
  546                 fb->bpp = msg.bpp.body.resp.bpp;
  547 
  548         return (err);
  549 }
  550 
  551 int
  552 bcm2835_mbox_fb_init(struct bcm2835_fb_config *fb)
  553 {
  554         int err;
  555         struct msg_fb_setup msg;
  556 
  557         memset(&msg, 0, sizeof(msg));
  558         msg.hdr.buf_size = sizeof(msg);
  559         msg.hdr.code = BCM2835_MBOX_CODE_REQ;
  560         BCM2835_MBOX_INIT_TAG(&msg.physical_w_h, SET_PHYSICAL_W_H);
  561         msg.physical_w_h.body.req.width = fb->xres;
  562         msg.physical_w_h.body.req.height = fb->yres;
  563         BCM2835_MBOX_INIT_TAG(&msg.virtual_w_h, SET_VIRTUAL_W_H);
  564         msg.virtual_w_h.body.req.width = fb->vxres;
  565         msg.virtual_w_h.body.req.height = fb->vyres;
  566         BCM2835_MBOX_INIT_TAG(&msg.offset, SET_VIRTUAL_OFFSET);
  567         msg.offset.body.req.x = fb->xoffset;
  568         msg.offset.body.req.y = fb->yoffset;
  569         BCM2835_MBOX_INIT_TAG(&msg.depth, SET_DEPTH);
  570         msg.depth.body.req.bpp = fb->bpp;
  571         BCM2835_MBOX_INIT_TAG(&msg.alpha, SET_ALPHA_MODE);
  572         msg.alpha.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED;
  573         BCM2835_MBOX_INIT_TAG(&msg.buffer, ALLOCATE_BUFFER);
  574         msg.buffer.body.req.alignment = PAGE_SIZE;
  575         BCM2835_MBOX_INIT_TAG(&msg.pitch, GET_PITCH);
  576         msg.end_tag = 0;
  577 
  578         err = bcm2835_mbox_property(&msg, sizeof(msg));
  579         if (err == 0) {
  580                 fb->xres = msg.physical_w_h.body.resp.width;
  581                 fb->yres = msg.physical_w_h.body.resp.height;
  582                 fb->vxres = msg.virtual_w_h.body.resp.width;
  583                 fb->vyres = msg.virtual_w_h.body.resp.height;
  584                 fb->xoffset = msg.offset.body.resp.x;
  585                 fb->yoffset = msg.offset.body.resp.y;
  586                 fb->pitch = msg.pitch.body.resp.pitch;
  587                 fb->base = VCBUS_TO_ARMC(msg.buffer.body.resp.fb_address);
  588                 fb->size = msg.buffer.body.resp.fb_size;
  589         }
  590 
  591         return (err);
  592 }

Cache object: e8a01f66148df58bf5f6d9ddacaf99cf


[ 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.