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:
parent
b2d056ecde
commit
83447512ed
@ -20,6 +20,36 @@
|
||||
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
|
||||
register_sim(device_node_handle parent)
|
||||
{
|
||||
@ -58,42 +88,64 @@ register_sim(device_node_handle parent)
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
static float
|
||||
ahci_supports_device(device_node_handle parent, bool *_noConnection)
|
||||
{
|
||||
uint8 baseClass, subClass, classAPI;
|
||||
uint16 vendorID;
|
||||
uint16 deviceID;
|
||||
bool isPCI;
|
||||
const char *name;
|
||||
char *bus;
|
||||
|
||||
TRACE("ahci_supports_device\n");
|
||||
|
||||
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus,
|
||||
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);
|
||||
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false) < B_OK)
|
||||
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",
|
||||
vendorID, deviceID);
|
||||
if (vendorID == PCI_VENDOR_JMICRON) {
|
||||
// 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);
|
||||
return 0.5;
|
||||
TRACE("AHCI controller %s found!\n", name);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
|
||||
@ -156,6 +208,8 @@ ahci_init_driver(device_node_handle node, void *userCookie, void **_cookie)
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
TRACE("ahci_init_driver: gPCI %p, pciDevice %p\n", gPCI, pciDevice);
|
||||
|
||||
gDeviceManager->put_device_node(parent);
|
||||
|
||||
*_userCookie = pciDevice;
|
||||
|
@ -20,6 +20,7 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device)
|
||||
, fPCIDevice(device)
|
||||
, fPCIVendorID(0xffff)
|
||||
, fPCIDeviceID(0xffff)
|
||||
, fFlags(0)
|
||||
, fCommandSlotCount(0)
|
||||
, fPortCountMax(0)
|
||||
, fPortCountAvail(0)
|
||||
@ -69,6 +70,8 @@ AHCIController::Init()
|
||||
fInstanceCheck = create_port(1, sName);
|
||||
// --- Instance check workaround end
|
||||
|
||||
get_device_info(fPCIVendorID, fPCIDeviceID, NULL, &fFlags);
|
||||
|
||||
uchar capabilityOffset;
|
||||
status_t res = gPCI->find_pci_capability(fPCIDevice, PCI_cap_id_sata, &capabilityOffset);
|
||||
if (res == B_OK) {
|
||||
|
@ -40,6 +40,7 @@ private:
|
||||
pci_device_info* fPCIDevice;
|
||||
uint16 fPCIVendorID;
|
||||
uint16 fPCIDeviceID;
|
||||
uint32 fFlags;
|
||||
|
||||
volatile ahci_hba * fRegs;
|
||||
area_id fRegsArea;
|
||||
@ -49,7 +50,6 @@ private:
|
||||
uint8 fIRQ;
|
||||
AHCIPort * fPort[32];
|
||||
|
||||
|
||||
// --- Instance check workaround begin
|
||||
port_id fInstanceCheck;
|
||||
// --- Instance check workaround end
|
||||
@ -64,5 +64,4 @@ AHCIController::FlushPostedWrites()
|
||||
dummy = dummy;
|
||||
}
|
||||
|
||||
|
||||
#endif // _AHCI_CONTROLLER_H
|
||||
|
@ -8,6 +8,10 @@
|
||||
#include <bus/PCI.h>
|
||||
#include <bus/SCSI.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/device_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 */
|
||||
|
||||
|
||||
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 device_manager_info *gDeviceManager;
|
||||
extern pci_device_module_info *gPCI;
|
||||
@ -224,6 +238,10 @@ extern scsi_for_sim_interface *gSCSI;
|
||||
#define PCI_VENDOR_JMICRON 0x197b
|
||||
#define PCI_JMICRON_CONTROLLER_CONTROL_1 0x40
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
template <class T>
|
||||
@ -264,5 +282,4 @@ wait_until_clear(volatile uint32 *reg, uint32 bits, bigtime_t timeout)
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* _AHCI_DEFS_H */
|
||||
|
@ -130,15 +130,19 @@ ahci_sim_init_bus(device_node_handle node, void *userCookie, void **_cookie)
|
||||
AHCIController *controller;
|
||||
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);
|
||||
status = gDeviceManager->init_driver(parent, &pciDevice, NULL, NULL);
|
||||
gDeviceManager->put_device_node(parent);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
TRACE("ahci_sim_init_bus: pciDevice %p\n", pciDevice);
|
||||
|
||||
controller = new(std::nothrow) AHCIController(node, pciDevice);
|
||||
if (!controller)
|
||||
return B_NO_MEMORY;
|
||||
|
Loading…
Reference in New Issue
Block a user