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