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