Changed device detection. The driver now first uses device and vendor id to check
for devices. This allows using devices that are in IDE compatibility mode. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22419 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -20,6 +20,36 @@
|
|||||||
device_manager_info *gDeviceManager;
|
device_manager_info *gDeviceManager;
|
||||||
|
|
||||||
|
|
||||||
|
device_info sSupportedDevices[] =
|
||||||
|
{
|
||||||
|
{ 0x197b, 0x2360, "JMicron JMB360" },
|
||||||
|
{ 0x197b, 0x2361, "JMicron JMB361" },
|
||||||
|
{ 0x197b, 0x2362, "JMicron JMB362" },
|
||||||
|
{ 0x197b, 0x2363, "JMicron JMB363" },
|
||||||
|
{ 0x197b, 0x2366, "JMicron JMB366" },
|
||||||
|
{ 0x8086, 0x27c0, "Intel ICH7 (IDE mode)" },
|
||||||
|
{ 0x8086, 0x27c1, "Intel ICH7 (AHCI mode)" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
get_device_info(uint16 vendorID, uint16 deviceID, const char **name, uint32 *flags)
|
||||||
|
{
|
||||||
|
device_info *info;
|
||||||
|
for (info = sSupportedDevices; info->vendor; info++) {
|
||||||
|
if (info->vendor == vendorID && info->device == deviceID) {
|
||||||
|
if (name)
|
||||||
|
*name = info->name;
|
||||||
|
if (flags)
|
||||||
|
*flags = info->flags;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
register_sim(device_node_handle parent)
|
register_sim(device_node_handle parent)
|
||||||
{
|
{
|
||||||
@@ -58,42 +88,64 @@ register_sim(device_node_handle parent)
|
|||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
static float
|
static float
|
||||||
ahci_supports_device(device_node_handle parent, bool *_noConnection)
|
ahci_supports_device(device_node_handle parent, bool *_noConnection)
|
||||||
{
|
{
|
||||||
uint8 baseClass, subClass, classAPI;
|
uint8 baseClass, subClass, classAPI;
|
||||||
uint16 vendorID;
|
uint16 vendorID;
|
||||||
uint16 deviceID;
|
uint16 deviceID;
|
||||||
|
bool isPCI;
|
||||||
|
const char *name;
|
||||||
char *bus;
|
char *bus;
|
||||||
|
|
||||||
TRACE("ahci_supports_device\n");
|
TRACE("ahci_supports_device\n");
|
||||||
|
|
||||||
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus,
|
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false) < B_OK)
|
||||||
false) != B_OK
|
|
||||||
|| gDeviceManager->get_attr_uint8(parent,
|
|
||||||
PCI_DEVICE_BASE_CLASS_ID_ITEM, &baseClass, false) != B_OK
|
|
||||||
|| gDeviceManager->get_attr_uint8(parent,
|
|
||||||
PCI_DEVICE_SUB_CLASS_ID_ITEM, &subClass, false) != B_OK
|
|
||||||
|| gDeviceManager->get_attr_uint8(parent,
|
|
||||||
PCI_DEVICE_API_ID_ITEM, &classAPI, false) != B_OK
|
|
||||||
|| gDeviceManager->get_attr_uint16(parent,
|
|
||||||
PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, false) != B_OK
|
|
||||||
|| gDeviceManager->get_attr_uint16(parent,
|
|
||||||
PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, false) != B_OK)
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
if (strcmp(bus, "pci") || baseClass != PCI_mass_storage
|
|
||||||
|| subClass != PCI_sata || classAPI != PCI_sata_ahci) {
|
|
||||||
free(bus);
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
isPCI = !strcmp(bus, "pci");
|
||||||
|
free(bus);
|
||||||
|
if (!isPCI)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
if (gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_BASE_CLASS_ID_ITEM, &baseClass, false) < B_OK
|
||||||
|
|| gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_SUB_CLASS_ID_ITEM, &subClass, false) < B_OK
|
||||||
|
|| gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_API_ID_ITEM, &classAPI, false) < B_OK
|
||||||
|
|| gDeviceManager->get_attr_uint16(parent, PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, false) < B_OK
|
||||||
|
|| gDeviceManager->get_attr_uint16(parent, PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, false) < B_OK)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
if (get_device_info(vendorID, deviceID, &name, NULL) < B_OK) {
|
||||||
|
if (baseClass != PCI_mass_storage || subClass != PCI_sata || classAPI != PCI_sata_ahci)
|
||||||
|
return 0.0f;
|
||||||
|
TRACE("generic AHCI controller found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
|
||||||
|
return 0.8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("controller found! vendor 0x%04x, device 0x%04x\n",
|
if (vendorID == PCI_VENDOR_JMICRON) {
|
||||||
vendorID, deviceID);
|
// JMicron uses the same device ID for SATA and PATA controllers,
|
||||||
|
// check if BAR5 exists to determine if it's a AHCI controller
|
||||||
|
uint8 bus, device, function;
|
||||||
|
pci_info info;
|
||||||
|
pci_module_info *pci;
|
||||||
|
size_t size = 0;
|
||||||
|
int i;
|
||||||
|
gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_BUS_ITEM, &bus, false);
|
||||||
|
gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_DEVICE_ITEM, &device, false);
|
||||||
|
gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_FUNCTION_ITEM, &function, false);
|
||||||
|
get_module(B_PCI_MODULE_NAME, (module_info **)&pci);
|
||||||
|
for (i = 0; B_OK == pci->get_nth_pci_info(i, &info); i++) {
|
||||||
|
if (info.bus == bus && info.device == device && info.function == function) {
|
||||||
|
size = info.u.h0.base_register_sizes[5];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
put_module(B_PCI_MODULE_NAME);
|
||||||
|
if (size == 0)
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
free(bus);
|
TRACE("AHCI controller %s found!\n", name);
|
||||||
return 0.5;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -156,6 +208,8 @@ ahci_init_driver(device_node_handle node, void *userCookie, void **_cookie)
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
TRACE("ahci_init_driver: gPCI %p, pciDevice %p\n", gPCI, pciDevice);
|
||||||
|
|
||||||
gDeviceManager->put_device_node(parent);
|
gDeviceManager->put_device_node(parent);
|
||||||
|
|
||||||
*_userCookie = pciDevice;
|
*_userCookie = pciDevice;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device)
|
|||||||
, fPCIDevice(device)
|
, fPCIDevice(device)
|
||||||
, fPCIVendorID(0xffff)
|
, fPCIVendorID(0xffff)
|
||||||
, fPCIDeviceID(0xffff)
|
, fPCIDeviceID(0xffff)
|
||||||
|
, fFlags(0)
|
||||||
, fCommandSlotCount(0)
|
, fCommandSlotCount(0)
|
||||||
, fPortCountMax(0)
|
, fPortCountMax(0)
|
||||||
, fPortCountAvail(0)
|
, fPortCountAvail(0)
|
||||||
@@ -69,6 +70,8 @@ AHCIController::Init()
|
|||||||
fInstanceCheck = create_port(1, sName);
|
fInstanceCheck = create_port(1, sName);
|
||||||
// --- Instance check workaround end
|
// --- Instance check workaround end
|
||||||
|
|
||||||
|
get_device_info(fPCIVendorID, fPCIDeviceID, NULL, &fFlags);
|
||||||
|
|
||||||
uchar capabilityOffset;
|
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) {
|
if (res == B_OK) {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ private:
|
|||||||
pci_device_info* fPCIDevice;
|
pci_device_info* fPCIDevice;
|
||||||
uint16 fPCIVendorID;
|
uint16 fPCIVendorID;
|
||||||
uint16 fPCIDeviceID;
|
uint16 fPCIDeviceID;
|
||||||
|
uint32 fFlags;
|
||||||
|
|
||||||
volatile ahci_hba * fRegs;
|
volatile ahci_hba * fRegs;
|
||||||
area_id fRegsArea;
|
area_id fRegsArea;
|
||||||
@@ -49,7 +50,6 @@ private:
|
|||||||
uint8 fIRQ;
|
uint8 fIRQ;
|
||||||
AHCIPort * fPort[32];
|
AHCIPort * fPort[32];
|
||||||
|
|
||||||
|
|
||||||
// --- Instance check workaround begin
|
// --- Instance check workaround begin
|
||||||
port_id fInstanceCheck;
|
port_id fInstanceCheck;
|
||||||
// --- Instance check workaround end
|
// --- Instance check workaround end
|
||||||
@@ -64,5 +64,4 @@ AHCIController::FlushPostedWrites()
|
|||||||
dummy = dummy;
|
dummy = dummy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif // _AHCI_CONTROLLER_H
|
#endif // _AHCI_CONTROLLER_H
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
#include <bus/PCI.h>
|
#include <bus/PCI.h>
|
||||||
#include <bus/SCSI.h>
|
#include <bus/SCSI.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/device_v1"
|
#define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/device_v1"
|
||||||
#define AHCI_SIM_MODULE_NAME "busses/scsi/ahci/sim/v1"
|
#define AHCI_SIM_MODULE_NAME "busses/scsi/ahci/sim/v1"
|
||||||
|
|
||||||
@@ -211,6 +215,16 @@ typedef struct {
|
|||||||
#define PRD_MAX_DATA_LENGTH 0x400000 /* 4 MB */
|
#define PRD_MAX_DATA_LENGTH 0x400000 /* 4 MB */
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16 vendor;
|
||||||
|
uint16 device;
|
||||||
|
const char *name;
|
||||||
|
uint32 flags;
|
||||||
|
} device_info;
|
||||||
|
|
||||||
|
status_t get_device_info(uint16 vendorID, uint16 deviceID, const char **name, uint32 *flags);
|
||||||
|
|
||||||
|
|
||||||
extern scsi_sim_interface gAHCISimInterface;
|
extern scsi_sim_interface gAHCISimInterface;
|
||||||
extern device_manager_info *gDeviceManager;
|
extern device_manager_info *gDeviceManager;
|
||||||
extern pci_device_module_info *gPCI;
|
extern pci_device_module_info *gPCI;
|
||||||
@@ -224,6 +238,10 @@ extern scsi_for_sim_interface *gSCSI;
|
|||||||
#define PCI_VENDOR_JMICRON 0x197b
|
#define PCI_VENDOR_JMICRON 0x197b
|
||||||
#define PCI_JMICRON_CONTROLLER_CONTROL_1 0x40
|
#define PCI_JMICRON_CONTROLLER_CONTROL_1 0x40
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -264,5 +282,4 @@ wait_until_clear(volatile uint32 *reg, uint32 bits, bigtime_t timeout)
|
|||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
#endif /* _AHCI_DEFS_H */
|
#endif /* _AHCI_DEFS_H */
|
||||||
|
|||||||
@@ -130,15 +130,19 @@ ahci_sim_init_bus(device_node_handle node, void *userCookie, void **_cookie)
|
|||||||
AHCIController *controller;
|
AHCIController *controller;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
TRACE("ahci_sim_init_bus, userCookie %p\n", userCookie);
|
TRACE("ahci_sim_init_bus: userCookie %p\n", userCookie);
|
||||||
|
|
||||||
// initialize parent (the bus) to get the PCI interface and device
|
TRACE("ahci_sim_init_bus: gPCI %p\n", gPCI);
|
||||||
|
|
||||||
|
// initialize parent (the bus) to get the PCI device
|
||||||
parent = gDeviceManager->get_parent(node);
|
parent = gDeviceManager->get_parent(node);
|
||||||
status = gDeviceManager->init_driver(parent, &pciDevice, NULL, NULL);
|
status = gDeviceManager->init_driver(parent, &pciDevice, NULL, NULL);
|
||||||
gDeviceManager->put_device_node(parent);
|
gDeviceManager->put_device_node(parent);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
TRACE("ahci_sim_init_bus: pciDevice %p\n", pciDevice);
|
||||||
|
|
||||||
controller = new(std::nothrow) AHCIController(node, pciDevice);
|
controller = new(std::nothrow) AHCIController(node, pciDevice);
|
||||||
if (!controller)
|
if (!controller)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|||||||
Reference in New Issue
Block a user