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/platform-defs.h>
9 #include <ddk/protocol/platform/device.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 typedef struct cpu_trace_dev {
14 zx_device_t* zxdev;
15 zx_handle_t bti;
16 } cpu_trace_dev_t;
17
18 static const pdev_device_info_t cpu_trace_pdev_device_info = {
19 .vid = PDEV_VID_INTEL,
20 .pid = PDEV_PID_GENERIC,
21 .did = PDEV_DID_INTEL_CPU_TRACE,
22 .bti_count = 1,
23 };
24
cpu_trace_get_bti(void * ctx,uint32_t index,zx_handle_t * out_handle)25 static zx_status_t cpu_trace_get_bti(void* ctx, uint32_t index, zx_handle_t* out_handle) {
26 cpu_trace_dev_t* dev = ctx;
27 if (index >= cpu_trace_pdev_device_info.bti_count || out_handle == NULL) {
28 return ZX_ERR_INVALID_ARGS;
29 }
30 return zx_handle_duplicate(dev->bti, ZX_RIGHT_SAME_RIGHTS, out_handle);
31 }
32
cpu_trace_get_device_info(void * ctx,pdev_device_info_t * out_info)33 static zx_status_t cpu_trace_get_device_info(void* ctx, pdev_device_info_t* out_info) {
34 memcpy(out_info, &cpu_trace_pdev_device_info, sizeof(*out_info));
35 return ZX_OK;
36 }
37
cpu_trace_get_mmio(void * ctx,uint32_t index,pdev_mmio_t * mmio)38 static zx_status_t cpu_trace_get_mmio(void* ctx, uint32_t index, pdev_mmio_t* mmio) {
39 return ZX_ERR_NOT_SUPPORTED;
40 }
41
cpu_trace_get_interrupt(void * ctx,uint32_t index,uint32_t flags,zx_handle_t * out_handle)42 static zx_status_t cpu_trace_get_interrupt(void* ctx, uint32_t index, uint32_t flags, zx_handle_t* out_handle) {
43 return ZX_ERR_NOT_SUPPORTED;
44 }
45
46 static pdev_protocol_ops_t cpu_trace_proto_ops = {
47 .get_mmio = cpu_trace_get_mmio,
48 .get_interrupt = cpu_trace_get_interrupt,
49 .get_bti = cpu_trace_get_bti,
50 .get_device_info = cpu_trace_get_device_info,
51 };
52
53
cpu_trace_release(void * ctx)54 static void cpu_trace_release(void* ctx) {
55 cpu_trace_dev_t* dev = ctx;
56 zx_handle_close(dev->bti);
57 free(dev);
58 }
59
60 static zx_protocol_device_t cpu_trace_dev_proto = {
61 .version = DEVICE_OPS_VERSION,
62 .release = cpu_trace_release,
63 };
64
publish_cpu_trace(zx_handle_t bti,zx_device_t * sys_root)65 zx_status_t publish_cpu_trace(zx_handle_t bti, zx_device_t* sys_root) {
66 cpu_trace_dev_t* dev = calloc(1, sizeof(*dev));
67 if (dev == NULL) {
68 return ZX_ERR_NO_MEMORY;
69 }
70 dev->bti = bti;
71
72 zx_device_prop_t props[] = {
73 {BIND_PLATFORM_DEV_VID, 0, cpu_trace_pdev_device_info.vid},
74 {BIND_PLATFORM_DEV_PID, 0, cpu_trace_pdev_device_info.pid},
75 {BIND_PLATFORM_DEV_DID, 0, cpu_trace_pdev_device_info.did},
76 };
77 device_add_args_t args = {
78 .version = DEVICE_ADD_ARGS_VERSION,
79 .name = "cpu-trace",
80 .ctx = dev,
81 .ops = &cpu_trace_dev_proto,
82 .proto_id = ZX_PROTOCOL_PDEV,
83 .proto_ops = &cpu_trace_proto_ops,
84 .props = props,
85 .prop_count = countof(props),
86 .proxy_args = NULL,
87 .flags = 0,
88 };
89
90 // add as a child of the sysroot
91 zx_status_t status = device_add(sys_root, &args, &dev->zxdev);
92 if (status != ZX_OK) {
93 zxlogf(ERROR, "acpi-bus: error %d in device_add(sys/cpu-trace)\n", status);
94 cpu_trace_release(dev);
95 return status;
96 }
97
98 return ZX_OK;
99 }
100