qemu/hw/sd/core.c
<<
>>
Prefs
   1/*
   2 * SD card bus interface code.
   3 *
   4 * Copyright (c) 2015 Linaro Limited
   5 *
   6 * Author:
   7 *  Peter Maydell <peter.maydell@linaro.org>
   8 *
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms and conditions of the GNU General Public License,
  11 * version 2 or later, as published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope it will be useful, but WITHOUT
  14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  16 * more details.
  17 *
  18 * You should have received a copy of the GNU General Public License along with
  19 * this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include "qemu/osdep.h"
  23#include "hw/qdev-core.h"
  24#include "sysemu/block-backend.h"
  25#include "hw/sd/sd.h"
  26
  27static SDState *get_card(SDBus *sdbus)
  28{
  29    /* We only ever have one child on the bus so just return it */
  30    BusChild *kid = QTAILQ_FIRST(&sdbus->qbus.children);
  31
  32    if (!kid) {
  33        return NULL;
  34    }
  35    return SD_CARD(kid->child);
  36}
  37
  38int sdbus_do_command(SDBus *sdbus, SDRequest *req, uint8_t *response)
  39{
  40    SDState *card = get_card(sdbus);
  41
  42    if (card) {
  43        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  44
  45        return sc->do_command(card, req, response);
  46    }
  47
  48    return 0;
  49}
  50
  51void sdbus_write_data(SDBus *sdbus, uint8_t value)
  52{
  53    SDState *card = get_card(sdbus);
  54
  55    if (card) {
  56        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  57
  58        sc->write_data(card, value);
  59    }
  60}
  61
  62uint8_t sdbus_read_data(SDBus *sdbus)
  63{
  64    SDState *card = get_card(sdbus);
  65
  66    if (card) {
  67        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  68
  69        return sc->read_data(card);
  70    }
  71
  72    return 0;
  73}
  74
  75bool sdbus_data_ready(SDBus *sdbus)
  76{
  77    SDState *card = get_card(sdbus);
  78
  79    if (card) {
  80        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  81
  82        return sc->data_ready(card);
  83    }
  84
  85    return false;
  86}
  87
  88bool sdbus_get_inserted(SDBus *sdbus)
  89{
  90    SDState *card = get_card(sdbus);
  91
  92    if (card) {
  93        SDCardClass *sc = SD_CARD_GET_CLASS(card);
  94
  95        return sc->get_inserted(card);
  96    }
  97
  98    return false;
  99}
 100
 101bool sdbus_get_readonly(SDBus *sdbus)
 102{
 103    SDState *card = get_card(sdbus);
 104
 105    if (card) {
 106        SDCardClass *sc = SD_CARD_GET_CLASS(card);
 107
 108        return sc->get_readonly(card);
 109    }
 110
 111    return false;
 112}
 113
 114void sdbus_set_inserted(SDBus *sdbus, bool inserted)
 115{
 116    SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
 117    BusState *qbus = BUS(sdbus);
 118
 119    if (sbc->set_inserted) {
 120        sbc->set_inserted(qbus->parent, inserted);
 121    }
 122}
 123
 124void sdbus_set_readonly(SDBus *sdbus, bool readonly)
 125{
 126    SDBusClass *sbc = SD_BUS_GET_CLASS(sdbus);
 127    BusState *qbus = BUS(sdbus);
 128
 129    if (sbc->set_readonly) {
 130        sbc->set_readonly(qbus->parent, readonly);
 131    }
 132}
 133
 134void sdbus_reparent_card(SDBus *from, SDBus *to)
 135{
 136    SDState *card = get_card(from);
 137    SDCardClass *sc;
 138    bool readonly;
 139
 140    /* We directly reparent the card object rather than implementing this
 141     * as a hotpluggable connection because we don't want to expose SD cards
 142     * to users as being hotpluggable, and we can get away with it in this
 143     * limited use case. This could perhaps be implemented more cleanly in
 144     * future by adding support to the hotplug infrastructure for "device
 145     * can be hotplugged only via code, not by user".
 146     */
 147
 148    if (!card) {
 149        return;
 150    }
 151
 152    sc = SD_CARD_GET_CLASS(card);
 153    readonly = sc->get_readonly(card);
 154
 155    sdbus_set_inserted(from, false);
 156    qdev_set_parent_bus(DEVICE(card), &to->qbus);
 157    sdbus_set_inserted(to, true);
 158    sdbus_set_readonly(to, readonly);
 159}
 160
 161static const TypeInfo sd_bus_info = {
 162    .name = TYPE_SD_BUS,
 163    .parent = TYPE_BUS,
 164    .instance_size = sizeof(SDBus),
 165    .class_size = sizeof(SDBusClass),
 166};
 167
 168static void sd_bus_register_types(void)
 169{
 170    type_register_static(&sd_bus_info);
 171}
 172
 173type_init(sd_bus_register_types)
 174