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 b9c8c03..1e942cb 100644
a
|
b
|
|
5 | 5 | #ifndef _AHCI_DEFS_H |
6 | 6 | #define _AHCI_DEFS_H |
7 | 7 | |
| 8 | #include <ata_types.h> |
8 | 9 | #include <bus/PCI.h> |
9 | 10 | #include <bus/SCSI.h> |
10 | 11 | #include <PCI_x86.h> |
… |
… |
enum {
|
97 | 98 | #define IPM_TRANSITIONS_TO_PARTIAL_DISABLED 0x1 |
98 | 99 | #define IPM_TRANSITIONS_TO_SLUMBER_DISABLED 0x2 |
99 | 100 | |
| 101 | // Device signatures |
| 102 | #define SATA_SIG_ATA 0x00000101 // SATA drive |
| 103 | #define SATA_SIG_ATAPI 0xEB140101 // ATAPI drive |
| 104 | #define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge |
| 105 | #define SATA_SIG_PM 0x96690101 // Port multiplier |
100 | 106 | |
101 | 107 | typedef struct { |
102 | 108 | uint32 clb; // Command List Base Address |
… |
… |
enum {
|
130 | 136 | PORT_CMD_ATAPI = (1 << 24), // Device is ATAPI |
131 | 137 | PORT_CMD_CR = (1 << 15), // Command List Running (DMA active) |
132 | 138 | PORT_CMD_FR = (1 << 14), // FIS Receive Running |
133 | | PORT_CMD_FER = (1 << 4), // FIS Receive Enable |
| 139 | PORT_CMD_FRE = (1 << 4), // FIS Receive Enable |
134 | 140 | PORT_CMD_CLO = (1 << 3), // Command List Override |
135 | 141 | PORT_CMD_POD = (1 << 2), // Power On Device |
136 | 142 | PORT_CMD_SUD = (1 << 1), // Spin-up Device |
… |
… |
enum {
|
167 | 173 | | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) |
168 | 174 | |
169 | 175 | enum { |
170 | | ATA_BSY = 0x80, |
171 | | ATA_DF = 0x20, |
172 | | ATA_DRQ = 0x08, |
173 | | ATA_ERR = 0x01, |
174 | | }; |
175 | | |
176 | | |
177 | | enum { |
178 | 176 | PORT_FBS_DWE_SHIFT = 16, // Device With Error |
179 | 177 | PORT_FBS_DWE_MASK = 0xf, |
180 | 178 | PORT_FBS_ADO_SHIFT = 12, // Active Device Optimization |
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 94a0034..45c7762 100644
a
|
b
|
AHCIPort::AHCIPort(AHCIController* controller, int index)
|
54 | 54 | fSectorCount(0), |
55 | 55 | fIsATAPI(false), |
56 | 56 | fTestUnitReadyActive(false), |
57 | | fResetPort(false), |
| 57 | fSoftReset(false), |
58 | 58 | fError(false), |
59 | 59 | fTrimSupported(false) |
60 | 60 | { |
… |
… |
AHCIPort::Init1()
|
120 | 120 | fRegs->is = fRegs->is; |
121 | 121 | |
122 | 122 | // clear error bits |
123 | | fRegs->serr = fRegs->serr; |
| 123 | _ClearErrorRegister(); |
124 | 124 | |
125 | 125 | // power up device |
126 | 126 | fRegs->cmd |= PORT_CMD_POD; |
… |
… |
AHCIPort::Init1()
|
131 | 131 | // activate link |
132 | 132 | fRegs->cmd = (fRegs->cmd & ~PORT_CMD_ICC_MASK) | PORT_CMD_ICC_ACTIVE; |
133 | 133 | |
134 | | // enable FIS receive |
135 | | fRegs->cmd |= PORT_CMD_FER; |
| 134 | // enable FIS receive (enabled when fb set, only to be disabled when unset) |
| 135 | fRegs->cmd |= PORT_CMD_FRE; |
136 | 136 | |
137 | 137 | FlushPostedWrites(); |
138 | 138 | |
… |
… |
AHCIPort::Init2()
|
146 | 146 | { |
147 | 147 | TRACE("AHCIPort::Init2 port %d\n", fIndex); |
148 | 148 | |
149 | | // start DMA engine |
150 | | fRegs->cmd |= PORT_CMD_ST; |
| 149 | // enable port |
| 150 | Enable(); |
151 | 151 | |
152 | 152 | // enable interrupts |
153 | 153 | fRegs->ie = PORT_INT_MASK; |
154 | 154 | |
155 | 155 | FlushPostedWrites(); |
156 | 156 | |
157 | | ResetPort(true); |
| 157 | // reset port and probe info |
| 158 | SoftReset(); |
158 | 159 | |
159 | 160 | TRACE("ie 0x%08" B_PRIx32 "\n", fRegs->ie); |
160 | 161 | TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); |
… |
… |
AHCIPort::Init2()
|
172 | 173 | |
173 | 174 | fDevicePresent = (fRegs->ssts & 0xf) == 0x3; |
174 | 175 | |
| 176 | TRACE("%s: port %d, device %s\n", __func__, fIndex, |
| 177 | fDevicePresent ? "present" : "absent"); |
| 178 | |
175 | 179 | return B_OK; |
176 | 180 | } |
177 | 181 | |
… |
… |
AHCIPort::Uninit()
|
181 | 185 | { |
182 | 186 | TRACE("AHCIPort::Uninit port %d\n", fIndex); |
183 | 187 | |
184 | | // disable FIS receive |
185 | | fRegs->cmd &= ~PORT_CMD_FER; |
| 188 | // Spec v1.3.1, §10.3.2 - Shut down port before unsetting FRE |
186 | 189 | |
187 | | // wait for receive completion, up to 500ms |
188 | | if (wait_until_clear(&fRegs->cmd, PORT_CMD_FR, 500000) < B_OK) { |
189 | | TRACE("AHCIPort::Uninit port %d error FIS rx still running\n", fIndex); |
| 190 | // shutdown the port |
| 191 | if (!Disable()) { |
| 192 | ERROR("%s: port %d error, unable to shutdown before FRE clear!\n", |
| 193 | __func__, fIndex); |
| 194 | return; |
190 | 195 | } |
191 | 196 | |
192 | | // stop DMA engine |
193 | | fRegs->cmd &= ~PORT_CMD_ST; |
194 | | |
195 | | // wait for DMA completion |
196 | | if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { |
197 | | TRACE("AHCIPort::Uninit port %d error DMA engine still running\n", |
198 | | fIndex); |
199 | | } |
| 197 | // Clear FRE and wait for completion |
| 198 | fRegs->cmd &= ~PORT_CMD_FRE; |
| 199 | if (wait_until_clear(&fRegs->cmd, PORT_CMD_FR, 500000) < B_OK) |
| 200 | ERROR("%s: port %d error FIS rx still running\n", __func__, fIndex); |
200 | 201 | |
201 | 202 | // disable interrupts |
202 | 203 | fRegs->ie = 0; |
… |
… |
void
|
218 | 219 | AHCIPort::ResetDevice() |
219 | 220 | { |
220 | 221 | // perform a hard reset |
221 | | if (!_HardReset()) |
| 222 | if (PortReset() != B_OK) { |
| 223 | ERROR("%s: port %d unable to hard reset device\n", __func__, fIndex); |
222 | 224 | return; |
| 225 | } |
223 | 226 | |
224 | 227 | if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) |
225 | 228 | TRACE("AHCIPort::ResetDevice port %d no device detected\n", fIndex); |
… |
… |
AHCIPort::ResetDevice()
|
238 | 241 | |
239 | 242 | |
240 | 243 | status_t |
241 | | AHCIPort::ResetPort(bool forceDeviceReset) |
| 244 | AHCIPort::SoftReset() |
242 | 245 | { |
243 | | if (!fTestUnitReadyActive) |
244 | | TRACE("AHCIPort::ResetPort port %d\n", fIndex); |
| 246 | TRACE("AHCIPort::SoftReset port %d\n", fIndex); |
245 | 247 | |
246 | | // stop DMA engine |
247 | | fRegs->cmd &= ~PORT_CMD_ST; |
248 | | FlushPostedWrites(); |
| 248 | // Spec v1.3.1, §10.4.1 Software Reset |
| 249 | // A single device on one port is reset, HBA and phy comm remain intact. |
249 | 250 | |
250 | | if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { |
251 | | TRACE("AHCIPort::ResetPort port %d error DMA engine doesn't stop\n", |
252 | | fIndex); |
| 251 | // stop port, flush transactions |
| 252 | if (!Disable()) { |
| 253 | // If the port doesn't power off, move on to a stronger reset. |
| 254 | ERROR("%s: port %d soft reset failed. Moving on to port reset.\n", |
| 255 | __func__, fIndex); |
| 256 | return PortReset(); |
253 | 257 | } |
254 | 258 | |
255 | | bool deviceBusy = fRegs->tfd & (ATA_BSY | ATA_DRQ); |
| 259 | // TODO: If FBS Enable, clear PxFBS.EN prior to issuing sw reset |
256 | 260 | |
257 | | if (!fTestUnitReadyActive) { |
258 | | TRACE("AHCIPort::ResetPort port %d, deviceBusy %d, " |
259 | | "forceDeviceReset %d\n", fIndex, deviceBusy, forceDeviceReset); |
| 261 | // If the port is still busy, move on to port reset. |
| 262 | if (fRegs->tfd & (ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST)) { |
| 263 | ERROR("%s: port %d still busy. Moving on to port reset.\n", |
| 264 | __func__, fIndex); |
| 265 | return PortReset(); |
260 | 266 | } |
261 | 267 | |
262 | | if (deviceBusy || forceDeviceReset) |
263 | | ResetDevice(); |
264 | | |
265 | | // start DMA engine |
266 | | fRegs->cmd |= PORT_CMD_ST; |
| 268 | // ATA Reset |
| 269 | fCommandList->r = 1; |
| 270 | // ATA Clear Busy |
| 271 | fCommandList->c = 1; |
| 272 | // Issue Command |
| 273 | fRegs->ci = 1; |
267 | 274 | FlushPostedWrites(); |
268 | 275 | |
| 276 | if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST, |
| 277 | 1000000) < B_OK) { |
| 278 | ERROR("%s: port %d software reset failed. Doing port reset...\n", |
| 279 | __func__, fIndex); |
| 280 | return PortReset(); |
| 281 | } |
| 282 | |
| 283 | // start port |
| 284 | Enable(); |
| 285 | |
269 | 286 | return PostReset(); |
270 | 287 | } |
271 | 288 | |
272 | 289 | |
273 | 290 | status_t |
274 | | AHCIPort::PostReset() |
| 291 | AHCIPort::PortReset() |
275 | 292 | { |
276 | | if (!fTestUnitReadyActive) |
277 | | TRACE("AHCIPort::PostReset port %d\n", fIndex); |
| 293 | TRACE("AHCIPort::PortReset port %d\n", fIndex); |
| 294 | |
| 295 | // Spec v1.3.1, §10.4.2 Port Reset |
| 296 | // Physical comm between HBA and port disabled. More Intrusive |
| 297 | if (!Disable()) { |
| 298 | ERROR("%s: port %d unable to reset!\n", __func__, fIndex); |
| 299 | return B_ERROR; |
| 300 | } |
| 301 | |
| 302 | fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) |
| 303 | | DET_INITIALIZATION << SATA_CONTROL_DET_SHIFT; |
| 304 | FlushPostedWrites(); |
| 305 | spin(1100); |
| 306 | // You must wait 1ms at minimum |
| 307 | fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) |
| 308 | | DET_NO_INITIALIZATION << SATA_CONTROL_DET_SHIFT; |
| 309 | FlushPostedWrites(); |
278 | 310 | |
279 | | if ((fRegs->ssts & 0xf) != 0x3 || (fRegs->tfd & 0xff) == 0x7f) { |
280 | | TRACE("AHCIPort::PostReset port %d: no device\n", fIndex); |
281 | | return B_OK; |
| 311 | if (wait_until_set(&fRegs->ssts, 0x3, 500000) < B_OK) { |
| 312 | TRACE("AHCIPort::PortReset port %d device present but no phy " |
| 313 | "communication\n", fIndex); |
| 314 | return B_ERROR; |
282 | 315 | } |
283 | 316 | |
| 317 | //if ((fRegs->tfd & 0xff) == 0x7f) { |
| 318 | // TRACE("AHCIPort::PostReset port %d: no device\n", fIndex); |
| 319 | // return B_OK; |
| 320 | //} |
| 321 | |
| 322 | Enable(); |
| 323 | |
| 324 | return PostReset(); |
| 325 | } |
| 326 | |
| 327 | |
| 328 | status_t |
| 329 | AHCIPort::PostReset() |
| 330 | { |
284 | 331 | if ((fRegs->tfd & 0xff) == 0xff) |
285 | 332 | snooze(200000); |
286 | 333 | |
… |
… |
AHCIPort::PostReset()
|
290 | 337 | return B_ERROR; |
291 | 338 | } |
292 | 339 | |
293 | | wait_until_clear(&fRegs->tfd, ATA_BSY, 31000000); |
294 | | |
295 | | fIsATAPI = fRegs->sig == 0xeb140101; |
| 340 | wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY, 31000000); |
296 | 341 | |
| 342 | fIsATAPI = fRegs->sig == SATA_SIG_ATAPI; |
297 | 343 | if (fIsATAPI) |
298 | 344 | fRegs->cmd |= PORT_CMD_ATAPI; |
299 | 345 | else |
… |
… |
AHCIPort::PostReset()
|
302 | 348 | |
303 | 349 | if (!fTestUnitReadyActive) { |
304 | 350 | TRACE("device signature 0x%08" B_PRIx32 " (%s)\n", fRegs->sig, |
305 | | fRegs->sig == 0xeb140101 ? "ATAPI" : fRegs->sig == 0x00000101 |
| 351 | fRegs->sig == SATA_SIG_ATAPI ? "ATAPI" : fRegs->sig == SATA_SIG_ATA |
306 | 352 | ? "ATA" : "unknown"); |
307 | 353 | } |
308 | 354 | |
| 355 | _ClearErrorRegister(); |
| 356 | |
309 | 357 | return B_OK; |
310 | 358 | } |
311 | 359 | |
… |
… |
AHCIPort::InterruptErrorHandler(uint32 is)
|
374 | 422 | } |
375 | 423 | |
376 | 424 | // read and clear SError |
377 | | uint32 serr = fRegs->serr; |
378 | | fRegs->serr = serr; |
| 425 | _ClearErrorRegister(); |
379 | 426 | |
380 | 427 | if (is & PORT_INT_TFE) { |
381 | 428 | if (!fTestUnitReadyActive) |
382 | 429 | TRACE("Task File Error\n"); |
383 | 430 | |
384 | | fResetPort = true; |
| 431 | fSoftReset = true; |
385 | 432 | fError = true; |
386 | 433 | } |
387 | 434 | if (is & PORT_INT_HBF) { |
388 | 435 | TRACE("Host Bus Fatal Error\n"); |
389 | | fResetPort = true; |
| 436 | fSoftReset = true; |
390 | 437 | fError = true; |
391 | 438 | } |
392 | 439 | if (is & PORT_INT_HBD) { |
393 | 440 | TRACE("Host Bus Data Error\n"); |
394 | | fResetPort = true; |
| 441 | fSoftReset = true; |
395 | 442 | fError = true; |
396 | 443 | } |
397 | 444 | if (is & PORT_INT_IF) { |
398 | 445 | TRACE("Interface Fatal Error\n"); |
399 | | fResetPort = true; |
| 446 | fSoftReset = true; |
400 | 447 | fError = true; |
401 | 448 | } |
402 | 449 | if (is & PORT_INT_INF) { |
… |
… |
AHCIPort::InterruptErrorHandler(uint32 is)
|
404 | 451 | } |
405 | 452 | if (is & PORT_INT_OF) { |
406 | 453 | TRACE("Overflow\n"); |
407 | | fResetPort = true; |
| 454 | fSoftReset = true; |
408 | 455 | fError = true; |
409 | 456 | } |
410 | 457 | if (is & PORT_INT_IPM) { |
… |
… |
AHCIPort::InterruptErrorHandler(uint32 is)
|
412 | 459 | } |
413 | 460 | if (is & PORT_INT_PRC) { |
414 | 461 | TRACE("PhyReady Change\n"); |
415 | | // fResetPort = true; |
| 462 | // fSoftReset = true; |
416 | 463 | } |
417 | 464 | if (is & PORT_INT_PC) { |
418 | 465 | TRACE("Port Connect Change\n"); |
419 | 466 | // Spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT |
420 | | |
421 | | // perform a hard reset |
422 | | if (!_HardReset()) |
423 | | return; |
424 | | |
425 | | // clear error bits to clear PxSERR.DIAG.X |
| 467 | // Spec v1.3.1, §7.4 Interaction of command list and port change status |
| 468 | // TODO: Issue COMRESET ? |
| 469 | //PortReset(); |
| 470 | //HBAReset(); ??? |
426 | 471 | _ClearErrorRegister(); |
427 | 472 | } |
428 | 473 | if (is & PORT_INT_UF) { |
429 | 474 | TRACE("Unknown FIS\n"); |
430 | | fResetPort = true; |
| 475 | fSoftReset = true; |
431 | 476 | } |
432 | 477 | |
433 | 478 | if (fError) { |
… |
… |
AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,
|
452 | 497 | status_t status = get_memory_map_etc(B_CURRENT_TEAM, data, dataSize, |
453 | 498 | entries, &entriesUsed); |
454 | 499 | if (status != B_OK) { |
455 | | TRACE("AHCIPort::FillPrdTable get_memory_map() failed: %s\n", |
456 | | strerror(status)); |
| 500 | TRACE("%s: get_memory_map() failed: %s\n", __func__, strerror(status)); |
457 | 501 | return B_ERROR; |
458 | 502 | } |
459 | 503 | |
… |
… |
AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,
|
500 | 544 | sgCount--; |
501 | 545 | } |
502 | 546 | if (*prdCount == 0) { |
503 | | TRACE("AHCIPort::FillPrdTable: count is 0\n"); |
| 547 | TRACE("%s: count is 0\n", __func__); |
504 | 548 | return B_ERROR; |
505 | 549 | } |
506 | 550 | if (dataSize > 0) { |
… |
… |
AHCIPort::ScsiInquiry(scsi_ccb* request)
|
663 | 707 | ExecuteSataRequest(&sreq); |
664 | 708 | sreq.WaitForCompletion(); |
665 | 709 | |
666 | | if ((sreq.CompletionStatus() & ATA_ERR) != 0) { |
| 710 | if ((sreq.CompletionStatus() & ATA_STATUS_ERROR) != 0) { |
667 | 711 | ERROR("identify device failed\n"); |
668 | 712 | request->subsys_status = SCSI_REQ_CMP_ERR; |
669 | 713 | gSCSI->finished(request, 1); |
… |
… |
for (uint32 i = 0; i < lbaRangeCount; i++) {
|
1005 | 1049 | ExecuteSataRequest(&sreq); |
1006 | 1050 | sreq.WaitForCompletion(); |
1007 | 1051 | |
1008 | | if ((sreq.CompletionStatus() & ATA_ERR) != 0) { |
| 1052 | if ((sreq.CompletionStatus() & ATA_STATUS_ERROR) != 0) { |
1009 | 1053 | TRACE("trim failed (%" B_PRIu32 " ranges)!\n", lbaRangeCount); |
1010 | 1054 | request->subsys_status = SCSI_REQ_CMP_ERR; |
1011 | 1055 | } else |
… |
… |
AHCIPort::ExecuteSataRequest(sata_request* request, bool isWrite)
|
1057 | 1101 | fCommandList->prdtl = prdEntrys; |
1058 | 1102 | fCommandList->prdbc = 0; |
1059 | 1103 | |
1060 | | if (wait_until_clear(&fRegs->tfd, ATA_BSY | ATA_DRQ, 1000000) < B_OK) { |
| 1104 | if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST, |
| 1105 | 1000000) < B_OK) { |
1061 | 1106 | TRACE("ExecuteAtaRequest port %d: device is busy\n", fIndex); |
1062 | | ResetPort(); |
| 1107 | SoftReset(); |
1063 | 1108 | FinishTransfer(); |
1064 | 1109 | request->Abort(); |
1065 | 1110 | return; |
… |
… |
AHCIPort::ExecuteSataRequest(sata_request* request, bool isWrite)
|
1094 | 1139 | TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); |
1095 | 1140 | */ |
1096 | 1141 | |
1097 | | if (fResetPort || status == B_TIMED_OUT) { |
1098 | | fResetPort = false; |
1099 | | ResetPort(); |
| 1142 | if (fSoftReset || status == B_TIMED_OUT) { |
| 1143 | fSoftReset = false; |
| 1144 | SoftReset(); |
1100 | 1145 | } |
1101 | 1146 | |
1102 | 1147 | size_t bytesTransfered = fCommandList->prdbc; |
… |
… |
AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense,
|
1322 | 1367 | |
1323 | 1368 | |
1324 | 1369 | bool |
1325 | | AHCIPort::_HardReset() |
| 1370 | AHCIPort::Enable() |
1326 | 1371 | { |
| 1372 | // Spec v1.3.1, §10.3.1 Start (PxCMD.ST) |
| 1373 | TRACE("%s: port %d\n", __func__, fIndex); |
1327 | 1374 | if ((fRegs->cmd & PORT_CMD_ST) != 0) { |
1328 | | // We shouldn't perform a reset, but at least document it |
1329 | | TRACE("AHCIPort::_HardReset() PORT_CMD_ST set, behaviour undefined\n"); |
| 1375 | TRACE("%s: Starting port already running!\n", __func__); |
1330 | 1376 | return false; |
1331 | 1377 | } |
1332 | 1378 | |
1333 | | fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) |
1334 | | | DET_INITIALIZATION << SATA_CONTROL_DET_SHIFT; |
| 1379 | if ((fRegs->cmd & PORT_CMD_FRE) == 0) { |
| 1380 | TRACE("%s: Unable to start port without FRE enabled!\n", __func__); |
| 1381 | return false; |
| 1382 | } |
| 1383 | |
| 1384 | // Clear DMA engine and wait for completion |
| 1385 | if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { |
| 1386 | TRACE("%s: port %d error DMA engine still running\n", __func__, |
| 1387 | fIndex); |
| 1388 | return false; |
| 1389 | } |
| 1390 | // Start port |
| 1391 | fRegs->cmd |= PORT_CMD_ST; |
1335 | 1392 | FlushPostedWrites(); |
1336 | | spin(1100); |
1337 | | // You must wait 1ms at minimum |
1338 | | fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) |
1339 | | | DET_NO_INITIALIZATION << SATA_CONTROL_DET_SHIFT; |
| 1393 | return true; |
| 1394 | } |
| 1395 | |
| 1396 | |
| 1397 | bool |
| 1398 | AHCIPort::Disable() |
| 1399 | { |
| 1400 | TRACE("%s: port %d\n", __func__, fIndex); |
| 1401 | |
| 1402 | if ((fRegs->cmd & PORT_CMD_ST) == 0) { |
| 1403 | TRACE("%s: port %d attempting to disable stopped port.\n", |
| 1404 | __func__, fIndex); |
| 1405 | } |
| 1406 | |
| 1407 | // Disable port |
| 1408 | fRegs->cmd &= ~PORT_CMD_ST; |
1340 | 1409 | FlushPostedWrites(); |
1341 | 1410 | |
| 1411 | // Spec v1.3.1, §10.4.2 Port Reset - assume hung after 500 mil. |
| 1412 | // Clear DMA engine and wait for completion |
| 1413 | if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { |
| 1414 | TRACE("%s: port %d error DMA engine still running\n", __func__, |
| 1415 | fIndex); |
| 1416 | return false; |
| 1417 | } |
| 1418 | |
1342 | 1419 | return true; |
1343 | 1420 | } |
1344 | 1421 | |
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
index 0bc4e67..deed571 100644
a
|
b
|
private:
|
48 | 48 | void ExecuteSataRequest(sata_request *request, bool isWrite = false); |
49 | 49 | |
50 | 50 | void ResetDevice(); |
51 | | status_t ResetPort(bool forceDeviceReset = false); |
| 51 | status_t SoftReset(); |
| 52 | status_t PortReset(); |
52 | 53 | status_t PostReset(); |
| 54 | |
| 55 | bool Enable(); |
| 56 | bool Disable(); |
| 57 | |
53 | 58 | void FlushPostedWrites(); |
54 | 59 | void DumpD2HFis(); |
55 | 60 | |
… |
… |
private:
|
57 | 62 | status_t WaitForTransfer(int *tfd, bigtime_t timeout); |
58 | 63 | void FinishTransfer(); |
59 | 64 | |
60 | | inline bool _HardReset(); |
61 | 65 | inline void _ClearErrorRegister(); |
62 | 66 | |
63 | 67 | // uint8 * SetCommandFis(volatile command_list_entry *cmd, volatile fis *fis, const void *data, size_t dataSize); |
… |
… |
private:
|
79 | 83 | uint64 fSectorCount; |
80 | 84 | bool fIsATAPI; |
81 | 85 | bool fTestUnitReadyActive; |
82 | | bool fResetPort; |
| 86 | bool fSoftReset; |
83 | 87 | bool fError; |
84 | 88 | bool fTrimSupported; |
85 | 89 | uint32 fMaxTrimRangeBlocks; |
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
index 6a53fcf..9e06dce 100644
a
|
b
|
sata_request::SetATAPICommand(size_t transferLength)
|
121 | 121 | void |
122 | 122 | sata_request::Finish(int tfd, size_t bytesTransfered) |
123 | 123 | { |
124 | | if ((tfd & (ATA_ERR | ATA_DF)) != 0) { |
| 124 | if ((tfd & (ATA_STATUS_ERROR | ATA_STATUS_DEVICE_FAULT)) != 0) { |
125 | 125 | uint8 status = tfd & 0xff; |
126 | 126 | uint8 error = (tfd >> 8) & 0xff; |
127 | 127 | |
… |
… |
sata_request::Finish(int tfd, size_t bytesTransfered)
|
135 | 135 | fCcb->data_resid = fCcb->data_length - bytesTransfered; |
136 | 136 | fCcb->device_status = SCSI_STATUS_GOOD; |
137 | 137 | fCcb->subsys_status = SCSI_REQ_CMP; |
138 | | if (tfd & (ATA_ERR | ATA_DF)) { |
| 138 | if (tfd & (ATA_STATUS_ERROR | ATA_STATUS_DEVICE_FAULT)) { |
139 | 139 | fCcb->subsys_status = SCSI_REQ_CMP_ERR; |
140 | 140 | if (fIsATAPI) { |
141 | 141 | if (!IsTestUnitReady()) { |
… |
… |
sata_request::Abort()
|
187 | 187 | gSCSI->finished(fCcb, 1); |
188 | 188 | delete this; |
189 | 189 | } else { |
190 | | fCompletionStatus = ATA_ERR; |
| 190 | fCompletionStatus = ATA_STATUS_ERROR; |
191 | 191 | release_sem(fCompletionSem); |
192 | 192 | } |
193 | 193 | } |