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 18typedef 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 30static status_t 31init_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 79static void 80uninit_device(void* device_cookie) 81{ 82 ccp_pci_sim_info* bus = (ccp_pci_sim_info*)device_cookie; 83 free(bus); 84} 85 86 87static status_t 88register_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 102static float 103supports_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 145driver_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