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 0x1537: 128 case 0x15df: 129 break; 130 default: 131 return 0.0f; 132 } 133 #ifdef TRACE_CCP_RNG 134 TRACE("CCP RNG device found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID); 135 #endif 136 return 0.8f; 137 } 138 139 140 // #pragma mark - 141 142 143 driver_module_info gCcpPciDevice = { 144 { 145 CCP_PCI_DEVICE_MODULE_NAME, 146 0, 147 NULL 148 }, 149 150 supports_device, 151 register_device, 152 init_device, 153 uninit_device, 154 NULL, // register_child_devices, 155 NULL, // rescan 156 NULL, // device removed 157 }; 158 159