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