ccp: driver for the RNG part of CCP on AMD
the entropy source is read every second and pushed to the PRNG. the PCI device is tested, not the ACPI. Change-Id: I9bb6b21c7189b28a1d8a624d83b33ff6682152dc Reviewed-on: https://review.haiku-os.org/c/haiku/+/5825 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Jérôme Duval <[email protected]>
This commit is contained in:
@@ -30,7 +30,7 @@ AddFilesToPackage add-ons kernel busses ata
|
|||||||
|
|
||||||
AddFilesToPackage add-ons kernel busses i2c : pch_i2c@x86,x86_64 ;
|
AddFilesToPackage add-ons kernel busses i2c : pch_i2c@x86,x86_64 ;
|
||||||
AddFilesToPackage add-ons kernel busses mmc : sdhci_pci ;
|
AddFilesToPackage add-ons kernel busses mmc : sdhci_pci ;
|
||||||
AddFilesToPackage add-ons kernel busses random : virtio_rng ;
|
AddFilesToPackage add-ons kernel busses random : ccp_rng@x86,x86_64 virtio_rng ;
|
||||||
AddFilesToPackage add-ons kernel busses scsi : ahci virtio_scsi ;
|
AddFilesToPackage add-ons kernel busses scsi : ahci virtio_scsi ;
|
||||||
AddFilesToPackage add-ons kernel busses usb : <usb>uhci <usb>ohci <usb>ehci
|
AddFilesToPackage add-ons kernel busses usb : <usb>uhci <usb>ohci <usb>ehci
|
||||||
<usb>xhci ;
|
<usb>xhci ;
|
||||||
|
|||||||
@@ -620,6 +620,13 @@ struct pci_module_info {
|
|||||||
#define PCI_wireless_cellular_ethernet 0x41
|
#define PCI_wireless_cellular_ethernet 0x41
|
||||||
#define PCI_wireless_other 0x80
|
#define PCI_wireless_other 0x80
|
||||||
|
|
||||||
|
/* ---
|
||||||
|
values for the class_sub field for class_base = 0x10 (encryption decryption)
|
||||||
|
--- */
|
||||||
|
#define PCI_encryption_decryption_network_computing 0x00
|
||||||
|
#define PCI_encryption_decryption_entertainment 0x10
|
||||||
|
#define PCI_encryption_decryption_other 0x80
|
||||||
|
|
||||||
/* ---
|
/* ---
|
||||||
values for the class_sub field for class_base = 0x11 (data acquisition)
|
values for the class_sub field for class_base = 0x11 (data acquisition)
|
||||||
--- */
|
--- */
|
||||||
|
|||||||
@@ -7,3 +7,7 @@ KernelAddon virtio_rng :
|
|||||||
virtio_rng.cpp
|
virtio_rng.cpp
|
||||||
VirtioRNGDevice.cpp
|
VirtioRNGDevice.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel busses random ccp ;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel busses random ccp ;
|
||||||
|
|
||||||
|
UsePrivateHeaders drivers ;
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) bus_managers acpi acpica include ] ;
|
||||||
|
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) bus_managers acpi acpica include platform ] ;
|
||||||
|
|
||||||
|
|
||||||
|
KernelAddon ccp_rng :
|
||||||
|
ccp.cpp
|
||||||
|
ccp_acpi.cpp
|
||||||
|
ccp_pci.cpp
|
||||||
|
;
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <condition_variable.h>
|
||||||
|
#include <dpc.h>
|
||||||
|
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
|
#include "ccp.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define CCP_REG_TRNG 0xc
|
||||||
|
|
||||||
|
|
||||||
|
device_manager_info* gDeviceManager;
|
||||||
|
random_for_controller_interface *gRandom;
|
||||||
|
dpc_module_info *gDPC;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
handleDPC(void *arg)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
ccp_device_info* bus = reinterpret_cast<ccp_device_info*>(arg);
|
||||||
|
|
||||||
|
uint32 lowValue = read32(bus->registers + CCP_REG_TRNG);
|
||||||
|
uint32 highValue = read32(bus->registers + CCP_REG_TRNG);
|
||||||
|
if (lowValue == 0 || highValue == 0)
|
||||||
|
return;
|
||||||
|
gRandom->queue_randomness((uint64)lowValue | ((uint64)highValue << 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32
|
||||||
|
handleTimerHook(struct timer* timer)
|
||||||
|
{
|
||||||
|
ccp_device_info* bus = reinterpret_cast<ccp_device_info*>(timer->user_data);
|
||||||
|
|
||||||
|
gDPC->queue_dpc(bus->dpcHandle, handleDPC, bus);
|
||||||
|
return B_HANDLED_INTERRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_device(device_node* parent)
|
||||||
|
{
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "CCP device"}},
|
||||||
|
{B_DEVICE_BUS, B_STRING_TYPE, {string: "CCP"}},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_node(parent,
|
||||||
|
CCP_DEVICE_MODULE_NAME, attrs, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
init_bus(device_node* node, void** bus_cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
driver_module_info* driver;
|
||||||
|
ccp_device_info* bus;
|
||||||
|
device_node* parent = gDeviceManager->get_parent_node(node);
|
||||||
|
gDeviceManager->get_driver(parent, &driver, (void**)&bus);
|
||||||
|
gDeviceManager->put_node(parent);
|
||||||
|
|
||||||
|
TRACE_ALWAYS("init_bus() addr 0x%" B_PRIxPHYSADDR " size 0x%" B_PRIx64
|
||||||
|
" \n", bus->base_addr, bus->map_size);
|
||||||
|
|
||||||
|
bus->registersArea = map_physical_memory("CCP memory mapped registers",
|
||||||
|
bus->base_addr, bus->map_size, B_ANY_KERNEL_ADDRESS,
|
||||||
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA,
|
||||||
|
(void **)&bus->registers);
|
||||||
|
if (bus->registersArea < 0)
|
||||||
|
return bus->registersArea;
|
||||||
|
|
||||||
|
status_t status = gDPC->new_dpc_queue(&bus->dpcHandle, "ccp timer",
|
||||||
|
B_LOW_PRIORITY);
|
||||||
|
if (status != B_OK) {
|
||||||
|
ERROR("dpc setup failed (%s)\n", strerror(status));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus->extractTimer.user_data = bus;
|
||||||
|
status = add_timer(&bus->extractTimer, &handleTimerHook, 1 * 1000 * 1000, B_PERIODIC_TIMER);
|
||||||
|
if (status != B_OK) {
|
||||||
|
ERROR("timer setup failed (%s)\n", strerror(status));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger also now
|
||||||
|
gDPC->queue_dpc(bus->dpcHandle, handleDPC, bus);
|
||||||
|
|
||||||
|
*bus_cookie = bus;
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninit_bus(void* bus_cookie)
|
||||||
|
{
|
||||||
|
ccp_device_info* bus = (ccp_device_info*)bus_cookie;
|
||||||
|
|
||||||
|
cancel_timer(&bus->extractTimer);
|
||||||
|
gDPC->delete_dpc_queue(&bus->dpcHandle);
|
||||||
|
|
||||||
|
if (bus->registersArea >= 0)
|
||||||
|
delete_area(bus->registersArea);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
module_dependency module_dependencies[] = {
|
||||||
|
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
|
||||||
|
{ RANDOM_FOR_CONTROLLER_MODULE_NAME, (module_info**)&gRandom },
|
||||||
|
{ B_DPC_MODULE_NAME, (module_info **)&gDPC },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static driver_module_info sCcpDeviceModule = {
|
||||||
|
{
|
||||||
|
CCP_DEVICE_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
|
||||||
|
NULL, // supports device
|
||||||
|
register_device,
|
||||||
|
init_bus,
|
||||||
|
uninit_bus,
|
||||||
|
NULL, // register child devices
|
||||||
|
NULL, // rescan
|
||||||
|
NULL, // device removed
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module_info* modules[] = {
|
||||||
|
(module_info* )&gCcpAcpiDevice,
|
||||||
|
(module_info* )&sCcpDeviceModule,
|
||||||
|
(module_info* )&gCcpPciDevice,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022, Jérôme Duval, [email protected].
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _CCP_H
|
||||||
|
#define _CCP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_CCP_RNG
|
||||||
|
#ifndef DRIVER_NAME
|
||||||
|
# define DRIVER_NAME "ccp_rng"
|
||||||
|
#endif
|
||||||
|
#ifdef TRACE_CCP_RNG
|
||||||
|
# define TRACE(x...) dprintf("\33[33m" DRIVER_NAME ":\33[0m " x)
|
||||||
|
#else
|
||||||
|
# define TRACE(x...) ;
|
||||||
|
#endif
|
||||||
|
#define TRACE_ALWAYS(x...) dprintf("\33[33m" DRIVER_NAME ":\33[0m " x)
|
||||||
|
#define ERROR(x...) dprintf("\33[33m" DRIVER_NAME ":\33[0m " x)
|
||||||
|
#define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
|
||||||
|
#define CCP_ACPI_DEVICE_MODULE_NAME "busses/random/ccp_rng/acpi/driver_v1"
|
||||||
|
#define CCP_PCI_DEVICE_MODULE_NAME "busses/random/ccp_rng/pci/driver_v1"
|
||||||
|
#define CCP_DEVICE_MODULE_NAME "busses/random/ccp_rng/device/v1"
|
||||||
|
|
||||||
|
|
||||||
|
#define read32(address) \
|
||||||
|
(*((volatile uint32*)(address)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern device_manager_info* gDeviceManager;
|
||||||
|
extern driver_module_info gCcpAcpiDevice;
|
||||||
|
extern driver_module_info gCcpPciDevice;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
phys_addr_t base_addr;
|
||||||
|
uint64 map_size;
|
||||||
|
|
||||||
|
device_node* node;
|
||||||
|
device_node* driver_node;
|
||||||
|
|
||||||
|
area_id registersArea;
|
||||||
|
addr_t registers;
|
||||||
|
|
||||||
|
timer extractTimer;
|
||||||
|
void* dpcHandle;
|
||||||
|
} ccp_device_info;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _CCP_H
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <ACPI.h>
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
#include <condition_variable.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
# include "acpi.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define DRIVER_NAME "ccp_rng_acpi"
|
||||||
|
#include "ccp.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ccp_device_info info;
|
||||||
|
acpi_device_module_info* acpi;
|
||||||
|
acpi_device device;
|
||||||
|
|
||||||
|
} ccp_acpi_sim_info;
|
||||||
|
|
||||||
|
|
||||||
|
struct ccp_crs {
|
||||||
|
uint32 addr_bas;
|
||||||
|
uint32 addr_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static acpi_status
|
||||||
|
ccp_scan_parse_callback(ACPI_RESOURCE *res, void *context)
|
||||||
|
{
|
||||||
|
struct ccp_crs* crs = (struct ccp_crs*)context;
|
||||||
|
|
||||||
|
if (res->Type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
|
||||||
|
crs->addr_bas = res->Data.FixedMemory32.Address;
|
||||||
|
crs->addr_len = res->Data.FixedMemory32.AddressLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
init_device(device_node* node, void** device_cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
|
ccp_acpi_sim_info* bus = (ccp_acpi_sim_info*)calloc(1,
|
||||||
|
sizeof(ccp_acpi_sim_info));
|
||||||
|
if (bus == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
acpi_device_module_info* acpi;
|
||||||
|
acpi_device device;
|
||||||
|
{
|
||||||
|
device_node* acpiParent = gDeviceManager->get_parent_node(node);
|
||||||
|
gDeviceManager->get_driver(acpiParent, (driver_module_info**)&acpi,
|
||||||
|
(void**)&device);
|
||||||
|
gDeviceManager->put_node(acpiParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bus->acpi = acpi;
|
||||||
|
bus->device = device;
|
||||||
|
|
||||||
|
struct ccp_crs crs;
|
||||||
|
status = acpi->walk_resources(device, (ACPI_STRING)"_CRS",
|
||||||
|
ccp_scan_parse_callback, &crs);
|
||||||
|
if (status != B_OK) {
|
||||||
|
ERROR("Error while getting resouces\n");
|
||||||
|
free(bus);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (crs.addr_bas == 0 || crs.addr_len == 0) {
|
||||||
|
TRACE("skipping non configured CCP devices\n");
|
||||||
|
free(bus);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bus->info.base_addr = crs.addr_bas;
|
||||||
|
bus->info.map_size = crs.addr_len;
|
||||||
|
|
||||||
|
*device_cookie = bus;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninit_device(void* device_cookie)
|
||||||
|
{
|
||||||
|
ccp_acpi_sim_info* bus = (ccp_acpi_sim_info*)device_cookie;
|
||||||
|
free(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_device(device_node* parent)
|
||||||
|
{
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "CCP ACPI"}},
|
||||||
|
{B_DEVICE_BUS, B_STRING_TYPE, {string: "CCP"}},
|
||||||
|
{B_DEVICE_FIXED_CHILD, B_STRING_TYPE, {string: CCP_DEVICE_MODULE_NAME}},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_node(parent,
|
||||||
|
CCP_ACPI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static float
|
||||||
|
supports_device(device_node* parent)
|
||||||
|
{
|
||||||
|
const char* bus;
|
||||||
|
|
||||||
|
// make sure parent is a CCP ACPI device node
|
||||||
|
if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
|
||||||
|
< B_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(bus, "acpi") != 0)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
// check whether it's really a device
|
||||||
|
uint32 device_type;
|
||||||
|
if (gDeviceManager->get_attr_uint32(parent, ACPI_DEVICE_TYPE_ITEM,
|
||||||
|
&device_type, false) != B_OK
|
||||||
|
|| device_type != ACPI_TYPE_DEVICE) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether it's a CCP device
|
||||||
|
const char *name;
|
||||||
|
if (gDeviceManager->get_attr_string(parent, ACPI_DEVICE_HID_ITEM, &name,
|
||||||
|
false) != B_OK) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(name, "AMDI0C00") == 0) {
|
||||||
|
TRACE("CCP device found! name %s\n", name);
|
||||||
|
return 0.6f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
driver_module_info gCcpAcpiDevice = {
|
||||||
|
{
|
||||||
|
CCP_ACPI_DEVICE_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
|
||||||
|
supports_device,
|
||||||
|
register_device,
|
||||||
|
init_device,
|
||||||
|
uninit_device,
|
||||||
|
NULL, // register_child_devices,
|
||||||
|
NULL, // rescan
|
||||||
|
NULL, // device removed
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022, Jérôme Duval, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
#include <bus/PCI.h>
|
||||||
|
#include <PCI_x86.h>
|
||||||
|
|
||||||
|
#define DRIVER_NAME "ccp_rng_pci"
|
||||||
|
#include "ccp.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ccp_device_info info;
|
||||||
|
pci_device_module_info* pci;
|
||||||
|
pci_device* device;
|
||||||
|
|
||||||
|
pci_info pciinfo;
|
||||||
|
} ccp_pci_sim_info;
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
init_device(device_node* node, void** device_cookie)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
ccp_pci_sim_info* bus = (ccp_pci_sim_info*)calloc(1,
|
||||||
|
sizeof(ccp_pci_sim_info));
|
||||||
|
if (bus == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
pci_device_module_info* pci;
|
||||||
|
pci_device* device;
|
||||||
|
{
|
||||||
|
device_node* pciParent = gDeviceManager->get_parent_node(node);
|
||||||
|
gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci,
|
||||||
|
(void**)&device);
|
||||||
|
gDeviceManager->put_node(pciParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bus->pci = pci;
|
||||||
|
bus->device = device;
|
||||||
|
|
||||||
|
pci_info *pciInfo = &bus->pciinfo;
|
||||||
|
pci->get_pci_info(device, pciInfo);
|
||||||
|
|
||||||
|
#define BAR_INDEX 2
|
||||||
|
bus->info.base_addr = pciInfo->u.h0.base_registers[BAR_INDEX];
|
||||||
|
bus->info.map_size = pciInfo->u.h0.base_register_sizes[BAR_INDEX];
|
||||||
|
if ((pciInfo->u.h0.base_register_flags[BAR_INDEX] & PCI_address_type)
|
||||||
|
== PCI_address_type_64) {
|
||||||
|
bus->info.base_addr |= (uint64)pciInfo->u.h0.base_registers[BAR_INDEX + 1] << 32;
|
||||||
|
bus->info.map_size |= (uint64)pciInfo->u.h0.base_register_sizes[BAR_INDEX + 1] << 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bus->info.base_addr == 0) {
|
||||||
|
ERROR("PCI BAR not assigned\n");
|
||||||
|
free(bus);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable bus master and memory
|
||||||
|
uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2);
|
||||||
|
pcicmd |= PCI_command_master | PCI_command_memory;
|
||||||
|
pci->write_pci_config(device, PCI_command, 2, pcicmd);
|
||||||
|
|
||||||
|
*device_cookie = bus;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninit_device(void* device_cookie)
|
||||||
|
{
|
||||||
|
ccp_pci_sim_info* bus = (ccp_pci_sim_info*)device_cookie;
|
||||||
|
free(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
register_device(device_node* parent)
|
||||||
|
{
|
||||||
|
device_attr attrs[] = {
|
||||||
|
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "CCP PCI"}},
|
||||||
|
{B_DEVICE_BUS, B_STRING_TYPE, {string: "CCP"}},
|
||||||
|
{B_DEVICE_FIXED_CHILD, B_STRING_TYPE, {string: CCP_DEVICE_MODULE_NAME}},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
return gDeviceManager->register_node(parent,
|
||||||
|
CCP_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static float
|
||||||
|
supports_device(device_node* parent)
|
||||||
|
{
|
||||||
|
const char* bus;
|
||||||
|
uint16 vendorID, deviceID;
|
||||||
|
|
||||||
|
// make sure parent is a CCP PCI device node
|
||||||
|
if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
|
||||||
|
< B_OK || gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID,
|
||||||
|
&vendorID, false) < B_OK
|
||||||
|
|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID,
|
||||||
|
false) < B_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(bus, "pci") != 0)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
if (vendorID != 0x1022)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
switch (deviceID) {
|
||||||
|
case 0x1456:
|
||||||
|
case 0x1468:
|
||||||
|
case 0x1486:
|
||||||
|
case 0x1537:
|
||||||
|
case 0x15df:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
#ifdef TRACE_CCP_RNG
|
||||||
|
TRACE("CCP RNG device found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
|
||||||
|
#endif
|
||||||
|
return 0.8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
driver_module_info gCcpPciDevice = {
|
||||||
|
{
|
||||||
|
CCP_PCI_DEVICE_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
|
||||||
|
supports_device,
|
||||||
|
register_device,
|
||||||
|
init_device,
|
||||||
|
uninit_device,
|
||||||
|
NULL, // register_child_devices,
|
||||||
|
NULL, // rescan
|
||||||
|
NULL, // device removed
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1727,6 +1727,16 @@ device_node::_GetNextDriverPath(void*& cookie, KPath& _path)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PCI_encryption_decryption:
|
||||||
|
switch (subType) {
|
||||||
|
case PCI_encryption_decryption_other:
|
||||||
|
_AddPath(*stack, "busses", "random");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_AddPath(*stack, "drivers");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PCI_data_acquisition:
|
case PCI_data_acquisition:
|
||||||
switch (subType) {
|
switch (subType) {
|
||||||
case PCI_data_acquisition_other:
|
case PCI_data_acquisition_other:
|
||||||
@@ -1874,7 +1884,14 @@ device_node::_AlwaysRegisterDynamic()
|
|||||||
get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
|
get_attr_uint16(this, B_DEVICE_TYPE, &type, false);
|
||||||
get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
|
get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false);
|
||||||
|
|
||||||
return type == PCI_serial_bus || type == PCI_bridge || type == 0;
|
switch (type) {
|
||||||
|
case PCI_serial_bus:
|
||||||
|
case PCI_bridge:
|
||||||
|
case PCI_encryption_decryption:
|
||||||
|
case 0:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
// TODO: we may want to be a bit more specific in the future
|
// TODO: we may want to be a bit more specific in the future
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user