xref: /haiku/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp (revision 0f9ffb37c166a9d9257044c8937f6450f4257b75)
1 /*
2  * Copyright 2008-2015 Haiku, Inc. All rights reserved.
3  * Copyright 2007-2009, Marcus Overhagen. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  *
6  * Authors:
7  *		Axel Dörfler, axeld@pinc-software.de
8  *		Michael Lotz, mmlr@mlotz.ch
9  *		Alexander von Gluck IV, kallisti5@unixzen.com
10  */
11 
12 
13 #include "ahci_port.h"
14 
15 #include <new>
16 #include <stdio.h>
17 #include <string.h>
18 
19 #include <ByteOrder.h>
20 #include <KernelExport.h>
21 
22 #include <ATACommands.h>
23 #include <ATAInfoBlock.h>
24 #include <AutoDeleter.h>
25 
26 #include "ahci_controller.h"
27 #include "ahci_tracing.h"
28 #include "sata_request.h"
29 #include "scsi_cmds.h"
30 #include "util.h"
31 
32 
33 //#define TRACE_AHCI
34 #ifdef TRACE_AHCI
35 #	define TRACE(a...) dprintf("ahci: " a)
36 #else
37 #	define TRACE(a...)
38 #endif
39 
40 #define ERROR(a...) dprintf("ahci: " a)
41 //#define FLOW(a...)	dprintf("ahci: " a)
42 //#define RWTRACE(a...) dprintf("ahci: " a)
43 #define FLOW(a...)
44 #define RWTRACE(a...)
45 
46 
47 #define INQUIRY_BASE_LENGTH 36
48 
49 
50 AHCIPort::AHCIPort(AHCIController* controller, int index)
51 	:
52 	fController(controller),
53 	fIndex(index),
54 	fRegs(&controller->fRegs->port[index]),
55 	fArea(-1),
56 	fCommandsActive(0),
57 	fRequestSem(-1),
58 	fResponseSem(-1),
59 	fDevicePresent(false),
60 	fUse48BitCommands(false),
61 	fSectorSize(0),
62 	fSectorCount(0),
63 	fIsATAPI(false),
64 	fTestUnitReadyActive(false),
65 	fPortReset(false),
66 	fError(false),
67 	fTrimSupported(false)
68 {
69 	B_INITIALIZE_SPINLOCK(&fSpinlock);
70 	fRequestSem = create_sem(1, "ahci request");
71 	fResponseSem = create_sem(0, "ahci response");
72 }
73 
74 
75 AHCIPort::~AHCIPort()
76 {
77 	delete_sem(fRequestSem);
78 	delete_sem(fResponseSem);
79 }
80 
81 
82 status_t
83 AHCIPort::Init1()
84 {
85 	TRACE("AHCIPort::Init1 port %d\n", fIndex);
86 
87 	size_t size = sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT
88 		+ sizeof(fis) + sizeof(command_table)
89 		+ sizeof(prd) * PRD_TABLE_ENTRY_COUNT;
90 
91 	char* virtAddr;
92 	phys_addr_t physAddr;
93 	char name[32];
94 	snprintf(name, sizeof(name), "AHCI port %d", fIndex);
95 
96 	fArea = alloc_mem((void**)&virtAddr, &physAddr, size, 0, name);
97 	if (fArea < B_OK) {
98 		TRACE("failed allocating memory for port %d\n", fIndex);
99 		return fArea;
100 	}
101 	memset(virtAddr, 0, size);
102 
103 	fCommandList = (command_list_entry*)virtAddr;
104 	virtAddr += sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT;
105 	fFIS = (fis*)virtAddr;
106 	virtAddr += sizeof(fis);
107 	fCommandTable = (command_table*)virtAddr;
108 	virtAddr += sizeof(command_table);
109 	fPRDTable = (prd*)virtAddr;
110 	TRACE("PRD table is at %p\n", fPRDTable);
111 
112 	fRegs->clb  = LO32(physAddr);
113 	fRegs->clbu = HI32(physAddr);
114 	physAddr += sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT;
115 	fRegs->fb   = LO32(physAddr);
116 	fRegs->fbu  = HI32(physAddr);
117 	physAddr += sizeof(fis);
118 	fCommandList[0].ctba  = LO32(physAddr);
119 	fCommandList[0].ctbau = HI32(physAddr);
120 	// prdt follows after command table
121 
122 	// disable transitions to partial or slumber state
123 	fRegs->sctl |= (SCTL_PORT_IPM_NOPART | SCTL_PORT_IPM_NOSLUM);
124 
125 	// clear IRQ status bits
126 	fRegs->is = fRegs->is;
127 
128 	// clear error bits
129 	_ClearErrorRegister();
130 
131 	// power up device
132 	fRegs->cmd |= PORT_CMD_POD;
133 
134 	// spin up device
135 	fRegs->cmd |= PORT_CMD_SUD;
136 
137 	// activate link
138 	fRegs->cmd = (fRegs->cmd & ~PORT_CMD_ICC_MASK) | PORT_CMD_ICC_ACTIVE;
139 
140 	// enable FIS receive (enabled when fb set, only to be disabled when unset)
141 	fRegs->cmd |= PORT_CMD_FRE;
142 
143 	FlushPostedWrites();
144 
145 	return B_OK;
146 }
147 
148 
149 // called with global interrupts enabled
150 status_t
151 AHCIPort::Init2()
152 {
153 	TRACE("AHCIPort::Init2 port %d\n", fIndex);
154 
155 	// enable port
156 	Enable();
157 
158 	// enable interrupts
159 	fRegs->ie = PORT_INT_MASK;
160 
161 	FlushPostedWrites();
162 
163 	// reset port and probe info
164 	ResetDevice();
165 
166 	DumpHBAState();
167 
168 	TRACE("%s: port %d, device %s\n", __func__, fIndex,
169 		fDevicePresent ? "present" : "absent");
170 
171 	return B_OK;
172 }
173 
174 
175 void
176 AHCIPort::Uninit()
177 {
178 	TRACE("AHCIPort::Uninit port %d\n", fIndex);
179 
180 	// Spec v1.3.1, §10.3.2 - Shut down port before unsetting FRE
181 
182 	// shutdown the port
183 	if (!Disable()) {
184 		ERROR("%s: port %d error, unable to shutdown before FRE clear!\n",
185 			__func__, fIndex);
186 		return;
187 	}
188 
189 	// Clear FRE and wait for completion
190 	fRegs->cmd &= ~PORT_CMD_FRE;
191 	if (wait_until_clear(&fRegs->cmd, PORT_CMD_FR, 500000) < B_OK)
192 		ERROR("%s: port %d error FIS rx still running\n", __func__, fIndex);
193 
194 	// disable interrupts
195 	fRegs->ie = 0;
196 
197 	// clear pending interrupts
198 	fRegs->is = fRegs->is;
199 
200 	// invalidate DMA addresses
201 	fRegs->clb  = 0;
202 	fRegs->clbu = 0;
203 	fRegs->fb   = 0;
204 	fRegs->fbu  = 0;
205 
206 	delete_area(fArea);
207 }
208 
209 
210 void
211 AHCIPort::ResetDevice()
212 {
213 	// perform a hard reset
214 	if (PortReset() != B_OK) {
215 		ERROR("%s: port %d unable to hard reset device\n", __func__, fIndex);
216 		return;
217 	}
218 
219 	if (wait_until_set(&fRegs->ssts, SSTS_PORT_DET_NODEV, 100000) < B_OK)
220 		TRACE("AHCIPort::ResetDevice port %d no device detected\n", fIndex);
221 
222 	_ClearErrorRegister();
223 
224 	if (fRegs->ssts & SSTS_PORT_DET_NOPHY) {
225 		if (wait_until_set(&fRegs->ssts, 0x3, 500000) < B_OK) {
226 			TRACE("AHCIPort::ResetDevice port %d device present but no phy "
227 				"communication\n", fIndex);
228 		}
229 	}
230 
231 	_ClearErrorRegister();
232 }
233 
234 
235 status_t
236 AHCIPort::PortReset()
237 {
238 	TRACE("AHCIPort::PortReset port %d\n", fIndex);
239 
240 	if (!Disable()) {
241 		ERROR("%s: port %d unable to shutdown!\n", __func__, fIndex);
242 		return B_ERROR;
243 	}
244 
245 	_ClearErrorRegister();
246 
247 	// Wait for BSY and DRQ to clear (idle port)
248 	if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST,
249 		1000000) < B_OK) {
250 		// If we can't clear busy, do a full comreset
251 
252 		// Spec v1.3.1, §10.4.2 Port Reset
253 		// Physical comm between HBA and port disabled. More Intrusive
254 		ERROR("%s: port %d undergoing COMRESET\n", __func__, fIndex);
255 
256 		// Notice we're throwing out all other control flags.
257 		fRegs->sctl = (SSTS_PORT_IPM_ACTIVE | SSTS_PORT_IPM_PARTIAL
258 			| SCTL_PORT_DET_INIT);
259 		FlushPostedWrites();
260 		spin(1100);
261 		// You must wait 1ms at minimum
262 		fRegs->sctl = (fRegs->sctl & ~HBA_PORT_DET_MASK) | SCTL_PORT_DET_NOINIT;
263 		FlushPostedWrites();
264 	}
265 
266 	Enable();
267 
268 	if (wait_until_set(&fRegs->ssts, SSTS_PORT_DET_PRESENT, 500000) < B_OK) {
269 		TRACE("%s: port %d: no device detected\n", __func__, fIndex);
270 		fDevicePresent = false;
271 		return B_OK;
272 	}
273 
274 	return Probe();
275 }
276 
277 
278 status_t
279 AHCIPort::Probe()
280 {
281 	if ((fRegs->tfd & 0xff) == 0xff)
282 		snooze(200000);
283 
284 	if ((fRegs->tfd & 0xff) == 0xff) {
285 		TRACE("%s: port %d: invalid task file status 0xff\n", __func__,
286 			fIndex);
287 		return B_ERROR;
288 	}
289 
290 	if (!fTestUnitReadyActive) {
291 		switch (fRegs->ssts & HBA_PORT_SPD_MASK) {
292 			case 0x10:
293 				ERROR("%s: port %d link speed 1.5Gb/s\n", __func__, fIndex);
294 				break;
295 			case 0x20:
296 				ERROR("%s: port %d link speed 3.0Gb/s\n", __func__, fIndex);
297 				break;
298 			case 0x30:
299 				ERROR("%s: port %d link speed 6.0Gb/s\n", __func__, fIndex);
300 				break;
301 			default:
302 				ERROR("%s: port %d link speed unrestricted\n", __func__, fIndex);
303 				break;
304 		}
305 	}
306 
307 	wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY, 31000000);
308 
309 	fDevicePresent = (fRegs->ssts & HBA_PORT_DET_MASK) == SSTS_PORT_DET_PRESENT;
310 	fIsATAPI = fRegs->sig == SATA_SIG_ATAPI;
311 
312 	if (fIsATAPI)
313 		fRegs->cmd |= PORT_CMD_ATAPI;
314 	else
315 		fRegs->cmd &= ~PORT_CMD_ATAPI;
316 	FlushPostedWrites();
317 
318 	TRACE("device signature 0x%08" B_PRIx32 " (%s)\n", fRegs->sig,
319 		fRegs->sig == SATA_SIG_ATAPI ? "ATAPI" : fRegs->sig == SATA_SIG_ATA
320 			? "ATA" : "unknown");
321 
322 	return B_OK;
323 }
324 
325 
326 void
327 AHCIPort::DumpD2HFis()
328 {
329 	TRACE("D2H FIS:\n");
330 	TRACE("  DW0  %02x %02x %02x %02x\n", fFIS->rfis[3], fFIS->rfis[2],
331 		fFIS->rfis[1], fFIS->rfis[0]);
332 	TRACE("  DW1  %02x %02x %02x %02x\n", fFIS->rfis[7], fFIS->rfis[6],
333 		fFIS->rfis[5], fFIS->rfis[4]);
334 	TRACE("  DW2  %02x %02x %02x %02x\n", fFIS->rfis[11], fFIS->rfis[10],
335 		fFIS->rfis[9], fFIS->rfis[8]);
336 	TRACE("  DW3  %02x %02x %02x %02x\n", fFIS->rfis[15], fFIS->rfis[14],
337 		fFIS->rfis[13], fFIS->rfis[12]);
338 	TRACE("  DW4  %02x %02x %02x %02x\n", fFIS->rfis[19], fFIS->rfis[18],
339 		fFIS->rfis[17], fFIS->rfis[16]);
340 }
341 
342 
343 void
344 AHCIPort::DumpHBAState()
345 {
346 	TRACE("Port %d state:\n", fIndex);
347 	TRACE("  ie   0x%08" B_PRIx32 "\n", fRegs->ie);
348 	TRACE("  is   0x%08" B_PRIx32 "\n", fRegs->is);
349 	TRACE("  cmd  0x%08" B_PRIx32 "\n", fRegs->cmd);
350 	TRACE("  ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
351 	TRACE("  sctl 0x%08" B_PRIx32 "\n", fRegs->sctl);
352 	TRACE("  serr 0x%08" B_PRIx32 "\n", fRegs->serr);
353 	TRACE("  sact 0x%08" B_PRIx32 "\n", fRegs->sact);
354 	TRACE("  tfd  0x%08" B_PRIx32 "\n", fRegs->tfd);
355 }
356 
357 
358 void
359 AHCIPort::Interrupt()
360 {
361 	uint32 is = fRegs->is;
362 	fRegs->is = is; // clear interrupts
363 
364 	if (is & PORT_INT_ERROR) {
365 		InterruptErrorHandler(is);
366 		return;
367 	}
368 
369 	uint32 ci = fRegs->ci;
370 
371 	RWTRACE("[%lld] %ld AHCIPort::Interrupt port %d, fCommandsActive 0x%08"
372 		B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n",
373 		system_time(), find_thread(NULL), fIndex, fCommandsActive, is, ci);
374 
375 	acquire_spinlock(&fSpinlock);
376 	if ((fCommandsActive & 1) && !(ci & 1)) {
377 		fCommandsActive &= ~1;
378 		release_sem_etc(fResponseSem, 1, B_DO_NOT_RESCHEDULE);
379 	}
380 	release_spinlock(&fSpinlock);
381 }
382 
383 
384 void
385 AHCIPort::InterruptErrorHandler(uint32 is)
386 {
387 	TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08"
388 		B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex,
389 		fCommandsActive, is, fRegs->ci);
390 	TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
391 	TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl);
392 	TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr);
393 	TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact);
394 
395 	// read and clear SError
396 	_ClearErrorRegister();
397 
398 	if (is & PORT_INT_TFE) {
399 		TRACE("Task File Error\n");
400 
401 		fPortReset = true;
402 		fError = true;
403 	}
404 	if (is & PORT_INT_HBF) {
405 		ERROR("Host Bus Fatal Error\n");
406 		fPortReset = true;
407 		fError = true;
408 	}
409 	if (is & PORT_INT_HBD) {
410 		ERROR("Host Bus Data Error\n");
411 		fPortReset = true;
412 		fError = true;
413 	}
414 	if (is & PORT_INT_IF) {
415 		ERROR("Interface Fatal Error\n");
416 		fPortReset = true;
417 		fError = true;
418 	}
419 	if (is & PORT_INT_INF) {
420 		TRACE("Interface Non Fatal Error\n");
421 	}
422 	if (is & PORT_INT_OF) {
423 		TRACE("Overflow\n");
424 		fPortReset = true;
425 		fError = true;
426 	}
427 	if (is & PORT_INT_IPM) {
428 		TRACE("Incorrect Port Multiplier Status\n");
429 	}
430 	if (is & PORT_INT_PRC) {
431 		TRACE("PhyReady Change\n");
432 		//fPortReset = true;
433 	}
434 	if (is & PORT_INT_PC) {
435 		TRACE("Port Connect Change\n");
436 		// Unsolicited when we had a port connect change without us requesting
437 		// Spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT
438 
439 		// XXX: This shouldn't be needed here... but we can loop without it
440 		//_ClearErrorRegister();
441 	}
442 	if (is & PORT_INT_UF) {
443 		TRACE("Unknown FIS\n");
444 		fPortReset = true;
445 	}
446 
447 	if (fError) {
448 		acquire_spinlock(&fSpinlock);
449 		if ((fCommandsActive & 1)) {
450 			fCommandsActive &= ~1;
451 			release_sem_etc(fResponseSem, 1, B_DO_NOT_RESCHEDULE);
452 		}
453 		release_spinlock(&fSpinlock);
454 	}
455 }
456 
457 
458 status_t
459 AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,
460 	const void* data, size_t dataSize)
461 {
462 	int maxEntries = prdMax + 1;
463 	physical_entry entries[maxEntries];
464 	uint32 entriesUsed = maxEntries;
465 
466 	status_t status = get_memory_map_etc(B_CURRENT_TEAM, data, dataSize,
467 		entries, &entriesUsed);
468 	if (status != B_OK) {
469 		ERROR("%s: get_memory_map() failed: %s\n", __func__, strerror(status));
470 		return B_ERROR;
471 	}
472 
473 	return FillPrdTable(prdTable, prdCount, prdMax, entries, entriesUsed,
474 		dataSize);
475 }
476 
477 
478 status_t
479 AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,
480 	const physical_entry* sgTable, int sgCount, size_t dataSize)
481 {
482 	*prdCount = 0;
483 	while (sgCount > 0 && dataSize > 0) {
484 		size_t size = min_c(sgTable->size, dataSize);
485 		phys_addr_t address = sgTable->address;
486 		T_PORT(AHCIPortPrdTable(fController, fIndex, address, size));
487 		FLOW("FillPrdTable: sg-entry addr %#" B_PRIxPHYSADDR ", size %lu\n",
488 			address, size);
489 		if (address & 1) {
490 			ERROR("AHCIPort::FillPrdTable: data alignment error\n");
491 			return B_ERROR;
492 		}
493 		dataSize -= size;
494 		while (size > 0) {
495 			size_t bytes = min_c(size, PRD_MAX_DATA_LENGTH);
496 			if (*prdCount == prdMax) {
497 				ERROR("AHCIPort::FillPrdTable: prd table exhausted\n");
498 				return B_ERROR;
499 			}
500 			FLOW("FillPrdTable: prd-entry %u, addr %p, size %lu\n",
501 				*prdCount, address, bytes);
502 
503 			prdTable->dba = LO32(address);
504 			prdTable->dbau = HI32(address);
505 			prdTable->res = 0;
506 			prdTable->dbc = bytes - 1;
507 			*prdCount += 1;
508 			prdTable++;
509 			address = address + bytes;
510 			size -= bytes;
511 		}
512 		sgTable++;
513 		sgCount--;
514 	}
515 	if (*prdCount == 0) {
516 		ERROR("%s: count is 0\n", __func__);
517 		return B_ERROR;
518 	}
519 	if (dataSize > 0) {
520 		ERROR("AHCIPort::FillPrdTable: sg table %ld bytes too small\n",
521 			dataSize);
522 		return B_ERROR;
523 	}
524 	return B_OK;
525 }
526 
527 
528 void
529 AHCIPort::StartTransfer()
530 {
531 	acquire_sem(fRequestSem);
532 }
533 
534 
535 status_t
536 AHCIPort::WaitForTransfer(int* tfd, bigtime_t timeout)
537 {
538 	status_t result = acquire_sem_etc(fResponseSem, 1, B_RELATIVE_TIMEOUT,
539 		timeout);
540 	if (result < B_OK) {
541 		cpu_status cpu = disable_interrupts();
542 		acquire_spinlock(&fSpinlock);
543 		fCommandsActive &= ~1;
544 		release_spinlock(&fSpinlock);
545 		restore_interrupts(cpu);
546 
547 		result = B_TIMED_OUT;
548 	} else if (fError) {
549 		*tfd = fRegs->tfd;
550 		result = B_ERROR;
551 		fError = false;
552 	} else {
553 		*tfd = fRegs->tfd;
554 	}
555 	return result;
556 }
557 
558 
559 void
560 AHCIPort::FinishTransfer()
561 {
562 	release_sem(fRequestSem);
563 }
564 
565 
566 void
567 AHCIPort::ScsiTestUnitReady(scsi_ccb* request)
568 {
569 	TRACE("AHCIPort::ScsiTestUnitReady port %d\n", fIndex);
570 	request->subsys_status = SCSI_REQ_CMP;
571 	gSCSI->finished(request, 1);
572 }
573 
574 
575 void
576 AHCIPort::ScsiVPDInquiry(scsi_ccb* request, ata_device_infoblock* ataData)
577 {
578 	TRACE("AHCIPort::ScsiVPDInquiry port %d\n", fIndex);
579 
580 	const scsi_cmd_inquiry* cmd = (const scsi_cmd_inquiry*)request->cdb;
581 
582 	size_t vpdDataLength = 0;
583 	status_t transactionResult = B_ERROR;
584 
585 	switch (cmd->page_code) {
586 		case SCSI_PAGE_SUPPORTED_VPD:
587 		{
588 			scsi_page_list vpdPageData;
589 			vpdDataLength = sizeof(vpdPageData);
590 
591 			vpdPageData.page_code = cmd->page_code;
592 			// Our supported pages
593 			vpdPageData.page_length = 1;
594 			vpdPageData.pages[0] = SCSI_PAGE_BLOCK_LIMITS;
595 
596 			transactionResult = sg_memcpy(request->sg_list, request->sg_count,
597 				&vpdPageData, vpdDataLength);
598 			break;
599 		}
600 		case SCSI_PAGE_BLOCK_LIMITS:
601 		{
602 			scsi_page_block_limits vpdPageData;
603 			vpdDataLength = sizeof(vpdPageData);
604 
605 			vpdPageData.page_code = cmd->page_code;
606 			vpdPageData.max_unmap_lba_count
607 				= ataData->max_data_set_management_lba_range_blocks;
608 
609 			transactionResult = sg_memcpy(request->sg_list, request->sg_count,
610 				&vpdPageData, vpdDataLength);
611 			break;
612 		}
613 		case SCSI_PAGE_USN:
614 		case SCSI_PAGE_BLOCK_DEVICE_CHARS:
615 		case SCSI_PAGE_LB_PROVISIONING:
616 		case SCSI_PAGE_REFERRALS:
617 			ERROR("VPD AHCI page %d not yet implemented!\n",
618 				cmd->page_code);
619 			//request->subsys_status = SCSI_REQ_CMP;
620 			request->subsys_status = SCSI_REQ_ABORTED;
621 			return;
622 		default:
623 			ERROR("unknown VPD page code!\n");
624 			request->subsys_status = SCSI_REQ_ABORTED;
625 			return;
626 	}
627 
628 	if (transactionResult < B_OK) {
629 		request->subsys_status = SCSI_DATA_RUN_ERR;
630 	} else {
631 		request->subsys_status = SCSI_REQ_CMP;
632 		request->data_resid = request->data_length
633 			- vpdDataLength;
634 	}
635 }
636 
637 
638 void
639 AHCIPort::ScsiInquiry(scsi_ccb* request)
640 {
641 	TRACE("AHCIPort::ScsiInquiry port %d\n", fIndex);
642 
643 	const scsi_cmd_inquiry* cmd = (const scsi_cmd_inquiry*)request->cdb;
644 	scsi_res_inquiry scsiData;
645 	ata_device_infoblock ataData;
646 
647 	ASSERT(sizeof(ataData) == 512);
648 
649 	if (cmd->evpd) {
650 		TRACE("VPD inquiry page 0x%X\n", cmd->page_code);
651 		if (!request->data || request->data_length == 0) {
652 			ERROR("invalid VPD request\n");
653 			request->subsys_status = SCSI_REQ_ABORTED;
654 			gSCSI->finished(request, 1);
655 			return;
656 		}
657 	} else if (cmd->page_code) {
658 		// page_code without evpd is invalid per SCSI spec
659 		ERROR("page code 0x%X on non-VPD request\n", cmd->page_code);
660 		request->subsys_status = SCSI_REQ_ABORTED;
661 		request->device_status = SCSI_STATUS_CHECK_CONDITION;
662 		// TODO: Sense ILLEGAL REQUEST + INVALID FIELD IN CDB?
663 		gSCSI->finished(request, 1);
664 		return;
665 	} else if (request->data_length < INQUIRY_BASE_LENGTH) {
666 		ERROR("invalid request %" B_PRIu32 "\n", request->data_length);
667 		request->subsys_status = SCSI_REQ_ABORTED;
668 		gSCSI->finished(request, 1);
669 		return;
670 	}
671 
672 	sata_request sreq;
673 	sreq.SetData(&ataData, sizeof(ataData));
674 	sreq.SetATACommand(fIsATAPI
675 		? ATA_COMMAND_IDENTIFY_PACKET_DEVICE : ATA_COMMAND_IDENTIFY_DEVICE);
676 	ExecuteSataRequest(&sreq);
677 	sreq.WaitForCompletion();
678 
679 	if ((sreq.CompletionStatus() & ATA_STATUS_ERROR) != 0) {
680 		ERROR("identify device failed\n");
681 		request->subsys_status = SCSI_REQ_CMP_ERR;
682 		gSCSI->finished(request, 1);
683 		return;
684 	}
685 
686 	if (cmd->evpd) {
687 		// Simulate SCSI VPD data.
688 		ScsiVPDInquiry(request, &ataData);
689 		gSCSI->finished(request, 1);
690 		return;
691 	}
692 
693 /*
694 	uint8* data = (uint8*)&ataData;
695 	for (int i = 0; i < 512; i += 8) {
696 		TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1],
697 			data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]);
698 	}
699 */
700 
701 	scsiData.device_type = fIsATAPI
702 		? ataData.word_0.atapi.command_packet_set : scsi_dev_direct_access;
703 	scsiData.device_qualifier = scsi_periph_qual_connected;
704 	scsiData.device_type_modifier = 0;
705 	scsiData.removable_medium = ataData.word_0.ata.removable_media_device;
706 	scsiData.ansi_version = 2;
707 	scsiData.ecma_version = 0;
708 	scsiData.iso_version = 0;
709 	scsiData.response_data_format = 2;
710 	scsiData.term_iop = false;
711 	scsiData.additional_length = sizeof(scsi_res_inquiry) - 4;
712 	scsiData.soft_reset = false;
713 	scsiData.cmd_queue = false;
714 	scsiData.linked = false;
715 	scsiData.sync = false;
716 	scsiData.write_bus16 = true;
717 	scsiData.write_bus32 = false;
718 	scsiData.relative_address = false;
719 
720 	if (!fIsATAPI) {
721 		fSectorCount = ataData.SectorCount(fUse48BitCommands, true);
722 		fSectorSize = ataData.SectorSize();
723 		fTrimSupported = ataData.data_set_management_support;
724 		fMaxTrimRangeBlocks = B_LENDIAN_TO_HOST_INT16(
725 			ataData.max_data_set_management_lba_range_blocks);
726 		TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" B_PRIu32
727 			", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n",
728 			ataData.dma_supported != 0, ataData.lba48_supported != 0,
729 			fUse48BitCommands, ataData.lba_sector_count,
730 			ataData.lba48_sector_count, fSectorCount * fSectorSize);
731 		if (fTrimSupported) {
732 			if (fMaxTrimRangeBlocks == 0)
733 				fMaxTrimRangeBlocks = 1;
734 
735 			#ifdef TRACE_AHCI
736 			bool deterministic = ataData.supports_deterministic_read_after_trim;
737 			TRACE("trim supported, %" B_PRIu32 " ranges blocks, reads are "
738 				"%sdeterministic%s.\n", fMaxTrimRangeBlocks,
739 				deterministic ? "" : "non-", deterministic
740 					? (ataData.supports_read_zero_after_trim
741 						? ", zero" : ", random") : "");
742 			#endif
743 		}
744 	}
745 
746 #if 0
747 	if (fSectorCount < 0x0fffffff) {
748 		TRACE("disabling 48 bit commands\n");
749 		fUse48BitCommands = 0;
750 	}
751 #endif
752 
753 	char modelNumber[sizeof(ataData.model_number) + 1];
754 	char serialNumber[sizeof(ataData.serial_number) + 1];
755 	char firmwareRev[sizeof(ataData.firmware_revision) + 1];
756 
757 	strlcpy(modelNumber, ataData.model_number, sizeof(modelNumber));
758 	strlcpy(serialNumber, ataData.serial_number, sizeof(serialNumber));
759 	strlcpy(firmwareRev, ataData.firmware_revision, sizeof(firmwareRev));
760 
761 	swap_words(modelNumber, sizeof(modelNumber) - 1);
762 	swap_words(serialNumber, sizeof(serialNumber) - 1);
763 	swap_words(firmwareRev, sizeof(firmwareRev) - 1);
764 
765 	TRACE("model number: %s\n", modelNumber);
766 	TRACE("serial number: %s\n", serialNumber);
767 	TRACE("firmware rev.: %s\n", firmwareRev);
768 
769 	// There's not enough space to fit all of the data in. ATA has 40 bytes for
770 	// the model number, 20 for the serial number and another 8 for the
771 	// firmware revision. SCSI has room for 8 for vendor ident, 16 for product
772 	// ident and another 4 for product revision.
773 	size_t vendorLen = strcspn(modelNumber, " ");
774 	if (vendorLen >= sizeof(scsiData.vendor_ident))
775 		vendorLen = strcspn(modelNumber, "-");
776 	if (vendorLen < sizeof(scsiData.vendor_ident)) {
777 		// First we try to break things apart smartly.
778 		snprintf(scsiData.vendor_ident, vendorLen + 1, "%s", modelNumber);
779 		size_t modelRemain = (sizeof(modelNumber) - vendorLen);
780 		if (modelRemain > sizeof(scsiData.product_ident))
781 			modelRemain = sizeof(scsiData.product_ident);
782 		memcpy(scsiData.product_ident, modelNumber + (vendorLen + 1),
783 			modelRemain);
784 	} else {
785 		// If we're unable to smartly break apart the vendor and model, just
786 		// dumbly squeeze as much in as possible.
787 		memcpy(scsiData.vendor_ident, modelNumber, sizeof(scsiData.vendor_ident));
788 		memcpy(scsiData.product_ident, modelNumber + 8,
789 			sizeof(scsiData.product_ident));
790 	}
791 	// Take the last 4 digits of the serial number as product rev
792 	size_t serialLen = sizeof(scsiData.product_rev);
793 	size_t serialOff = sizeof(serialNumber) - serialLen;
794 	memcpy(scsiData.product_rev, serialNumber + serialOff, serialLen);
795 
796 	if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
797 			sizeof(scsiData)) < B_OK) {
798 		request->subsys_status = SCSI_DATA_RUN_ERR;
799 	} else {
800 		request->subsys_status = SCSI_REQ_CMP;
801 		request->data_resid = request->data_length - sizeof(scsiData);
802 	}
803 	gSCSI->finished(request, 1);
804 }
805 
806 
807 void
808 AHCIPort::ScsiSynchronizeCache(scsi_ccb* request)
809 {
810 	//TRACE("AHCIPort::ScsiSynchronizeCache port %d\n", fIndex);
811 
812 	sata_request* sreq = new(std::nothrow) sata_request(request);
813 	if (sreq == NULL) {
814 		ERROR("out of memory when allocating sync request\n");
815 		request->subsys_status = SCSI_REQ_ABORTED;
816 		gSCSI->finished(request, 1);
817 		return;
818 	}
819 
820 	sreq->SetATACommand(fUse48BitCommands
821 		? ATA_COMMAND_FLUSH_CACHE_EXT : ATA_COMMAND_FLUSH_CACHE);
822 	ExecuteSataRequest(sreq);
823 }
824 
825 
826 void
827 AHCIPort::ScsiReadCapacity(scsi_ccb* request)
828 {
829 	TRACE("AHCIPort::ScsiReadCapacity port %d\n", fIndex);
830 
831 	const scsi_cmd_read_capacity* cmd
832 		= (const scsi_cmd_read_capacity*)request->cdb;
833 	scsi_res_read_capacity scsiData;
834 
835 	if (cmd->pmi || cmd->lba || request->data_length < sizeof(scsiData)) {
836 		TRACE("invalid request\n");
837 		request->subsys_status = SCSI_REQ_ABORTED;
838 		gSCSI->finished(request, 1);
839 		return;
840 	}
841 
842 	TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n",
843 		fSectorSize, fSectorCount);
844 
845 	scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize);
846 
847 	if (fSectorCount <= 0xffffffff)
848 		scsiData.lba = B_HOST_TO_BENDIAN_INT32(fSectorCount - 1);
849 	else
850 		scsiData.lba = 0xffffffff;
851 
852 	if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
853 			sizeof(scsiData)) < B_OK) {
854 		request->subsys_status = SCSI_DATA_RUN_ERR;
855 	} else {
856 		request->subsys_status = SCSI_REQ_CMP;
857 		request->data_resid = request->data_length - sizeof(scsiData);
858 	}
859 	gSCSI->finished(request, 1);
860 }
861 
862 
863 void
864 AHCIPort::ScsiReadCapacity16(scsi_ccb* request)
865 {
866 	TRACE("AHCIPort::ScsiReadCapacity16 port %d\n", fIndex);
867 
868 	scsi_res_read_capacity_long scsiData;
869 
870 	TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n",
871 		fSectorSize, fSectorCount);
872 
873 	scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize);
874 	scsiData.lba = B_HOST_TO_BENDIAN_INT64(fSectorCount - 1);
875 
876 	if (sg_memcpy(request->sg_list, request->sg_count, &scsiData,
877 			sizeof(scsiData)) < B_OK) {
878 		request->subsys_status = SCSI_DATA_RUN_ERR;
879 	} else {
880 		request->subsys_status = SCSI_REQ_CMP;
881 		request->data_resid = request->data_length - sizeof(scsiData);
882 	}
883 	gSCSI->finished(request, 1);
884 }
885 
886 
887 void
888 AHCIPort::ScsiReadWrite(scsi_ccb* request, uint64 lba, size_t sectorCount,
889 	bool isWrite)
890 {
891 	RWTRACE("[%lld] %ld ScsiReadWrite: position %llu, size %lu, isWrite %d\n",
892 		system_time(), find_thread(NULL), lba * 512, sectorCount * 512,
893 		isWrite);
894 
895 #if 0
896 	if (isWrite) {
897 		TRACE("write request ignored\n");
898 		request->subsys_status = SCSI_REQ_CMP;
899 		request->data_resid = 0;
900 		gSCSI->finished(request, 1);
901 		return;
902 	}
903 #endif
904 
905 	ASSERT(request->data_length == sectorCount * 512);
906 	sata_request* sreq = new(std::nothrow) sata_request(request);
907 	if (sreq == NULL) {
908 		TRACE("out of memory when allocating read/write request\n");
909 		request->subsys_status = SCSI_REQ_ABORTED;
910 		gSCSI->finished(request, 1);
911 		return;
912 	}
913 
914 	if (fUse48BitCommands) {
915 		if (sectorCount > 65536) {
916 			panic("ahci: ScsiReadWrite length too large, %lu sectors",
917 				sectorCount);
918 		}
919 		if (lba > MAX_SECTOR_LBA_48)
920 			panic("achi: ScsiReadWrite position too large for 48-bit LBA\n");
921 		sreq->SetATA48Command(
922 			isWrite ? ATA_COMMAND_WRITE_DMA_EXT : ATA_COMMAND_READ_DMA_EXT,
923 			lba, sectorCount);
924 	} else {
925 		if (sectorCount > 256) {
926 			panic("ahci: ScsiReadWrite length too large, %lu sectors",
927 				sectorCount);
928 		}
929 		if (lba > MAX_SECTOR_LBA_28)
930 			panic("achi: ScsiReadWrite position too large for normal LBA\n");
931 		sreq->SetATA28Command(isWrite
932 			? ATA_COMMAND_WRITE_DMA : ATA_COMMAND_READ_DMA, lba, sectorCount);
933 	}
934 
935 	ExecuteSataRequest(sreq, isWrite);
936 }
937 
938 
939 void
940 AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks)
941 {
942 	// Determine how many blocks are supposed to be trimmed in total
943 	uint32 scsiRangeCount = B_BENDIAN_TO_HOST_INT16(
944 		unmapBlocks->block_data_length) / sizeof(scsi_unmap_block_descriptor);
945 
946 dprintf("TRIM SCSI:\n");
947 for (uint32 i = 0; i < scsiRangeCount; i++) {
948 	dprintf("[%3" B_PRIu32 "] %" B_PRIu64 " : %" B_PRIu32 "\n", i,
949 		(uint64)B_BENDIAN_TO_HOST_INT64(unmapBlocks->blocks[i].lba),
950 		(uint32)B_BENDIAN_TO_HOST_INT32(unmapBlocks->blocks[i].block_count));
951 }
952 
953 	uint32 scsiIndex = 0;
954 	uint32 scsiLastBlocks = 0;
955 	uint32 maxLBARangeCount = fMaxTrimRangeBlocks * 512 / 8;
956 		// 512 bytes per range block, 8 bytes per range
957 
958 	// Split the SCSI ranges into ATA ranges as large as allowed.
959 	// We assume that the SCSI unmap ranges cannot be merged together
960 
961 	while (scsiIndex < scsiRangeCount) {
962 		// Determine how many LBA ranges we need for the next chunk
963 		uint32 lbaRangeCount = 0;
964 		for (uint32 i = scsiIndex; i < scsiRangeCount; i++) {
965 			uint32 scsiBlocks = B_BENDIAN_TO_HOST_INT32(
966 				unmapBlocks->blocks[i].block_count);
967 			if (scsiBlocks == 0)
968 				break;
969 			if (i == scsiIndex)
970 				scsiBlocks -= scsiLastBlocks;
971 
972 			lbaRangeCount += (scsiBlocks + 65534) / 65535;
973 			if (lbaRangeCount >= maxLBARangeCount) {
974 				lbaRangeCount = maxLBARangeCount;
975 				break;
976 			}
977 		}
978 		if (lbaRangeCount == 0)
979 			break;
980 
981 		uint32 lbaRangesSize = lbaRangeCount * sizeof(uint64);
982 		uint64* lbaRanges = (uint64*)malloc(lbaRangesSize);
983 		if (lbaRanges == NULL) {
984 			ERROR("out of memory when allocating %" B_PRIu32 " unmap ranges\n",
985 				lbaRangeCount);
986 			request->subsys_status = SCSI_REQ_ABORTED;
987 			gSCSI->finished(request, 1);
988 			return;
989 		}
990 
991 		MemoryDeleter deleter(lbaRanges);
992 
993 		for (uint32 lbaIndex = 0;
994 				scsiIndex < scsiRangeCount && lbaIndex < lbaRangeCount;) {
995 			uint64 scsiOffset = B_BENDIAN_TO_HOST_INT64(
996 				unmapBlocks->blocks[scsiIndex].lba) + scsiLastBlocks;
997 			uint32 scsiBlocksLeft = B_BENDIAN_TO_HOST_INT32(
998 				unmapBlocks->blocks[scsiIndex].block_count) - scsiLastBlocks;
999 
1000 			if (scsiBlocksLeft == 0) {
1001 				// Ignore the rest of the ranges (they are empty)
1002 				scsiIndex = scsiRangeCount;
1003 				break;
1004 			}
1005 
1006 			while (scsiBlocksLeft > 0 && lbaIndex < lbaRangeCount) {
1007 				uint16 blocks = scsiBlocksLeft > 65535
1008 					? 65535 : (uint16)scsiBlocksLeft;
1009 				lbaRanges[lbaIndex++] = B_HOST_TO_LENDIAN_INT64(
1010 					((uint64)blocks << 48) | scsiOffset);
1011 
1012 				scsiOffset += blocks;
1013 				scsiLastBlocks += blocks;
1014 				scsiBlocksLeft -= blocks;
1015 			}
1016 
1017 			if (scsiBlocksLeft == 0) {
1018 				scsiLastBlocks = 0;
1019 				scsiIndex++;
1020 			}
1021 		}
1022 
1023 dprintf("TRIM AHCI:\n");
1024 for (uint32 i = 0; i < lbaRangeCount; i++) {
1025 	uint64 value = B_HOST_TO_LENDIAN_INT64(lbaRanges[i]);
1026 	dprintf("[%3" B_PRIu32 "] %" B_PRIu64 " : %" B_PRIu64 "\n", i,
1027 		value & (((uint64)1 << 48) - 1), value >> 48);
1028 }
1029 
1030 		sata_request sreq;
1031 		sreq.SetATA48Command(ATA_COMMAND_DATA_SET_MANAGEMENT, 0,
1032 			(lbaRangesSize + 511) / 512);
1033 		sreq.SetFeature(1);
1034 		sreq.SetData(lbaRanges, lbaRangesSize);
1035 
1036 		ExecuteSataRequest(&sreq);
1037 		sreq.WaitForCompletion();
1038 
1039 		if ((sreq.CompletionStatus() & ATA_STATUS_ERROR) != 0) {
1040 			ERROR("trim failed (%" B_PRIu32 " ranges)!\n", lbaRangeCount);
1041 			request->subsys_status = SCSI_REQ_CMP_ERR;
1042 		} else
1043 			request->subsys_status = SCSI_REQ_CMP;
1044 	}
1045 
1046 	request->data_resid = 0;
1047 	request->device_status = SCSI_STATUS_GOOD;
1048 	gSCSI->finished(request, 1);
1049 }
1050 
1051 
1052 void
1053 AHCIPort::ExecuteSataRequest(sata_request* request, bool isWrite)
1054 {
1055 	FLOW("ExecuteAtaRequest port %d\n", fIndex);
1056 
1057 	StartTransfer();
1058 
1059 	int prdEntrys;
1060 
1061 	if (request->CCB() && request->CCB()->data_length) {
1062 		FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT,
1063 			request->CCB()->sg_list, request->CCB()->sg_count,
1064 			request->CCB()->data_length);
1065 	} else if (request->Data() && request->Size()) {
1066 		FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT,
1067 			request->Data(), request->Size());
1068 	} else
1069 		prdEntrys = 0;
1070 
1071 	FLOW("prdEntrys %d\n", prdEntrys);
1072 
1073 	fCommandList->prdtl_flags_cfl = 0;
1074 	fCommandList->cfl = 5; // 20 bytes, length in DWORDS
1075 	memcpy((char*)fCommandTable->cfis, request->FIS(), 20);
1076 
1077 	// We some hide messages when the test unit ready active is clear
1078 	// as empty removeable media resets constantly.
1079 	fTestUnitReadyActive = request->IsTestUnitReady();
1080 
1081 	if (request->IsATAPI()) {
1082 		// ATAPI PACKET is a 12 or 16 byte SCSI command
1083 		memset((char*)fCommandTable->acmd, 0, 32);
1084 		memcpy((char*)fCommandTable->acmd, request->CCB()->cdb,
1085 			request->CCB()->cdb_length);
1086 		fCommandList->a = 1;
1087 	}
1088 
1089 	if (isWrite)
1090 		fCommandList->w = 1;
1091 	fCommandList->prdtl = prdEntrys;
1092 	fCommandList->prdbc = 0;
1093 
1094 	if (wait_until_clear(&fRegs->tfd, ATA_STATUS_BUSY | ATA_STATUS_DATA_REQUEST,
1095 			1000000) < B_OK) {
1096 		ERROR("ExecuteAtaRequest port %d: device is busy\n", fIndex);
1097 		PortReset();
1098 		FinishTransfer();
1099 		request->Abort();
1100 		return;
1101 	}
1102 
1103 	cpu_status cpu = disable_interrupts();
1104 	acquire_spinlock(&fSpinlock);
1105 	fCommandsActive |= 1;
1106 	fRegs->ci = 1;
1107 	FlushPostedWrites();
1108 	release_spinlock(&fSpinlock);
1109 	restore_interrupts(cpu);
1110 
1111 	int tfd;
1112 	status_t status = WaitForTransfer(&tfd, 20000000);
1113 
1114 	FLOW("Port %d sata request flow:\n", fIndex);
1115 	FLOW("  tfd %#x\n", tfd);
1116 	FLOW("  prdbc %ld\n", fCommandList->prdbc);
1117 	FLOW("  ci   0x%08" B_PRIx32 "\n", fRegs->ci);
1118 	FLOW("  is   0x%08" B_PRIx32 "\n", fRegs->is);
1119 	FLOW("  serr 0x%08" B_PRIx32 "\n", fRegs->serr);
1120 
1121 /*
1122 	TRACE("ci   0x%08" B_PRIx32 "\n", fRegs->ci);
1123 	TRACE("ie   0x%08" B_PRIx32 "\n", fRegs->ie);
1124 	TRACE("is   0x%08" B_PRIx32 "\n", fRegs->is);
1125 	TRACE("cmd  0x%08" B_PRIx32 "\n", fRegs->cmd);
1126 	TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
1127 	TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl);
1128 	TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr);
1129 	TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact);
1130 	TRACE("tfd  0x%08" B_PRIx32 "\n", fRegs->tfd);
1131 */
1132 
1133 	if (fPortReset || status == B_TIMED_OUT) {
1134 		fPortReset = false;
1135 		PortReset();
1136 	}
1137 
1138 	size_t bytesTransfered = fCommandList->prdbc;
1139 
1140 	FinishTransfer();
1141 
1142 	if (status == B_TIMED_OUT) {
1143 		ERROR("ExecuteAtaRequest port %d: device timeout\n", fIndex);
1144 		request->Abort();
1145 		return;
1146 	}
1147 
1148 	request->Finish(tfd, bytesTransfered);
1149 }
1150 
1151 
1152 void
1153 AHCIPort::ScsiExecuteRequest(scsi_ccb* request)
1154 {
1155 //	TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
1156 
1157 	if (fIsATAPI) {
1158 		bool isWrite = false;
1159 		switch (request->flags & SCSI_DIR_MASK) {
1160 			case SCSI_DIR_NONE:
1161 				ASSERT(request->data_length == 0);
1162 				break;
1163 			case SCSI_DIR_IN:
1164 				break;
1165 			case SCSI_DIR_OUT:
1166 				isWrite = true;
1167 				ASSERT(request->data_length > 0);
1168 				break;
1169 			default:
1170 				panic("CDB has invalid direction mask");
1171 		}
1172 
1173 //		TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
1174 
1175 		sata_request* sreq = new(std::nothrow) sata_request(request);
1176 		if (sreq == NULL) {
1177 			ERROR("out of memory when allocating atapi request\n");
1178 			request->subsys_status = SCSI_REQ_ABORTED;
1179 			gSCSI->finished(request, 1);
1180 			return;
1181 		}
1182 
1183 		sreq->SetATAPICommand(request->data_length);
1184 //		uint8* data = (uint8*) sreq->ccb()->cdb;
1185 //		for (int i = 0; i < 16; i += 8) {
1186 //			TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]);
1187 //		}
1188 		ExecuteSataRequest(sreq, isWrite);
1189 		return;
1190 	}
1191 
1192 	if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) {
1193 		panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n");
1194 		return;
1195 	}
1196 
1197 	if (!fDevicePresent) {
1198 		TRACE("no device present on port %d\n", fIndex);
1199 		request->subsys_status = SCSI_DEV_NOT_THERE;
1200 		gSCSI->finished(request, 1);
1201 		return;
1202 	}
1203 
1204 	request->subsys_status = SCSI_REQ_CMP;
1205 
1206 	switch (request->cdb[0]) {
1207 		case SCSI_OP_TEST_UNIT_READY:
1208 			ScsiTestUnitReady(request);
1209 			break;
1210 		case SCSI_OP_INQUIRY:
1211 			ScsiInquiry(request);
1212 			break;
1213 		case SCSI_OP_READ_CAPACITY:
1214 			ScsiReadCapacity(request);
1215 			break;
1216 		case SCSI_OP_SERVICE_ACTION_IN:
1217 			if ((request->cdb[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16)
1218 				ScsiReadCapacity16(request);
1219 			else {
1220 				request->subsys_status = SCSI_REQ_INVALID;
1221 				gSCSI->finished(request, 1);
1222 			}
1223 			break;
1224 		case SCSI_OP_SYNCHRONIZE_CACHE:
1225 			ScsiSynchronizeCache(request);
1226 			break;
1227 		case SCSI_OP_READ_6:
1228 		case SCSI_OP_WRITE_6:
1229 		{
1230 			const scsi_cmd_rw_6* cmd = (const scsi_cmd_rw_6*)request->cdb;
1231 			uint32 position = ((uint32)cmd->high_lba << 16)
1232 				| ((uint32)cmd->mid_lba << 8) | (uint32)cmd->low_lba;
1233 			size_t length = cmd->length != 0 ? cmd->length : 256;
1234 			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_6;
1235 			ScsiReadWrite(request, position, length, isWrite);
1236 			break;
1237 		}
1238 		case SCSI_OP_READ_10:
1239 		case SCSI_OP_WRITE_10:
1240 		{
1241 			const scsi_cmd_rw_10* cmd = (const scsi_cmd_rw_10*)request->cdb;
1242 			uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
1243 			size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length);
1244 			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10;
1245 			if (length) {
1246 				ScsiReadWrite(request, position, length, isWrite);
1247 			} else {
1248 				ERROR("AHCIPort::ScsiExecuteRequest error: transfer without "
1249 					"data!\n");
1250 				request->subsys_status = SCSI_REQ_INVALID;
1251 				gSCSI->finished(request, 1);
1252 			}
1253 			break;
1254 		}
1255 		case SCSI_OP_READ_12:
1256 		case SCSI_OP_WRITE_12:
1257 		{
1258 			const scsi_cmd_rw_12* cmd = (const scsi_cmd_rw_12*)request->cdb;
1259 			uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
1260 			size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
1261 			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12;
1262 			if (length) {
1263 				ScsiReadWrite(request, position, length, isWrite);
1264 			} else {
1265 				ERROR("AHCIPort::ScsiExecuteRequest error: transfer without "
1266 					"data!\n");
1267 				request->subsys_status = SCSI_REQ_INVALID;
1268 				gSCSI->finished(request, 1);
1269 			}
1270 			break;
1271 		}
1272 		case SCSI_OP_READ_16:
1273 		case SCSI_OP_WRITE_16:
1274 		{
1275 			const scsi_cmd_rw_16* cmd = (const scsi_cmd_rw_16*)request->cdb;
1276 			uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba);
1277 			size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
1278 			bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16;
1279 			if (length) {
1280 				ScsiReadWrite(request, position, length, isWrite);
1281 			} else {
1282 				ERROR("AHCIPort::ScsiExecuteRequest error: transfer without "
1283 					"data!\n");
1284 				request->subsys_status = SCSI_REQ_INVALID;
1285 				gSCSI->finished(request, 1);
1286 			}
1287 			break;
1288 		}
1289 		case SCSI_OP_UNMAP:
1290 		{
1291 			const scsi_cmd_unmap* cmd = (const scsi_cmd_unmap*)request->cdb;
1292 
1293 			if (!fTrimSupported) {
1294 				ERROR("%s port %d: unsupported request opcode 0x%02x\n",
1295 					__func__, fIndex, request->cdb[0]);
1296 				request->subsys_status = SCSI_REQ_ABORTED;
1297 				gSCSI->finished(request, 1);
1298 				break;
1299 			}
1300 
1301 			scsi_unmap_parameter_list* unmapBlocks
1302 				= (scsi_unmap_parameter_list*)request->data;
1303 			if (unmapBlocks == NULL
1304 				|| B_BENDIAN_TO_HOST_INT16(cmd->length) != request->data_length
1305 				|| B_BENDIAN_TO_HOST_INT16(unmapBlocks->data_length)
1306 					!= request->data_length - 1) {
1307 				ERROR("%s port %d: invalid unmap parameter data length\n",
1308 					__func__, fIndex);
1309 				request->subsys_status = SCSI_REQ_ABORTED;
1310 				gSCSI->finished(request, 1);
1311 			} else {
1312 				ScsiUnmap(request, unmapBlocks);
1313 			}
1314 			break;
1315 		}
1316 		default:
1317 			ERROR("AHCIPort::ScsiExecuteRequest port %d unsupported request "
1318 				"opcode 0x%02x\n", fIndex, request->cdb[0]);
1319 			request->subsys_status = SCSI_REQ_ABORTED;
1320 			gSCSI->finished(request, 1);
1321 	}
1322 }
1323 
1324 
1325 uchar
1326 AHCIPort::ScsiAbortRequest(scsi_ccb* request)
1327 {
1328 	return SCSI_REQ_CMP;
1329 }
1330 
1331 
1332 uchar
1333 AHCIPort::ScsiTerminateRequest(scsi_ccb* request)
1334 {
1335 	return SCSI_REQ_CMP;
1336 }
1337 
1338 
1339 uchar
1340 AHCIPort::ScsiResetDevice()
1341 {
1342 	return SCSI_REQ_CMP;
1343 }
1344 
1345 
1346 void
1347 AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense,
1348 	uint32* maxBlocks)
1349 {
1350 	*isATAPI = fIsATAPI;
1351 	*noAutoSense = fIsATAPI; // emulated auto sense for ATA, but not ATAPI
1352 	*maxBlocks = fUse48BitCommands ? 65536 : 256;
1353 	TRACE("AHCIPort::ScsiGetRestrictions port %d: isATAPI %d, noAutoSense %d, "
1354 		"maxBlocks %" B_PRIu32 "\n", fIndex, *isATAPI, *noAutoSense,
1355 		*maxBlocks);
1356 }
1357 
1358 
1359 bool
1360 AHCIPort::Enable()
1361 {
1362 	// Spec v1.3.1, §10.3.1 Start (PxCMD.ST)
1363 	TRACE("%s: port %d\n", __func__, fIndex);
1364 
1365 	if ((fRegs->cmd & PORT_CMD_ST) != 0) {
1366 		ERROR("%s: Starting port already running!\n", __func__);
1367 		return false;
1368 	}
1369 
1370 	if ((fRegs->cmd & PORT_CMD_FRE) == 0) {
1371 		ERROR("%s: Unable to start port without FRE enabled!\n", __func__);
1372 		return false;
1373 	}
1374 
1375 	// Clear DMA engine and wait for completion
1376 	if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) {
1377 		ERROR("%s: port %d error DMA engine still running\n", __func__,
1378 			fIndex);
1379 		return false;
1380 	}
1381 	// Start port
1382 	fRegs->cmd |= PORT_CMD_ST;
1383 	FlushPostedWrites();
1384 	return true;
1385 }
1386 
1387 
1388 bool
1389 AHCIPort::Disable()
1390 {
1391 	TRACE("%s: port %d\n", __func__, fIndex);
1392 
1393 	if ((fRegs->cmd & PORT_CMD_ST) == 0) {
1394 		// Port already disabled, carry on.
1395 		TRACE("%s: port %d attempting to disable stopped port.\n",
1396 			__func__, fIndex);
1397 	} else {
1398 		// Disable port
1399 		fRegs->cmd &= ~PORT_CMD_ST;
1400 		FlushPostedWrites();
1401 	}
1402 
1403 	// Spec v1.3.1, §10.4.2 Port Reset - assume hung after 500 mil.
1404 	// Clear DMA engine and wait for completion
1405 	if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) {
1406 		ERROR("%s: port %d error DMA engine still running\n", __func__,
1407 			fIndex);
1408 		return false;
1409 	}
1410 
1411 	return true;
1412 }
1413 
1414 
1415 void
1416 AHCIPort::_ClearErrorRegister()
1417 {
1418 	// clear error bits
1419 	fRegs->serr = fRegs->serr;
1420 	FlushPostedWrites();
1421 }
1422