1652d5f63SJérôme Duval /*
2652d5f63SJérôme Duval * Copyright 2022, Jérôme Duval, jerome.duval@gmail.com.
3652d5f63SJérôme Duval * Distributed under the terms of the MIT License.
4652d5f63SJérôme Duval */
5652d5f63SJérôme Duval
6652d5f63SJérôme Duval
7652d5f63SJérôme Duval #include <new>
8652d5f63SJérôme Duval #include <stdio.h>
9652d5f63SJérôme Duval #include <string.h>
10652d5f63SJérôme Duval
11652d5f63SJérôme Duval #include <ByteOrder.h>
12652d5f63SJérôme Duval #include <bus/PCI.h>
13652d5f63SJérôme Duval
14652d5f63SJérôme Duval #define DRIVER_NAME "ccp_rng_pci"
15652d5f63SJérôme Duval #include "ccp.h"
16652d5f63SJérôme Duval
17652d5f63SJérôme Duval
18652d5f63SJérôme Duval typedef struct {
19652d5f63SJérôme Duval ccp_device_info info;
20652d5f63SJérôme Duval pci_device_module_info* pci;
21652d5f63SJérôme Duval pci_device* device;
22652d5f63SJérôme Duval
23652d5f63SJérôme Duval pci_info pciinfo;
24652d5f63SJérôme Duval } ccp_pci_sim_info;
25652d5f63SJérôme Duval
26652d5f63SJérôme Duval
27652d5f63SJérôme Duval // #pragma mark -
28652d5f63SJérôme Duval
29652d5f63SJérôme Duval
30652d5f63SJérôme Duval static status_t
init_device(device_node * node,void ** device_cookie)31652d5f63SJérôme Duval init_device(device_node* node, void** device_cookie)
32652d5f63SJérôme Duval {
33652d5f63SJérôme Duval CALLED();
34652d5f63SJérôme Duval ccp_pci_sim_info* bus = (ccp_pci_sim_info*)calloc(1,
35652d5f63SJérôme Duval sizeof(ccp_pci_sim_info));
36652d5f63SJérôme Duval if (bus == NULL)
37652d5f63SJérôme Duval return B_NO_MEMORY;
38652d5f63SJérôme Duval
39652d5f63SJérôme Duval pci_device_module_info* pci;
40652d5f63SJérôme Duval pci_device* device;
41652d5f63SJérôme Duval {
42652d5f63SJérôme Duval device_node* pciParent = gDeviceManager->get_parent_node(node);
43652d5f63SJérôme Duval gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
44652d5f63SJérôme Duval (void**)&device);
45652d5f63SJérôme Duval gDeviceManager->put_node(pciParent);
46652d5f63SJérôme Duval }
47652d5f63SJérôme Duval
48652d5f63SJérôme Duval bus->pci = pci;
49652d5f63SJérôme Duval bus->device = device;
50652d5f63SJérôme Duval
51652d5f63SJérôme Duval pci_info *pciInfo = &bus->pciinfo;
52652d5f63SJérôme Duval pci->get_pci_info(device, pciInfo);
53652d5f63SJérôme Duval
54652d5f63SJérôme Duval #define BAR_INDEX 2
55652d5f63SJérôme Duval bus->info.base_addr = pciInfo->u.h0.base_registers[BAR_INDEX];
56652d5f63SJérôme Duval bus->info.map_size = pciInfo->u.h0.base_register_sizes[BAR_INDEX];
57652d5f63SJérôme Duval if ((pciInfo->u.h0.base_register_flags[BAR_INDEX] & PCI_address_type)
58652d5f63SJérôme Duval == PCI_address_type_64) {
59652d5f63SJérôme Duval bus->info.base_addr |= (uint64)pciInfo->u.h0.base_registers[BAR_INDEX + 1] << 32;
60652d5f63SJérôme Duval bus->info.map_size |= (uint64)pciInfo->u.h0.base_register_sizes[BAR_INDEX + 1] << 32;
61652d5f63SJérôme Duval }
62652d5f63SJérôme Duval
63652d5f63SJérôme Duval if (bus->info.base_addr == 0) {
64652d5f63SJérôme Duval ERROR("PCI BAR not assigned\n");
65652d5f63SJérôme Duval free(bus);
66652d5f63SJérôme Duval return B_ERROR;
67652d5f63SJérôme Duval }
68652d5f63SJérôme Duval
69652d5f63SJérôme Duval // enable bus master and memory
70652d5f63SJérôme Duval uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
71652d5f63SJérôme Duval pcicmd |= PCI_command_master | PCI_command_memory;
72652d5f63SJérôme Duval pci->write_pci_config(device, PCI_command, 2, pcicmd);
73652d5f63SJérôme Duval
74652d5f63SJérôme Duval *device_cookie = bus;
75652d5f63SJérôme Duval return B_OK;
76652d5f63SJérôme Duval }
77652d5f63SJérôme Duval
78652d5f63SJérôme Duval
79652d5f63SJérôme Duval static void
uninit_device(void * device_cookie)80652d5f63SJérôme Duval uninit_device(void* device_cookie)
81652d5f63SJérôme Duval {
82652d5f63SJérôme Duval ccp_pci_sim_info* bus = (ccp_pci_sim_info*)device_cookie;
83652d5f63SJérôme Duval free(bus);
84652d5f63SJérôme Duval }
85652d5f63SJérôme Duval
86652d5f63SJérôme Duval
87652d5f63SJérôme Duval static status_t
register_device(device_node * parent)88652d5f63SJérôme Duval register_device(device_node* parent)
89652d5f63SJérôme Duval {
90652d5f63SJérôme Duval device_attr attrs[] = {
91215b685fSX512 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "CCP PCI"}},
92215b685fSX512 {B_DEVICE_BUS, B_STRING_TYPE, {.string = "CCP"}},
93215b685fSX512 {B_DEVICE_FIXED_CHILD, B_STRING_TYPE, {.string = CCP_DEVICE_MODULE_NAME}},
94652d5f63SJérôme Duval {}
95652d5f63SJérôme Duval };
96652d5f63SJérôme Duval
97652d5f63SJérôme Duval return gDeviceManager->register_node(parent,
98652d5f63SJérôme Duval CCP_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
99652d5f63SJérôme Duval }
100652d5f63SJérôme Duval
101652d5f63SJérôme Duval
102652d5f63SJérôme Duval static float
supports_device(device_node * parent)103652d5f63SJérôme Duval supports_device(device_node* parent)
104652d5f63SJérôme Duval {
105652d5f63SJérôme Duval const char* bus;
106652d5f63SJérôme Duval uint16 vendorID, deviceID;
107652d5f63SJérôme Duval
108652d5f63SJérôme Duval // make sure parent is a CCP PCI device node
109652d5f63SJérôme Duval if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
110652d5f63SJérôme Duval < B_OK || gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID,
111652d5f63SJérôme Duval &vendorID, false) < B_OK
112652d5f63SJérôme Duval || gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID,
113652d5f63SJérôme Duval false) < B_OK) {
114652d5f63SJérôme Duval return -1;
115652d5f63SJérôme Duval }
116652d5f63SJérôme Duval
117652d5f63SJérôme Duval if (strcmp(bus, "pci") != 0)
118652d5f63SJérôme Duval return 0.0f;
119652d5f63SJérôme Duval
120652d5f63SJérôme Duval if (vendorID != 0x1022)
121652d5f63SJérôme Duval return 0.0f;
122652d5f63SJérôme Duval
123652d5f63SJérôme Duval switch (deviceID) {
124652d5f63SJérôme Duval case 0x1456:
125652d5f63SJérôme Duval case 0x1468:
126652d5f63SJérôme Duval case 0x1486:
127*33fb08b1SJérôme Duval case 0x14ca:
128652d5f63SJérôme Duval case 0x1537:
129652d5f63SJérôme Duval case 0x15df:
130*33fb08b1SJérôme Duval case 0x1649:
131652d5f63SJérôme Duval break;
132652d5f63SJérôme Duval default:
133652d5f63SJérôme Duval return 0.0f;
134652d5f63SJérôme Duval }
135652d5f63SJérôme Duval #ifdef TRACE_CCP_RNG
136652d5f63SJérôme Duval TRACE("CCP RNG device found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
137652d5f63SJérôme Duval #endif
138652d5f63SJérôme Duval return 0.8f;
139652d5f63SJérôme Duval }
140652d5f63SJérôme Duval
141652d5f63SJérôme Duval
142652d5f63SJérôme Duval // #pragma mark -
143652d5f63SJérôme Duval
144652d5f63SJérôme Duval
145652d5f63SJérôme Duval driver_module_info gCcpPciDevice = {
146652d5f63SJérôme Duval {
147652d5f63SJérôme Duval CCP_PCI_DEVICE_MODULE_NAME,
148652d5f63SJérôme Duval 0,
149652d5f63SJérôme Duval NULL
150652d5f63SJérôme Duval },
151652d5f63SJérôme Duval
152652d5f63SJérôme Duval supports_device,
153652d5f63SJérôme Duval register_device,
154652d5f63SJérôme Duval init_device,
155652d5f63SJérôme Duval uninit_device,
156652d5f63SJérôme Duval NULL, // register_child_devices,
157652d5f63SJérôme Duval NULL, // rescan
158652d5f63SJérôme Duval NULL, // device removed
159652d5f63SJérôme Duval };
160652d5f63SJérôme Duval
161