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:
Marcus Overhagen 2007-10-03 16:05:23 +00:00
parent b2d056ecde
commit 83447512ed
5 changed files with 104 additions and 27 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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 */

View File

@ -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;