Ticket #12357: ahci-rework-v1.diff
File ahci-rework-v1.diff, 5.2 KB (added by , 9 years ago) |
---|
-
src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h
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..a465fe2 100644
a b enum { 130 130 PORT_CMD_ATAPI = (1 << 24), // Device is ATAPI 131 131 PORT_CMD_CR = (1 << 15), // Command List Running (DMA active) 132 132 PORT_CMD_FR = (1 << 14), // FIS Receive Running 133 PORT_CMD_F ER= (1 << 4), // FIS Receive Enable133 PORT_CMD_FRE = (1 << 4), // FIS Receive Enable 134 134 PORT_CMD_CLO = (1 << 3), // Command List Override 135 135 PORT_CMD_POD = (1 << 2), // Power On Device 136 136 PORT_CMD_SUD = (1 << 1), // Spin-up Device -
src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
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 82efc5b..e6138a1 100644
a b AHCIPort::Init1() 132 132 fRegs->cmd = (fRegs->cmd & ~PORT_CMD_ICC_MASK) | PORT_CMD_ICC_ACTIVE; 133 133 134 134 // enable FIS receive 135 fRegs->cmd |= PORT_CMD_F ER;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 engine150 fRegs->cmd |= PORT_CMD_ST;149 // enable port 150 Enable(true); 151 151 152 152 // enable interrupts 153 153 fRegs->ie = PORT_INT_MASK; 154 154 155 155 FlushPostedWrites(); 156 156 157 ResetPort(true);158 159 157 TRACE("ie 0x%08" B_PRIx32 "\n", fRegs->ie); 160 158 TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); 161 159 TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); … … AHCIPort::Uninit() 181 179 { 182 180 TRACE("AHCIPort::Uninit port %d\n", fIndex); 183 181 184 // disable FIS receive 185 fRegs->cmd &= ~PORT_CMD_FER; 186 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 } 191 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 } 182 // shutdown the port 183 Enable(false); 200 184 201 185 // disable interrupts 202 186 fRegs->ie = 0; … … status_t 240 224 AHCIPort::ResetPort(bool forceDeviceReset) 241 225 { 242 226 if (!fTestUnitReadyActive) 243 TRACE(" AHCIPort::ResetPort port %d\n", fIndex);227 TRACE("%s: port %d\n", __func__, fIndex); 244 228 245 // stop DMA engine 246 fRegs->cmd &= ~PORT_CMD_ST; 247 FlushPostedWrites(); 248 249 if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { 250 TRACE("AHCIPort::ResetPort port %d error DMA engine doesn't stop\n", 251 fIndex); 252 } 229 // stop port, flush transactions 230 Enable(false); 253 231 254 232 bool deviceBusy = fRegs->tfd & (ATA_BSY | ATA_DRQ); 255 233 … … AHCIPort::ResetPort(bool forceDeviceReset) 261 239 if (deviceBusy || forceDeviceReset) 262 240 ResetDevice(); 263 241 264 // start DMA engine 265 fRegs->cmd |= PORT_CMD_ST; 266 FlushPostedWrites(); 242 // start port 243 Enable(true); 267 244 268 245 return PostReset(); 269 246 } … … AHCIPort::InterruptErrorHandler(uint32 is) 417 394 TRACE("Port Connect Change\n"); 418 395 // Spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT 419 396 397 // TODO: Do we need to disable the port here? Or is ST clear? 398 420 399 // perform a hard reset 421 400 _HardReset(); 422 401 … … AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense, 1320 1299 1321 1300 1322 1301 void 1302 AHCIPort::Enable(bool enable) 1303 { 1304 TRACE("%s: port %d\n", __func__, fIndex); 1305 1306 if ((fRegs->cmd & PORT_CMD_ST) != 0) { 1307 if (enable) { 1308 TRACE("%s: Starting port already running!\n", __func__); 1309 return; 1310 } 1311 1312 // wait for DMA completion if port running 1313 if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { 1314 TRACE("AHCIPort::Uninit port %d error DMA engine still running\n", 1315 fIndex); 1316 } 1317 } 1318 1319 if (enable) { 1320 // Start port 1321 fRegs->cmd |= PORT_CMD_FRE; 1322 fRegs->cmd |= PORT_CMD_ST; 1323 FlushPostedWrites(); 1324 return; 1325 } 1326 1327 // Clear FRE and wait for completion 1328 fRegs->cmd &= ~PORT_CMD_FRE; 1329 FlushPostedWrites(); 1330 if (wait_until_clear(&fRegs->cmd, PORT_CMD_FR, 500000) < B_OK) { 1331 TRACE("%s: port %d error FIS receive still running\n", __func__, 1332 fIndex); 1333 } 1334 1335 // Clear DMA engine and wait for completion 1336 fRegs->cmd &= ~PORT_CMD_ST; 1337 FlushPostedWrites(); 1338 if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { 1339 TRACE("%s: port %d error DMA engine still running\n", __func__, 1340 fIndex); 1341 } 1342 } 1343 1344 1345 void 1323 1346 AHCIPort::_HardReset() 1324 1347 { 1348 TRACE("%s: Called on port %d\n", __func__, fIndex); 1325 1349 if ((fRegs->cmd & PORT_CMD_ST) != 0) { 1326 1350 // We shouldn't perform a reset, but at least document it 1327 TRACE("AHCIPort::_HardReset() PORT_CMD_ST set, behaviour undefined\n"); 1351 TRACE("%s: PORT_CMD_ST set, bypassing hard reset\n", __func__); 1352 return; 1328 1353 } 1329 1354 1330 1355 fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) -
src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
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 34cee69..1d0ae20 100644
a b private: 50 50 void ResetDevice(); 51 51 status_t ResetPort(bool forceDeviceReset = false); 52 52 status_t PostReset(); 53 void Enable(bool enabled); 54 53 55 void FlushPostedWrites(); 54 56 void DumpD2HFis(); 55 57