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 #pragma once
6 
7 #include <ddk/protocol/pci.h>
8 #include <ddk/mmio-buffer.h>
9 
10 __BEGIN_CDECLS;
11 
pci_map_bar_buffer(const pci_protocol_t * pci,uint32_t bar_id,uint32_t cache_policy,mmio_buffer_t * buffer)12 static inline zx_status_t pci_map_bar_buffer(const pci_protocol_t* pci, uint32_t bar_id,
13                                       uint32_t cache_policy, mmio_buffer_t* buffer) {
14 
15     zx_pci_bar_t bar;
16 
17     zx_status_t status = pci->ops->get_bar(pci->ctx, bar_id, &bar);
18     if (status != ZX_OK) {
19         return status;
20     }
21     // TODO(cja): PIO may be mappable on non-x86 architectures
22     if (bar.type == ZX_PCI_BAR_TYPE_PIO || bar.handle == ZX_HANDLE_INVALID) {
23         return ZX_ERR_WRONG_TYPE;
24     }
25     return mmio_buffer_init(buffer, 0, bar.size, bar.handle, cache_policy);
26 }
27 
pci_config_read8(const pci_protocol_t * pci,uint16_t offset,uint8_t * value)28 static inline zx_status_t pci_config_read8(const pci_protocol_t* pci,
29                                            uint16_t offset, uint8_t* value) {
30     uint32_t value_;
31     zx_status_t st = pci->ops->config_read(pci->ctx, offset, sizeof(uint8_t), &value_);
32     *value = value_ & UINT8_MAX;
33     return st;
34 }
35 
pci_config_read16(const pci_protocol_t * pci,uint16_t offset,uint16_t * value)36 static inline zx_status_t pci_config_read16(const pci_protocol_t* pci,
37                                             uint16_t offset, uint16_t* value) {
38     uint32_t value_;
39     zx_status_t st = pci->ops->config_read(pci->ctx, offset, sizeof(uint16_t), &value_);
40     *value = value_ & UINT16_MAX;
41     return st;
42 }
43 
pci_config_read32(const pci_protocol_t * pci,uint16_t offset,uint32_t * value)44 static inline zx_status_t pci_config_read32(const pci_protocol_t* pci,
45                                             uint16_t offset, uint32_t* value) {
46     return pci->ops->config_read(pci->ctx, offset, sizeof(uint32_t), value);
47 }
48 
pci_config_write8(const pci_protocol_t * pci,uint16_t offset,uint8_t value)49 static inline zx_status_t pci_config_write8(const pci_protocol_t* pci,
50                                             uint16_t offset, uint8_t value) {
51     return pci->ops->config_write(pci->ctx, offset, sizeof(uint8_t), value);
52 }
53 
pci_config_write16(const pci_protocol_t * pci,uint16_t offset,uint16_t value)54 static inline zx_status_t pci_config_write16(const pci_protocol_t* pci,
55                                              uint16_t offset, uint16_t value) {
56     return pci->ops->config_write(pci->ctx, offset, sizeof(uint16_t), value);
57 }
58 
pci_config_write32(const pci_protocol_t * pci,uint16_t offset,uint32_t value)59 static inline zx_status_t pci_config_write32(const pci_protocol_t* pci,
60                                              uint16_t offset, uint32_t value) {
61     return pci->ops->config_write(pci->ctx, offset, sizeof(uint32_t), value);
62 }
63 
pci_get_first_capability(const pci_protocol_t * pci,uint8_t type)64 static inline uint8_t pci_get_first_capability(const pci_protocol_t* pci, uint8_t type) {
65     // the next_capability method will always look at the second byte next
66     // pointer to fetch the next capability. By offsetting the CapPtr field
67     // by -1 we can pretend we're working with a normal capability entry
68     return pci_get_next_capability(pci, PCI_CFG_CAPABILITIES_PTR - 1u, type);
69 }
70 
71 __END_CDECLS;
72