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
47AHCIPort::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
72AHCIPort::~AHCIPort()
73{
74	delete_sem(fRequestSem);
75	delete_sem(fResponseSem);
76}
77
78
79status_t
80AHCIPort::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
147status_t
148AHCIPort::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
172void
173AHCIPort::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
207void
208AHCIPort::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
232status_t
233AHCIPort::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
275status_t
276AHCIPort::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
323void
324AHCIPort::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
340void
341AHCIPort::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
355void
356AHCIPort::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
381void
382AHCIPort::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
455status_t
456AHCIPort::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
475status_t
476AHCIPort::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
525void
526AHCIPort::StartTransfer()
527{
528	acquire_sem(fRequestSem);
529}
530
531
532status_t
533AHCIPort::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
556void
557AHCIPort::FinishTransfer()
558{
559	release_sem(fRequestSem);
560}
561
562
563void
564AHCIPort::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
572void
573AHCIPort::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
635void
636AHCIPort::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
804void
805AHCIPort::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
823void
824AHCIPort::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
860void
861AHCIPort::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
884void
885AHCIPort::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
936void
937AHCIPort::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
943dprintf("TRIM SCSI:\n");
944for (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
1020dprintf("TRIM AHCI:\n");
1021for (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
1049void
1050AHCIPort::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
1149void
1150AHCIPort::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
1323uchar
1324AHCIPort::ScsiAbortRequest(scsi_ccb* request)
1325{
1326	return SCSI_REQ_CMP;
1327}
1328
1329
1330uchar
1331AHCIPort::ScsiTerminateRequest(scsi_ccb* request)
1332{
1333	return SCSI_REQ_CMP;
1334}
1335
1336
1337uchar
1338AHCIPort::ScsiResetDevice()
1339{
1340	return SCSI_REQ_CMP;
1341}
1342
1343
1344void
1345AHCIPort::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
1357bool
1358AHCIPort::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
1386bool
1387AHCIPort::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
1413void
1414AHCIPort::_ClearErrorRegister()
1415{
1416	// clear error bits
1417	fRegs->serr = fRegs->serr;
1418	FlushPostedWrites();
1419}
1420