diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h
index c4b0101..a7a6424 100644
a
|
b
|
enum {
|
76 | 76 | INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt/Enable |
77 | 77 | }; |
78 | 78 | |
| 79 | /* |
| 80 | * From Spec v1.3, §3.3.11 |
| 81 | */ |
| 82 | typedef struct { |
| 83 | uint16 reserved:12; // Reserved |
| 84 | uint8 pmp:4; // Port Multiplier Port (PMP) : This field is not used by AHCI. |
| 85 | uint8 spm:4; // Select Power Management (SPM) : This field is not used by AHCI |
| 86 | uint8 ipm:4; // Interface Power Management Trnasitions Allowed (IPM) |
| 87 | uint8 spd:4; // Speed Allowed (SPD) |
| 88 | uint8 det:4; //Device Detection Initialization (DET) |
| 89 | } _PACKED scontrol; |
| 90 | |
| 91 | #define TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED 3 |
| 92 | #define NO_INITIALIZATION 0 |
| 93 | #define INITIALIZATION 1 |
| 94 | |
79 | 95 | |
80 | 96 | typedef struct { |
81 | 97 | uint32 clb; // Command List Base Address (alignment 1024 byte) |
… |
… |
typedef struct {
|
89 | 105 | uint32 tfd; // Task File Data |
90 | 106 | uint32 sig; // Signature |
91 | 107 | uint32 ssts; // Serial ATA Status (SCR0: SStatus) |
92 | | uint32 sctl; // Serial ATA Control (SCR2: SControl) |
| 108 | scontrol sctl; // Serial ATA Control (SCR2: SControl) |
93 | 109 | uint32 serr; // Serial ATA Error (SCR1: SError) **RWC** |
94 | 110 | uint32 sact; // Serial ATA Active (SCR3: SActive) **RW1** |
95 | 111 | uint32 ci; // Command Issue **RW1** |
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index a045771..7740312 100644
a
|
b
|
AHCIPort::Init1()
|
110 | 110 | // prdt follows after command table |
111 | 111 | |
112 | 112 | // disable transitions to partial or slumber state |
113 | | fRegs->sctl |= 0x300; |
| 113 | fRegs->sctl.ipm |= TRANSITIONS_TO_PARTIAL_SLUMBER_DISABLED; /*TODO Why "|= and not "=" ??*/ |
114 | 114 | |
115 | 115 | // clear IRQ status bits |
116 | 116 | fRegs->is = fRegs->is; |
… |
… |
AHCIPort::Init2()
|
156 | 156 | TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); |
157 | 157 | TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); |
158 | 158 | TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); |
159 | | TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl); |
| 159 | TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved); |
| 160 | TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp); |
| 161 | TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm); |
| 162 | TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm); |
| 163 | TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd); |
| 164 | TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det); |
160 | 165 | TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); |
161 | 166 | TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); |
162 | 167 | TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); |
… |
… |
AHCIPort::ResetDevice()
|
212 | 217 | TRACE("AHCIPort::ResetDevice PORT_CMD_ST set, behaviour undefined\n"); |
213 | 218 | |
214 | 219 | // perform a hard reset |
215 | | fRegs->sctl = (fRegs->sctl & ~0xf) | 1; |
| 220 | fRegs->sctl.det |= INITIALIZATION; //TODO Why "|=" instead of "=" ? |
216 | 221 | FlushPostedWrites(); |
217 | 222 | spin(1100); |
218 | | fRegs->sctl &= ~0xf; |
| 223 | fRegs->sctl.det = NO_INITIALIZATION; |
219 | 224 | FlushPostedWrites(); |
220 | 225 | |
221 | 226 | if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) { |
… |
… |
AHCIPort::InterruptErrorHandler(uint32 is)
|
364 | 369 | TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08" |
365 | 370 | B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex, |
366 | 371 | fCommandsActive, is, ci); |
367 | | |
368 | | TRACE("ssts 0x%08" B_PRIx32 ", sctl 0x%08" B_PRIx32 ", serr 0x%08" |
369 | | B_PRIx32 ", sact 0x%08" B_PRIx32 "\n", |
370 | | fRegs->ssts, fRegs->sctl, fRegs->serr, fRegs->sact); |
| 372 | TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); |
| 373 | TRACE("sctl.reserved 0x%04" B_PRIx16 "\n", fRegs->sctl.reserved); |
| 374 | TRACE("sctl.pmp 0x%02" B_PRIx8 "\n", fRegs->sctl.pmp); |
| 375 | TRACE("sctl.spm 0x%02" B_PRIx8 "\n", fRegs->sctl.spm); |
| 376 | TRACE("sctl.ipm 0x%02" B_PRIx8 "\n", fRegs->sctl.ipm); |
| 377 | TRACE("sctl.spd 0x%02" B_PRIx8 "\n", fRegs->sctl.spd); |
| 378 | TRACE("sctl.det 0x%02" B_PRIx8 "\n", fRegs->sctl.det); |
| 379 | TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); |
| 380 | TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); |
371 | 381 | } |
372 | 382 | |
373 | 383 | // read and clear SError |
… |
… |
AHCIPort::InterruptErrorHandler(uint32 is)
|
411 | 421 | TRACE("PhyReady Change\n"); |
412 | 422 | // fResetPort = true; |
413 | 423 | } |
| 424 | //As we are in the InterruptErrorHandler, the §6.2.2.3 of the SATA specification v1.3 applies |
414 | 425 | if (is & PORT_INT_PC) { |
415 | 426 | TRACE("Port Connect Change\n"); |
| 427 | /* 6.2.2.3 Recovery of Unsolicited COMINIT |
| 428 | An unsolicited COMINIT is a COMINIT that is not received as a consequence of issuing a COMRESET to |
| 429 | the device (refer to Serial ATA revision 2.6). If the HBA receives an unsolicited COMINIT during normal |
| 430 | operation, the HBA shall perform the following actions; |
| 431 | - Respond to the device with a COMRESET |
| 432 | - Halt execution until PxIS.PCS is cleared to '0' by software |
| 433 | |
| 434 | To detect this condition, software should check whether PxIS.PCS is set to '1' on an interrupt. The HBA |
| 435 | cannot guarantee that a device received a COMRESET because a COMINIT may appear to be solicited |
| 436 | to the HBA if it happens to occur closely to an issued COMRESET. Therefore, when software detects |
| 437 | that PxIS.PCS is set, software should first issue a COMRESET to ensure that the device receives a |
| 438 | COMRESET. Then software should perform the appropriate actions to clear PxIC.PCS to '0'. To recover, |
| 439 | software should perform error recovery actions for a fatal error condition (including restarting the |
| 440 | controller). Then software should perform a re-enumeration to check whether a new device has been inserted. |
| 441 | */ |
416 | 442 | // fResetPort = true; |
417 | 443 | } |
418 | 444 | if (is & PORT_INT_UF) { |