1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <ddk/binding.h>
6#include <ddk/debug.h>
7#include <ddk/device.h>
8#include <ddk/driver.h>
9#include <ddk/protocol/platform-defs.h>
10#include <ddk/protocol/platform-device.h>
11
12#include "../qemu-virt.h"
13
14#define DRIVER_NAME "qemu-test-child-2"
15
16typedef struct {
17    zx_device_t* zxdev;
18} qemu_test_t;
19
20static void qemu_test_release(void* ctx) {
21    free(ctx);
22}
23
24static zx_protocol_device_t qemu_test_device_protocol = {
25    .version = DEVICE_OPS_VERSION,
26    .release = qemu_test_release,
27};
28
29static zx_status_t qemu_test_bind(void* ctx, zx_device_t* parent) {
30    platform_device_protocol_t pdev;
31    zx_status_t status;
32
33    zxlogf(INFO, "qemu_test_bind: %s \n", DRIVER_NAME);
34
35    status = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_DEV, &pdev);
36    if (status != ZX_OK) {
37        zxlogf(ERROR, "%s: could not get ZX_PROTOCOL_PLATFORM_DEV\n", DRIVER_NAME);
38        return status;
39    }
40
41    // Make sure we can access our MMIO.
42    mmio_buffer_t mmio;
43    status = pdev_map_mmio_buffer2(&pdev, 0, ZX_CACHE_POLICY_UNCACHED_DEVICE, &mmio);
44    if (status != ZX_OK) {
45        zxlogf(ERROR, "%s: pdev_map_mmio_buffer failed\n", DRIVER_NAME);
46        return status;
47    }
48    if (mmio.size != TEST_MMIO_3_SIZE) {
49        zxlogf(ERROR, "%s: mmio.size expected %u got %zu\n", DRIVER_NAME, TEST_MMIO_3_SIZE,
50               mmio.size);
51    }
52    mmio_buffer_release(&mmio);
53
54    qemu_test_t* test = calloc(1, sizeof(qemu_test_t));
55    if (!test) {
56        return ZX_ERR_NO_MEMORY;
57    }
58
59    device_add_args_t args = {
60        .version = DEVICE_ADD_ARGS_VERSION,
61        .name = "child-2",
62        .ctx = test,
63        .ops = &qemu_test_device_protocol,
64        .flags = DEVICE_ADD_NON_BINDABLE,
65    };
66
67    status = device_add(parent, &args, &test->zxdev);
68    if (status != ZX_OK) {
69        zxlogf(ERROR, "%s: device_add failed: %d\n", DRIVER_NAME, status);
70        free(test);
71        return status;
72    }
73
74    return ZX_OK;
75}
76
77static zx_driver_ops_t qemu_test_driver_ops = {
78    .version = DRIVER_OPS_VERSION,
79    .bind = qemu_test_bind,
80};
81
82ZIRCON_DRIVER_BEGIN(qemu_bus, qemu_test_driver_ops, "zircon", "0.1", 4)
83    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_DEV),
84    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_QEMU),
85    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_QEMU),
86    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_QEMU_TEST_CHILD_2),
87ZIRCON_DRIVER_END(qemu_bus)
88