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