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)
|
||||
, fPCIDeviceID(0xffff)
|
||||
, fCommandSlotCount(0)
|
||||
, fPortCount(0)
|
||||
, fPortMax(0)
|
||||
, fPortCountMax(0)
|
||||
, fPortCountAvail(0)
|
||||
, fIRQ(0)
|
||||
, fInstanceCheck(-1)
|
||||
{
|
||||
@@ -90,15 +90,13 @@ AHCIController::Init()
|
||||
}
|
||||
|
||||
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) {
|
||||
TRACE("controller doesn't implement any ports\n");
|
||||
goto err;
|
||||
}
|
||||
fPortMax = 31;
|
||||
while ((fRegs->pi & (1 << fPortMax)) == 0)
|
||||
fPortMax--;
|
||||
|
||||
fIRQ = gPCI->read_pci_config(fPCIDevice, PCI_interrupt_line, 1);
|
||||
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: 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 External SATA: %s\n", (fRegs->cap & CAP_SXS) ? "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("ghc: AHCI Enable: %s\n", (fRegs->ghc & GHC_AE) ? "yes" : "no");
|
||||
TRACE("Ports Implemented: %08lx\n", fRegs->pi);
|
||||
TRACE("Highest port Number: %d\n", fPortMax);
|
||||
TRACE("Ports Implemented Mask: %#08lx\n", fRegs->pi);
|
||||
TRACE("Number of Available Ports: %d\n", fPortCountAvail);
|
||||
TRACE("AHCI Version %lu.%lu\n", fRegs->vs >> 16, fRegs->vs & 0xff);
|
||||
TRACE("Interrupt %u\n", fIRQ);
|
||||
|
||||
@@ -132,7 +130,7 @@ AHCIController::Init()
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= fPortMax; i++) {
|
||||
for (int i = 0; i <= fPortCountMax; i++) {
|
||||
if (fRegs->pi & (1 << i)) {
|
||||
fPort[i] = new (std::nothrow)AHCIPort(this, i);
|
||||
if (!fPort[i]) {
|
||||
@@ -166,7 +164,7 @@ AHCIController::Uninit()
|
||||
{
|
||||
TRACE("AHCIController::Uninit\n");
|
||||
|
||||
for (int i = 0; i <= fPortMax; i++) {
|
||||
for (int i = 0; i <= fPortCountMax; i++) {
|
||||
if (fPort[i]) {
|
||||
fPort[i]->Uninit();
|
||||
delete fPort[i];
|
||||
@@ -233,7 +231,7 @@ AHCIController::Interrupt(void *data)
|
||||
if (int_stat == 0)
|
||||
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 (self->fPort[i]) {
|
||||
self->fPort[i]->Interrupt();
|
||||
|
||||
@@ -44,8 +44,8 @@ private:
|
||||
volatile ahci_hba * fRegs;
|
||||
area_id fRegsArea;
|
||||
int fCommandSlotCount;
|
||||
int fPortCount;
|
||||
int fPortMax;
|
||||
int fPortCountMax;
|
||||
int fPortCountAvail;
|
||||
uint8 fIRQ;
|
||||
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 {
|
||||
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 fb; // FIS Base Address
|
||||
uint32 fb; // FIS Base Address (alignment 256 byte)
|
||||
uint32 fbu; // FIS Base Address Upper 32-Bits
|
||||
uint32 is; // Interrupt Status
|
||||
uint32 ie; // Interrupt Enable
|
||||
@@ -91,4 +118,22 @@ extern device_manager_info *gDeviceManager;
|
||||
extern pci_device_module_info *gPCI;
|
||||
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 */
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "ahci_port.h"
|
||||
#include "ahci_controller.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <stdio.h>
|
||||
@@ -16,6 +17,7 @@
|
||||
AHCIPort::AHCIPort(AHCIController *controller, int index)
|
||||
: fIndex(index)
|
||||
, fRegs(&controller->fRegs->port[index])
|
||||
, fArea(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,6 +31,29 @@ status_t
|
||||
AHCIPort::Init()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -37,6 +62,20 @@ void
|
||||
AHCIPort::Uninit()
|
||||
{
|
||||
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 ResetDevice();
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
int fIndex;
|
||||
volatile ahci_port * fRegs;
|
||||
area_id fArea;
|
||||
};
|
||||
|
||||
#endif // _AHCI_PORT_H
|
||||
|
||||
Reference in New Issue
Block a user