xref: /haiku/src/add-ons/kernel/busses/random/ccp/ccp_pci.cpp (revision 33fb08b1a597a3809e372d34002b4cc400aa9d4d)
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