1#include <acpi/uacpi_interface.h>
2#include <asm.h>
3#include <console/printf.h>
4#include <drivers/pci.h>
5#include <mem/alloc.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <uacpi/kernel_api.h>
9#include <uacpi/types.h>
10
11#include "uacpi/status.h"
12
13uacpi_status uacpi_kernel_pci_device_open(uacpi_pci_address address,
14 uacpi_handle *out_handle) {
15
16 if (!out_handle) {
17 return UACPI_STATUS_INVALID_ARGUMENT;
18 }
19
20 if (address.segment != 0) {
21 printf(format: "PCI segment %u not supported\n", address.segment);
22 return UACPI_STATUS_INVALID_ARGUMENT;
23 }
24
25 uint8_t bus = address.bus;
26 uint8_t slot = address.device;
27 uint8_t func = address.function;
28
29 uacpi_pci_device *dev = kmalloc(sizeof(*dev), ALLOC_FLAGS_ZERO);
30
31 if (!dev) {
32 return UACPI_STATUS_OUT_OF_MEMORY;
33 }
34
35 dev->bus = bus;
36 dev->slot = slot;
37 dev->func = func;
38 dev->is_open = true;
39
40 *out_handle = dev;
41 return UACPI_STATUS_OK;
42}
43
44void uacpi_kernel_pci_device_close(uacpi_handle handle) {
45 uacpi_pci_device *dev = (uacpi_pci_device *) handle;
46 if (!dev->is_open) {
47 return;
48 }
49 dev->is_open = false;
50 kfree(dev);
51}
52
53uacpi_status uacpi_kernel_pci_read8(uacpi_handle device, uacpi_size offset,
54 uacpi_u8 *value) {
55
56 uacpi_pci_device *dev = (uacpi_pci_device *) device;
57 if (!dev || !value || !dev->is_open || offset >= 256) {
58 return UACPI_STATUS_INVALID_ARGUMENT;
59 }
60 *value = pci_read_byte(bus: dev->bus, slot: dev->slot, func: dev->func, offset);
61 return UACPI_STATUS_OK;
62}
63
64uacpi_status uacpi_kernel_pci_read16(uacpi_handle device, uacpi_size offset,
65 uacpi_u16 *value) {
66
67 uacpi_pci_device *dev = (uacpi_pci_device *) device;
68 if (!dev || !value || !dev->is_open || offset >= 256 || (offset & 1)) {
69 return UACPI_STATUS_INVALID_ARGUMENT;
70 }
71
72 *value = pci_read_word(bus: dev->bus, slot: dev->slot, func: dev->func, offset);
73 return UACPI_STATUS_OK;
74}
75
76uacpi_status uacpi_kernel_pci_read32(uacpi_handle device, uacpi_size offset,
77 uacpi_u32 *value) {
78
79 uacpi_pci_device *dev = (uacpi_pci_device *) device;
80 if (!dev || !value || !dev->is_open || offset >= 256 || (offset & 3)) {
81 return UACPI_STATUS_INVALID_ARGUMENT;
82 }
83
84 *value = pci_read(bus: dev->bus, slot: dev->slot, func: dev->func, offset);
85 return UACPI_STATUS_OK;
86}
87
88uacpi_status uacpi_kernel_pci_write8(uacpi_handle device, uacpi_size offset,
89 uacpi_u8 value) {
90
91 uacpi_pci_device *dev = (uacpi_pci_device *) device;
92 if (!dev || !dev->is_open || offset >= 256) {
93 return UACPI_STATUS_INVALID_ARGUMENT;
94 }
95
96 pci_write_byte(bus: dev->bus, slot: dev->slot, func: dev->func, offset, value);
97 return UACPI_STATUS_OK;
98}
99
100uacpi_status uacpi_kernel_pci_write16(uacpi_handle device, uacpi_size offset,
101 uacpi_u16 value) {
102
103 uacpi_pci_device *dev = (uacpi_pci_device *) device;
104 if (!dev || !dev->is_open || offset >= 256 || (offset & 1)) {
105 return UACPI_STATUS_INVALID_ARGUMENT;
106 }
107
108 pci_write_word(bus: dev->bus, slot: dev->slot, func: dev->func, offset, value);
109 return UACPI_STATUS_OK;
110}
111
112uacpi_status uacpi_kernel_pci_write32(uacpi_handle device, uacpi_size offset,
113 uacpi_u32 value) {
114
115 uacpi_pci_device *dev = (uacpi_pci_device *) device;
116 if (!dev || !dev->is_open || offset >= 256 || (offset & 3)) {
117 return UACPI_STATUS_INVALID_ARGUMENT;
118 }
119
120 pci_write(bus: dev->bus, slot: dev->slot, func: dev->func, offset, value);
121 return UACPI_STATUS_OK;
122}
123
124#define IO_ACCESS_GUARD() \
125 if (!handle || !handle->valid || offset >= handle->len || \
126 (handle->base + offset) > 0xFFFF) { \
127 return UACPI_STATUS_INVALID_ARGUMENT; \
128 }
129
130uacpi_status uacpi_kernel_io_read8(uacpi_handle h, uacpi_size offset,
131 uacpi_u8 *out) {
132 uacpi_io_handle *handle = (uacpi_io_handle *) h;
133 IO_ACCESS_GUARD();
134 *out = inb(port: (uint16_t) (handle->base + offset));
135 return UACPI_STATUS_OK;
136}
137
138uacpi_status uacpi_kernel_io_read16(uacpi_handle h, uacpi_size offset,
139 uacpi_u16 *out) {
140 uacpi_io_handle *handle = (uacpi_io_handle *) h;
141 IO_ACCESS_GUARD();
142 *out = inw(port: (uint16_t) (handle->base + offset));
143 return UACPI_STATUS_OK;
144}
145
146uacpi_status uacpi_kernel_io_read32(uacpi_handle h, uacpi_size offset,
147 uacpi_u32 *out) {
148 uacpi_io_handle *handle = (uacpi_io_handle *) h;
149 IO_ACCESS_GUARD();
150 *out = inl(port: (uint16_t) (handle->base + offset));
151 return UACPI_STATUS_OK;
152}
153
154uacpi_status uacpi_kernel_io_write8(uacpi_handle h, uacpi_size offset,
155 uacpi_u8 val) {
156 uacpi_io_handle *handle = (uacpi_io_handle *) h;
157 IO_ACCESS_GUARD();
158 outb(port: (uint16_t) (handle->base + offset), value: val);
159 return UACPI_STATUS_OK;
160}
161
162uacpi_status uacpi_kernel_io_write16(uacpi_handle h, uacpi_size offset,
163 uacpi_u16 val) {
164 uacpi_io_handle *handle = (uacpi_io_handle *) h;
165 IO_ACCESS_GUARD();
166 outw(port: (uint16_t) (handle->base + offset), value: val);
167 return UACPI_STATUS_OK;
168}
169
170uacpi_status uacpi_kernel_io_write32(uacpi_handle h, uacpi_size offset,
171 uacpi_u32 val) {
172 uacpi_io_handle *handle = (uacpi_io_handle *) h;
173 IO_ACCESS_GUARD();
174 outl(port: (uint16_t) (handle->base + offset), value: val);
175 return UACPI_STATUS_OK;
176}
177