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
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include "ahci_controller.h"
|
#include "ahci_controller.h"
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define TRACE(a...) dprintf("\33[34mahci:\33[0m " a)
|
#define TRACE(a...) dprintf("\33[34mahci:\33[0m " a)
|
||||||
#define FLOW(a...) dprintf("ahci: " a)
|
#define FLOW(a...) dprintf("ahci: " a)
|
||||||
@@ -15,18 +16,42 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device)
|
|||||||
: fNode(node)
|
: fNode(node)
|
||||||
, fPCIDevice(device)
|
, fPCIDevice(device)
|
||||||
, fDevicePresentMask(0)
|
, 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",
|
AHCIController::~AHCIController()
|
||||||
vendorID, deviceID);
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
uchar capabilityOffset;
|
||||||
status_t res = gPCI->find_pci_capability(fPCIDevice, PCI_cap_id_sata,
|
status_t res = gPCI->find_pci_capability(fPCIDevice, PCI_cap_id_sata, &capabilityOffset);
|
||||||
&capabilityOffset);
|
|
||||||
if (res == B_OK) {
|
if (res == B_OK) {
|
||||||
uint32 satacr0;
|
uint32 satacr0;
|
||||||
uint32 satacr1;
|
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);
|
satacr1 = gPCI->read_pci_config(fPCIDevice, capabilityOffset + 4, 4);
|
||||||
TRACE("satacr0 = 0x%08lx, satacr1 = 0x%08lx\n", satacr0, satacr1);
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ public:
|
|||||||
pci_device_info *pciDevice);
|
pci_device_info *pciDevice);
|
||||||
~AHCIController();
|
~AHCIController();
|
||||||
|
|
||||||
|
status_t Init();
|
||||||
|
void Uninit();
|
||||||
|
|
||||||
void ExecuteRequest(scsi_ccb *request);
|
void ExecuteRequest(scsi_ccb *request);
|
||||||
uchar AbortRequest(scsi_ccb *request);
|
uchar AbortRequest(scsi_ccb *request);
|
||||||
uchar TerminateRequest(scsi_ccb *request);
|
uchar TerminateRequest(scsi_ccb *request);
|
||||||
@@ -29,6 +32,12 @@ private:
|
|||||||
device_node_handle fNode;
|
device_node_handle fNode;
|
||||||
pci_device_info* fPCIDevice;
|
pci_device_info* fPCIDevice;
|
||||||
uint32 fDevicePresentMask;
|
uint32 fDevicePresentMask;
|
||||||
|
|
||||||
|
|
||||||
|
// --- Instance check workaround begin
|
||||||
|
port_id fInstanceCheck;
|
||||||
|
// --- Instance check workaround end
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -124,22 +124,30 @@ ahci_ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer,
|
|||||||
static status_t
|
static status_t
|
||||||
ahci_sim_init_bus(device_node_handle node, void *userCookie, void **_cookie)
|
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);
|
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
|
// initialize parent (the bus) to get the PCI interface and device
|
||||||
pci_device_info *pciDevice;
|
parent = gDeviceManager->get_parent(node);
|
||||||
status_t status = gDeviceManager->init_driver(parent, &pciDevice,
|
status = gDeviceManager->init_driver(parent, &pciDevice, NULL, NULL);
|
||||||
NULL, NULL);
|
gDeviceManager->put_device_node(parent);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
gDeviceManager->put_device_node(parent);
|
controller = new(std::nothrow) AHCIController(node, pciDevice);
|
||||||
|
if (!controller)
|
||||||
*_cookie = new(std::nothrow) AHCIController(node, pciDevice);
|
|
||||||
if (!*_cookie)
|
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
status = controller->Init();
|
||||||
|
if (status < B_OK) {
|
||||||
|
delete controller;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*_cookie = controller;
|
||||||
TRACE("cookie = %p\n", *_cookie);
|
TRACE("cookie = %p\n", *_cookie);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -153,10 +161,13 @@ ahci_sim_uninit_bus(void *cookie)
|
|||||||
|
|
||||||
device_node_handle parent = gDeviceManager->get_parent(
|
device_node_handle parent = gDeviceManager->get_parent(
|
||||||
controller->DeviceNode());
|
controller->DeviceNode());
|
||||||
|
|
||||||
|
controller->Uninit();
|
||||||
|
delete controller;
|
||||||
|
|
||||||
gDeviceManager->uninit_driver(parent);
|
gDeviceManager->uninit_driver(parent);
|
||||||
gDeviceManager->put_device_node(parent);
|
gDeviceManager->put_device_node(parent);
|
||||||
|
|
||||||
delete controller;
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user