From 036a8857a688d19fa7d268315d2df9253112e573 Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Tue, 28 Aug 2007 21:10:39 +0000 Subject: [PATCH] added a workaround to prevent loading the driver multiple times for the same device git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22099 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../busses/scsi/ahci/ahci_controller.cpp | 51 ++++++++++++++++--- .../kernel/busses/scsi/ahci/ahci_controller.h | 9 ++++ .../kernel/busses/scsi/ahci/ahci_sim.cpp | 31 +++++++---- 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp index 8f707d8cc6..40a4c69518 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.cpp @@ -6,6 +6,7 @@ #include "ahci_controller.h" #include +#include #define TRACE(a...) dprintf("\33[34mahci:\33[0m " a) #define FLOW(a...) dprintf("ahci: " a) @@ -15,18 +16,42 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device) : fNode(node) , fPCIDevice(device) , fDevicePresentMask(0) + , fInstanceCheck(-1) { - fDevicePresentMask = (1 << 7) | (1 << 19); +} - uint16 vendorID = gPCI->read_pci_config(fPCIDevice, PCI_vendor_id, 2); - uint16 deviceID = gPCI->read_pci_config(fPCIDevice, PCI_device_id, 2); - TRACE("AHCIController::AHCIController vendor %04x, device %04x\n", - vendorID, deviceID); +AHCIController::~AHCIController() +{ +} + + +status_t +AHCIController::Init() +{ + pci_info pciInfo; + + if (gPCI->get_pci_info(fPCIDevice, &pciInfo) < B_OK) { + dprintf("AHCIController::Init ERROR: getting PCI info failed!\n"); + return B_ERROR; + } + + TRACE("AHCIController::Init %u:%u:%u vendor %04x, device %04x\n", + pciInfo.bus, pciInfo.device, pciInfo.function, pciInfo.vendor_id, pciInfo.device_id); + +// --- Instance check workaround begin + char sName[32]; + snprintf(sName, sizeof(sName), "ahci-inst-%u-%u-%u", pciInfo.bus, pciInfo.device, pciInfo.function); + if (find_port(sName) >= 0) { + dprintf("AHCIController::Init ERROR: an instance for object %u:%u:%u already exists\n", + pciInfo.bus, pciInfo.device, pciInfo.function); + return B_ERROR; + } + fInstanceCheck = create_port(1, sName); +// --- Instance check workaround end uchar capabilityOffset; - status_t res = gPCI->find_pci_capability(fPCIDevice, PCI_cap_id_sata, - &capabilityOffset); + status_t res = gPCI->find_pci_capability(fPCIDevice, PCI_cap_id_sata, &capabilityOffset); if (res == B_OK) { uint32 satacr0; uint32 satacr1; @@ -35,11 +60,21 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device) satacr1 = gPCI->read_pci_config(fPCIDevice, capabilityOffset + 4, 4); TRACE("satacr0 = 0x%08lx, satacr1 = 0x%08lx\n", satacr0, satacr1); } + + fDevicePresentMask = (1 << 7) | (1 << 19); + + return B_OK; } -AHCIController::~AHCIController() +void +AHCIController::Uninit() { + TRACE("AHCIController::Uninit\n"); + +// --- Instance check workaround begin + delete_port(fInstanceCheck); +// --- Instance check workaround end } diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h index baa2c98796..2ea9fba242 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_controller.h @@ -15,6 +15,9 @@ public: pci_device_info *pciDevice); ~AHCIController(); + status_t Init(); + void Uninit(); + void ExecuteRequest(scsi_ccb *request); uchar AbortRequest(scsi_ccb *request); uchar TerminateRequest(scsi_ccb *request); @@ -29,6 +32,12 @@ private: device_node_handle fNode; pci_device_info* fPCIDevice; uint32 fDevicePresentMask; + + +// --- Instance check workaround begin + port_id fInstanceCheck; +// --- Instance check workaround end + }; diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_sim.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_sim.cpp index 63974b7357..e3b1e55baf 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_sim.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_sim.cpp @@ -124,22 +124,30 @@ ahci_ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer, static status_t ahci_sim_init_bus(device_node_handle node, void *userCookie, void **_cookie) { + pci_device_info *pciDevice; + device_node_handle parent; + AHCIController *controller; + status_t status; + TRACE("ahci_sim_init_bus, userCookie %p\n", userCookie); - device_node_handle parent = gDeviceManager->get_parent(node); - // initialize parent (the bus) to get the PCI interface and device - pci_device_info *pciDevice; - status_t status = gDeviceManager->init_driver(parent, &pciDevice, - NULL, NULL); + parent = gDeviceManager->get_parent(node); + status = gDeviceManager->init_driver(parent, &pciDevice, NULL, NULL); + gDeviceManager->put_device_node(parent); if (status != B_OK) return status; - gDeviceManager->put_device_node(parent); - - *_cookie = new(std::nothrow) AHCIController(node, pciDevice); - if (!*_cookie) + controller = new(std::nothrow) AHCIController(node, pciDevice); + if (!controller) return B_NO_MEMORY; + status = controller->Init(); + if (status < B_OK) { + delete controller; + return status; + } + + *_cookie = controller; TRACE("cookie = %p\n", *_cookie); return B_OK; } @@ -153,10 +161,13 @@ ahci_sim_uninit_bus(void *cookie) device_node_handle parent = gDeviceManager->get_parent( controller->DeviceNode()); + + controller->Uninit(); + delete controller; + gDeviceManager->uninit_driver(parent); gDeviceManager->put_device_node(parent); - delete controller; return B_OK; }