xref: /haiku/src/add-ons/kernel/busses/random/ccp/ccp_pci.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
1 /*
2  * Copyright 2022, Jérôme Duval, jerome.duval@gmail.com.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <new>
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include <ByteOrder.h>
12 #include <bus/PCI.h>
13 #include <PCI_x86.h>
14 
15 #define DRIVER_NAME "ccp_rng_pci"
16 #include "ccp.h"
17 
18 
19 typedef struct {
20 	ccp_device_info info;
21 	pci_device_module_info* pci;
22 	pci_device* device;
23 
24 	pci_info pciinfo;
25 } ccp_pci_sim_info;
26 
27 
28 //	#pragma mark -
29 
30 
31 static status_t
32 init_device(device_node* node, void** device_cookie)
33 {
34 	CALLED();
35 	ccp_pci_sim_info* bus = (ccp_pci_sim_info*)calloc(1,
36 		sizeof(ccp_pci_sim_info));
37 	if (bus == NULL)
38 		return B_NO_MEMORY;
39 
40 	pci_device_module_info* pci;
41 	pci_device* device;
42 	{
43 		device_node* pciParent = gDeviceManager->get_parent_node(node);
44 		gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
45 			(void**)&device);
46 		gDeviceManager->put_node(pciParent);
47 	}
48 
49 	bus->pci = pci;
50 	bus->device = device;
51 
52 	pci_info *pciInfo = &bus->pciinfo;
53 	pci->get_pci_info(device, pciInfo);
54 
55 #define BAR_INDEX 2
56 	bus->info.base_addr = pciInfo->u.h0.base_registers[BAR_INDEX];
57 	bus->info.map_size = pciInfo->u.h0.base_register_sizes[BAR_INDEX];
58 	if ((pciInfo->u.h0.base_register_flags[BAR_INDEX] & PCI_address_type)
59 			== PCI_address_type_64) {
60 		bus->info.base_addr |= (uint64)pciInfo->u.h0.base_registers[BAR_INDEX + 1] << 32;
61 		bus->info.map_size |= (uint64)pciInfo->u.h0.base_register_sizes[BAR_INDEX + 1] << 32;
62 	}
63 
64 	if (bus->info.base_addr == 0) {
65 		ERROR("PCI BAR not assigned\n");
66 		free(bus);
67 		return B_ERROR;
68 	}
69 
70 	// enable bus master and memory
71 	uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
72 	pcicmd |= PCI_command_master | PCI_command_memory;
73 	pci->write_pci_config(device, PCI_command, 2, pcicmd);
74 
75 	*device_cookie = bus;
76 	return B_OK;
77 }
78 
79 
80 static void
81 uninit_device(void* device_cookie)
82 {
83 	ccp_pci_sim_info* bus = (ccp_pci_sim_info*)device_cookie;
84 	free(bus);
85 }
86 
87 
88 static status_t
89 register_device(device_node* parent)
90 {
91 	device_attr attrs[] = {
92 		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "CCP PCI"}},
93 		{B_DEVICE_BUS, B_STRING_TYPE, {.string = "CCP"}},
94 		{B_DEVICE_FIXED_CHILD, B_STRING_TYPE, {.string = CCP_DEVICE_MODULE_NAME}},
95 		{}
96 	};
97 
98 	return gDeviceManager->register_node(parent,
99 		CCP_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
100 }
101 
102 
103 static float
104 supports_device(device_node* parent)
105 {
106 	const char* bus;
107 	uint16 vendorID, deviceID;
108 
109 	// make sure parent is a CCP PCI device node
110 	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
111 		< B_OK || gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID,
112 				&vendorID, false) < B_OK
113 		|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID,
114 				false) < B_OK) {
115 		return -1;
116 	}
117 
118 	if (strcmp(bus, "pci") != 0)
119 		return 0.0f;
120 
121 	if (vendorID != 0x1022)
122 		return 0.0f;
123 
124 	switch (deviceID) {
125 		case 0x1456:
126 		case 0x1468:
127 		case 0x1486:
128 		case 0x1537:
129 		case 0x15df:
130 			break;
131 		default:
132 			return 0.0f;
133 	}
134 #ifdef TRACE_CCP_RNG
135 	TRACE("CCP RNG device found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
136 #endif
137 	return 0.8f;
138 }
139 
140 
141 //	#pragma mark -
142 
143 
144 driver_module_info gCcpPciDevice = {
145 	{
146 		CCP_PCI_DEVICE_MODULE_NAME,
147 		0,
148 		NULL
149 	},
150 
151 	supports_device,
152 	register_device,
153 	init_device,
154 	uninit_device,
155 	NULL,	// register_child_devices,
156 	NULL,	// rescan
157 	NULL,	// device removed
158 };
159 
160