correct port number handling
allocate memory for command list and fis git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22221 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -21,8 +21,8 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device)
|
|||||||
, fPCIVendorID(0xffff)
|
, fPCIVendorID(0xffff)
|
||||||
, fPCIDeviceID(0xffff)
|
, fPCIDeviceID(0xffff)
|
||||||
, fCommandSlotCount(0)
|
, fCommandSlotCount(0)
|
||||||
, fPortCount(0)
|
, fPortCountMax(0)
|
||||||
, fPortMax(0)
|
, fPortCountAvail(0)
|
||||||
, fIRQ(0)
|
, fIRQ(0)
|
||||||
, fInstanceCheck(-1)
|
, fInstanceCheck(-1)
|
||||||
{
|
{
|
||||||
@@ -90,15 +90,13 @@ AHCIController::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
fCommandSlotCount = 1 + ((fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
|
fCommandSlotCount = 1 + ((fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
|
||||||
fPortCount = 1 + ((fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
|
fPortCountMax = 1 + ((fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
|
||||||
|
fPortCountAvail = count_bits_set(fRegs->pi);
|
||||||
|
|
||||||
if (fRegs->pi == 0) {
|
if (fRegs->pi == 0) {
|
||||||
TRACE("controller doesn't implement any ports\n");
|
TRACE("controller doesn't implement any ports\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
fPortMax = 31;
|
|
||||||
while ((fRegs->pi & (1 << fPortMax)) == 0)
|
|
||||||
fPortMax--;
|
|
||||||
|
|
||||||
fIRQ = gPCI->read_pci_config(fPCIDevice, PCI_interrupt_line, 1);
|
fIRQ = gPCI->read_pci_config(fPCIDevice, PCI_interrupt_line, 1);
|
||||||
if (fIRQ == 0 || fIRQ == 0xff) {
|
if (fIRQ == 0 || fIRQ == 0xff) {
|
||||||
@@ -108,7 +106,7 @@ AHCIController::Init()
|
|||||||
|
|
||||||
TRACE("cap: Interface Speed Support: generation %lu\n", (fRegs->cap >> CAP_ISS_SHIFT) & CAP_ISS_MASK);
|
TRACE("cap: Interface Speed Support: generation %lu\n", (fRegs->cap >> CAP_ISS_SHIFT) & CAP_ISS_MASK);
|
||||||
TRACE("cap: Number of Command Slots: %d (raw %#lx)\n", fCommandSlotCount, (fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
|
TRACE("cap: Number of Command Slots: %d (raw %#lx)\n", fCommandSlotCount, (fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
|
||||||
TRACE("cap: Number of Ports: %d (raw %#lx)\n", fPortCount, (fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
|
TRACE("cap: Number of Ports: %d (raw %#lx)\n", fPortCountMax, (fRegs->cap >> CAP_NP_SHIFT) & CAP_NP_MASK);
|
||||||
TRACE("cap: Supports Port Multiplier: %s\n", (fRegs->cap & CAP_SPM) ? "yes" : "no");
|
TRACE("cap: Supports Port Multiplier: %s\n", (fRegs->cap & CAP_SPM) ? "yes" : "no");
|
||||||
TRACE("cap: Supports External SATA: %s\n", (fRegs->cap & CAP_SXS) ? "yes" : "no");
|
TRACE("cap: Supports External SATA: %s\n", (fRegs->cap & CAP_SXS) ? "yes" : "no");
|
||||||
TRACE("cap: Enclosure Management Supported: %s\n", (fRegs->cap & CAP_EMS) ? "yes" : "no");
|
TRACE("cap: Enclosure Management Supported: %s\n", (fRegs->cap & CAP_EMS) ? "yes" : "no");
|
||||||
@@ -121,8 +119,8 @@ AHCIController::Init()
|
|||||||
|
|
||||||
TRACE("cap: Supports AHCI mode only: %s\n", (fRegs->cap & CAP_SAM) ? "yes" : "no");
|
TRACE("cap: Supports AHCI mode only: %s\n", (fRegs->cap & CAP_SAM) ? "yes" : "no");
|
||||||
TRACE("ghc: AHCI Enable: %s\n", (fRegs->ghc & GHC_AE) ? "yes" : "no");
|
TRACE("ghc: AHCI Enable: %s\n", (fRegs->ghc & GHC_AE) ? "yes" : "no");
|
||||||
TRACE("Ports Implemented: %08lx\n", fRegs->pi);
|
TRACE("Ports Implemented Mask: %#08lx\n", fRegs->pi);
|
||||||
TRACE("Highest port Number: %d\n", fPortMax);
|
TRACE("Number of Available Ports: %d\n", fPortCountAvail);
|
||||||
TRACE("AHCI Version %lu.%lu\n", fRegs->vs >> 16, fRegs->vs & 0xff);
|
TRACE("AHCI Version %lu.%lu\n", fRegs->vs >> 16, fRegs->vs & 0xff);
|
||||||
TRACE("Interrupt %u\n", fIRQ);
|
TRACE("Interrupt %u\n", fIRQ);
|
||||||
|
|
||||||
@@ -132,7 +130,7 @@ AHCIController::Init()
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i <= fPortMax; i++) {
|
for (int i = 0; i <= fPortCountMax; i++) {
|
||||||
if (fRegs->pi & (1 << i)) {
|
if (fRegs->pi & (1 << i)) {
|
||||||
fPort[i] = new (std::nothrow)AHCIPort(this, i);
|
fPort[i] = new (std::nothrow)AHCIPort(this, i);
|
||||||
if (!fPort[i]) {
|
if (!fPort[i]) {
|
||||||
@@ -166,7 +164,7 @@ AHCIController::Uninit()
|
|||||||
{
|
{
|
||||||
TRACE("AHCIController::Uninit\n");
|
TRACE("AHCIController::Uninit\n");
|
||||||
|
|
||||||
for (int i = 0; i <= fPortMax; i++) {
|
for (int i = 0; i <= fPortCountMax; i++) {
|
||||||
if (fPort[i]) {
|
if (fPort[i]) {
|
||||||
fPort[i]->Uninit();
|
fPort[i]->Uninit();
|
||||||
delete fPort[i];
|
delete fPort[i];
|
||||||
@@ -233,7 +231,7 @@ AHCIController::Interrupt(void *data)
|
|||||||
if (int_stat == 0)
|
if (int_stat == 0)
|
||||||
return B_UNHANDLED_INTERRUPT;
|
return B_UNHANDLED_INTERRUPT;
|
||||||
|
|
||||||
for (int i = 0; i < self->fPortMax; i++) {
|
for (int i = 0; i < self->fPortCountMax; i++) {
|
||||||
if (int_stat & (1 << i)) {
|
if (int_stat & (1 << i)) {
|
||||||
if (self->fPort[i]) {
|
if (self->fPort[i]) {
|
||||||
self->fPort[i]->Interrupt();
|
self->fPort[i]->Interrupt();
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ private:
|
|||||||
volatile ahci_hba * fRegs;
|
volatile ahci_hba * fRegs;
|
||||||
area_id fRegsArea;
|
area_id fRegsArea;
|
||||||
int fCommandSlotCount;
|
int fCommandSlotCount;
|
||||||
int fPortCount;
|
int fPortCountMax;
|
||||||
int fPortMax;
|
int fPortCountAvail;
|
||||||
uint8 fIRQ;
|
uint8 fIRQ;
|
||||||
AHCIPort * fPort[32];
|
AHCIPort * fPort[32];
|
||||||
|
|
||||||
|
|||||||
@@ -47,10 +47,37 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
INT_CPD = (1 << 31), // Cold Port Detect Status/Enable
|
||||||
|
INT_TFE = (1 << 30), // Task File Error Status/Enable
|
||||||
|
INT_HBF = (1 << 29), // Host Bus Fatal Error Status/Enable
|
||||||
|
INT_HBD = (1 << 28), // Host Bus Data Error Status/Enable
|
||||||
|
INT_IF = (1 << 27), // Interface Fatal Error Status/Enable
|
||||||
|
INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable
|
||||||
|
INT_OF = (1 << 24), // Overflow Status/Enable
|
||||||
|
INT_IPM = (1 << 23), // Incorrect Port Multiplier Status/Enable
|
||||||
|
INT_PRC = (1 << 22), // PhyRdy Change Status/Enable
|
||||||
|
INT_DMP = (1 << 7), // Device Mechanical Presence Status/Enable
|
||||||
|
INT_PC = (1 << 6), // Port Change Interrupt Status/Enable
|
||||||
|
INT_DP = (1 << 5), // Descriptor Processed Interrupt/Enable
|
||||||
|
INT_UF = (1 << 4), // Unknown FIS Interrupt/Enable
|
||||||
|
INT_SDB = (1 << 3), // Set Device Bits Interrupt/Enable
|
||||||
|
INT_DS = (1 << 2), // DMA Setup FIS Interrupt/Enable
|
||||||
|
INT_PS = (1 << 1), // PIO Setup FIS Interrupt/Enable
|
||||||
|
INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt/Enable
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AHCI_CLB_SIZE = 1024,
|
||||||
|
AHCI_FIS_SIZE = 256,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32 clb; // Command List Base Address
|
uint32 clb; // Command List Base Address (alignment 1024 byte)
|
||||||
uint32 clbu; // Command List Base Address Upper 32-Bits
|
uint32 clbu; // Command List Base Address Upper 32-Bits
|
||||||
uint32 fb; // FIS Base Address
|
uint32 fb; // FIS Base Address (alignment 256 byte)
|
||||||
uint32 fbu; // FIS Base Address Upper 32-Bits
|
uint32 fbu; // FIS Base Address Upper 32-Bits
|
||||||
uint32 is; // Interrupt Status
|
uint32 is; // Interrupt Status
|
||||||
uint32 ie; // Interrupt Enable
|
uint32 ie; // Interrupt Enable
|
||||||
@@ -91,4 +118,22 @@ extern device_manager_info *gDeviceManager;
|
|||||||
extern pci_device_module_info *gPCI;
|
extern pci_device_module_info *gPCI;
|
||||||
extern scsi_for_sim_interface *gSCSI;
|
extern scsi_for_sim_interface *gSCSI;
|
||||||
|
|
||||||
|
#define LO32(val) ((uint32)(val))
|
||||||
|
#define HI32(val) (((uint64)(val)) >> 32)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
int count_bits_set(T value)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (T mask = 1; mask; mask <<= 1)
|
||||||
|
if (value & mask)
|
||||||
|
count++;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
#endif /* _AHCI_DEFS_H */
|
#endif /* _AHCI_DEFS_H */
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "ahci_port.h"
|
#include "ahci_port.h"
|
||||||
#include "ahci_controller.h"
|
#include "ahci_controller.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
AHCIPort::AHCIPort(AHCIController *controller, int index)
|
AHCIPort::AHCIPort(AHCIController *controller, int index)
|
||||||
: fIndex(index)
|
: fIndex(index)
|
||||||
, fRegs(&controller->fRegs->port[index])
|
, fRegs(&controller->fRegs->port[index])
|
||||||
|
, fArea(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +31,29 @@ status_t
|
|||||||
AHCIPort::Init()
|
AHCIPort::Init()
|
||||||
{
|
{
|
||||||
TRACE("AHCIPort::Init port %d\n", fIndex);
|
TRACE("AHCIPort::Init port %d\n", fIndex);
|
||||||
|
|
||||||
|
size_t size = 999;
|
||||||
|
|
||||||
|
void *virtAddr;
|
||||||
|
void *physAddr;
|
||||||
|
|
||||||
|
fArea = alloc_mem(&virtAddr, &physAddr, size, 0, "some AHCI port");
|
||||||
|
if (fArea < B_OK) {
|
||||||
|
TRACE("failed allocating memory for port %d\n", fIndex);
|
||||||
|
return fArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *virtClbAddr;
|
||||||
|
void *physClbAddr = physAddr;
|
||||||
|
void *virtFisAddr;
|
||||||
|
void *physFisAddr = (char *)physAddr + 1024;
|
||||||
|
|
||||||
|
|
||||||
|
fRegs->clb = LO32(physClbAddr);
|
||||||
|
fRegs->clbu = HI32(physClbAddr);
|
||||||
|
fRegs->fb = LO32(physFisAddr);
|
||||||
|
fRegs->fbu = HI32(physFisAddr);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +62,20 @@ void
|
|||||||
AHCIPort::Uninit()
|
AHCIPort::Uninit()
|
||||||
{
|
{
|
||||||
TRACE("AHCIPort::Uninit port %d\n", fIndex);
|
TRACE("AHCIPort::Uninit port %d\n", fIndex);
|
||||||
|
|
||||||
|
// disable interrupts
|
||||||
|
fRegs->ie = 0;
|
||||||
|
|
||||||
|
// clear pending interrupts
|
||||||
|
fRegs->is = fRegs->is;
|
||||||
|
|
||||||
|
// invalidate DMA addresses
|
||||||
|
fRegs->clb = 0;
|
||||||
|
fRegs->clbu = 0;
|
||||||
|
fRegs->fb = 0;
|
||||||
|
fRegs->fbu = 0;
|
||||||
|
|
||||||
|
delete_area(fArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,12 @@ public:
|
|||||||
uchar TerminateRequest(scsi_ccb *request);
|
uchar TerminateRequest(scsi_ccb *request);
|
||||||
uchar ResetDevice();
|
uchar ResetDevice();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int fIndex;
|
int fIndex;
|
||||||
volatile ahci_port * fRegs;
|
volatile ahci_port * fRegs;
|
||||||
|
area_id fArea;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _AHCI_PORT_H
|
#endif // _AHCI_PORT_H
|
||||||
|
|||||||
Reference in New Issue
Block a user