VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DevAHCI.cpp@ 64664

Last change on this file since 64664 was 64660, checked in by vboxsync, 8 years ago

pdmstorageifs.h,AHCI,NVMe,LsiLogic,BusLogic,DrvSCSI: Prepare for a new callback in PDMIMEDIAEXPORT which can reduce the overhead of copying data between buffers under certain circumstances

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 233.7 KB
Line 
1/* $Id: DevAHCI.cpp 64660 2016-11-14 14:40:34Z vboxsync $ */
2/** @file
3 * DevAHCI - AHCI controller device (disk and cdrom).
4 *
5 * Implements the AHCI standard 1.1
6 */
7
8/*
9 * Copyright (C) 2006-2016 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/** @page pg_dev_ahci AHCI - Advanced Host Controller Interface Emulation.
21 *
22 * This component implements an AHCI serial ATA controller. The device is split
23 * into two parts. The first part implements the register interface for the
24 * guest and the second one does the data transfer.
25 *
26 * The guest can access the controller in two ways. The first one is the native
27 * way implementing the registers described in the AHCI specification and is
28 * the preferred one. The second implements the I/O ports used for booting from
29 * the hard disk and for guests which don't have an AHCI SATA driver.
30 *
31 * The data is transfered using the extended media interface, asynchronously if
32 * it is supported by the driver below otherwise it weill be done synchronous.
33 * Either way a thread is used to process new requests from the guest.
34 */
35
36
37/*********************************************************************************************************************************
38* Header Files *
39*********************************************************************************************************************************/
40#define LOG_GROUP LOG_GROUP_DEV_AHCI
41#include <VBox/vmm/pdmdev.h>
42#include <VBox/vmm/pdmstorageifs.h>
43#include <VBox/vmm/pdmqueue.h>
44#include <VBox/vmm/pdmthread.h>
45#include <VBox/vmm/pdmcritsect.h>
46#include <VBox/sup.h>
47#include <VBox/scsi.h>
48#include <iprt/assert.h>
49#include <iprt/asm.h>
50#include <iprt/string.h>
51#include <iprt/list.h>
52#ifdef IN_RING3
53# include <iprt/param.h>
54# include <iprt/thread.h>
55# include <iprt/semaphore.h>
56# include <iprt/alloc.h>
57# include <iprt/uuid.h>
58# include <iprt/time.h>
59#endif
60#include "PIIX3ATABmDma.h"
61#include "ide.h"
62#include "VBoxDD.h"
63
64#if defined(VBOX_WITH_DTRACE) \
65 && defined(IN_RING3) \
66 && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
67# include "dtrace/VBoxDD.h"
68#else
69# define VBOXDD_AHCI_REQ_SUBMIT(a,b,c,d) do { } while (0)
70# define VBOXDD_AHCI_REQ_COMPLETED(a,b,c,d) do { } while (0)
71#endif
72
73/** Maximum number of ports available.
74 * Spec defines 32 but we have one allocated for command completion coalescing
75 * and another for a reserved future feature.
76 */
77#define AHCI_MAX_NR_PORTS_IMPL 30
78/** Maximum number of command slots available. */
79#define AHCI_NR_COMMAND_SLOTS 32
80
81/** The current saved state version. */
82#define AHCI_SAVED_STATE_VERSION 9
83/** The saved state version before the ATAPI emulation was removed and the generic SCSI driver was used. */
84#define AHCI_SAVED_STATE_VERSION_PRE_ATAPI_REMOVE 8
85/** The saved state version before changing the port reset logic in an incompatible way. */
86#define AHCI_SAVED_STATE_VERSION_PRE_PORT_RESET_CHANGES 7
87/** Saved state version before the per port hotplug port was added. */
88#define AHCI_SAVED_STATE_VERSION_PRE_HOTPLUG_FLAG 6
89/** Saved state version before legacy ATA emulation was dropped. */
90#define AHCI_SAVED_STATE_VERSION_IDE_EMULATION 5
91/** Saved state version before ATAPI support was added. */
92#define AHCI_SAVED_STATE_VERSION_PRE_ATAPI 3
93/** The saved state version use in VirtualBox 3.0 and earlier.
94 * This was before the config was added and ahciIOTasks was dropped. */
95#define AHCI_SAVED_STATE_VERSION_VBOX_30 2
96/* for Older ATA state Read handling */
97#define ATA_CTL_SAVED_STATE_VERSION 3
98#define ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE 1
99#define ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS 2
100
101/** The maximum number of release log entries per device. */
102#define MAX_LOG_REL_ERRORS 1024
103
104/**
105 * Maximum number of sectors to transfer in a READ/WRITE MULTIPLE request.
106 * Set to 1 to disable multi-sector read support. According to the ATA
107 * specification this must be a power of 2 and it must fit in an 8 bit
108 * value. Thus the only valid values are 1, 2, 4, 8, 16, 32, 64 and 128.
109 */
110#define ATA_MAX_MULT_SECTORS 128
111
112/**
113 * Fastest PIO mode supported by the drive.
114 */
115#define ATA_PIO_MODE_MAX 4
116/**
117 * Fastest MDMA mode supported by the drive.
118 */
119#define ATA_MDMA_MODE_MAX 2
120/**
121 * Fastest UDMA mode supported by the drive.
122 */
123#define ATA_UDMA_MODE_MAX 6
124
125/**
126 * Length of the configurable VPD data (without termination)
127 */
128#define AHCI_SERIAL_NUMBER_LENGTH 20
129#define AHCI_FIRMWARE_REVISION_LENGTH 8
130#define AHCI_MODEL_NUMBER_LENGTH 40
131
132/** ATAPI sense info size. */
133#define ATAPI_SENSE_SIZE 64
134
135/**
136 * Command Header.
137 */
138#pragma pack(1)
139typedef struct
140{
141 /** Description Information. */
142 uint32_t u32DescInf;
143 /** Command status. */
144 uint32_t u32PRDBC;
145 /** Command Table Base Address. */
146 uint32_t u32CmdTblAddr;
147 /** Command Table Base Address - upper 32-bits. */
148 uint32_t u32CmdTblAddrUp;
149 /** Reserved */
150 uint32_t u32Reserved[4];
151} CmdHdr;
152#pragma pack()
153AssertCompileSize(CmdHdr, 32);
154
155/* Defines for the command header. */
156#define AHCI_CMDHDR_PRDTL_MASK 0xffff0000
157#define AHCI_CMDHDR_PRDTL_ENTRIES(x) ((x & AHCI_CMDHDR_PRDTL_MASK) >> 16)
158#define AHCI_CMDHDR_C RT_BIT(10)
159#define AHCI_CMDHDR_B RT_BIT(9)
160#define AHCI_CMDHDR_R RT_BIT(8)
161#define AHCI_CMDHDR_P RT_BIT(7)
162#define AHCI_CMDHDR_W RT_BIT(6)
163#define AHCI_CMDHDR_A RT_BIT(5)
164#define AHCI_CMDHDR_CFL_MASK 0x1f
165
166#define AHCI_CMDHDR_PRDT_OFFSET 0x80
167#define AHCI_CMDHDR_ACMD_OFFSET 0x40
168
169/* Defines for the command FIS. */
170/* Defines that are used in the first double word. */
171#define AHCI_CMDFIS_TYPE 0 /* The first byte. */
172# define AHCI_CMDFIS_TYPE_H2D 0x27 /* Register - Host to Device FIS. */
173# define AHCI_CMDFIS_TYPE_H2D_SIZE 20 /* Five double words. */
174# define AHCI_CMDFIS_TYPE_D2H 0x34 /* Register - Device to Host FIS. */
175# define AHCI_CMDFIS_TYPE_D2H_SIZE 20 /* Five double words. */
176# define AHCI_CMDFIS_TYPE_SETDEVBITS 0xa1 /* Set Device Bits - Device to Host FIS. */
177# define AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE 8 /* Two double words. */
178# define AHCI_CMDFIS_TYPE_DMAACTD2H 0x39 /* DMA Activate - Device to Host FIS. */
179# define AHCI_CMDFIS_TYPE_DMAACTD2H_SIZE 4 /* One double word. */
180# define AHCI_CMDFIS_TYPE_DMASETUP 0x41 /* DMA Setup - Bidirectional FIS. */
181# define AHCI_CMDFIS_TYPE_DMASETUP_SIZE 28 /* Seven double words. */
182# define AHCI_CMDFIS_TYPE_PIOSETUP 0x5f /* PIO Setup - Device to Host FIS. */
183# define AHCI_CMDFIS_TYPE_PIOSETUP_SIZE 20 /* Five double words. */
184# define AHCI_CMDFIS_TYPE_DATA 0x46 /* Data - Bidirectional FIS. */
185
186#define AHCI_CMDFIS_BITS 1 /* Interrupt and Update bit. */
187#define AHCI_CMDFIS_C RT_BIT(7) /* Host to device. */
188#define AHCI_CMDFIS_I RT_BIT(6) /* Device to Host. */
189#define AHCI_CMDFIS_D RT_BIT(5)
190
191#define AHCI_CMDFIS_CMD 2
192#define AHCI_CMDFIS_FET 3
193
194#define AHCI_CMDFIS_SECTN 4
195#define AHCI_CMDFIS_CYLL 5
196#define AHCI_CMDFIS_CYLH 6
197#define AHCI_CMDFIS_HEAD 7
198
199#define AHCI_CMDFIS_SECTNEXP 8
200#define AHCI_CMDFIS_CYLLEXP 9
201#define AHCI_CMDFIS_CYLHEXP 10
202#define AHCI_CMDFIS_FETEXP 11
203
204#define AHCI_CMDFIS_SECTC 12
205#define AHCI_CMDFIS_SECTCEXP 13
206#define AHCI_CMDFIS_CTL 15
207# define AHCI_CMDFIS_CTL_SRST RT_BIT(2) /* Reset device. */
208# define AHCI_CMDFIS_CTL_NIEN RT_BIT(1) /* Assert or clear interrupt. */
209
210/* For D2H FIS */
211#define AHCI_CMDFIS_STS 2
212#define AHCI_CMDFIS_ERR 3
213
214/** Pointer to a task state. */
215typedef struct AHCIREQ *PAHCIREQ;
216
217/** Task encountered a buffer overflow. */
218#define AHCI_REQ_OVERFLOW RT_BIT_32(0)
219/** Request is a PIO data command, if this flag is not set it either is
220 * a command which does not transfer data or a DMA command based on the transfer size. */
221#define AHCI_REQ_PIO_DATA RT_BIT_32(1)
222/** The request has the SACT register set. */
223#define AHCI_REQ_CLEAR_SACT RT_BIT_32(2)
224/** Flag whether the request is queued. */
225#define AHCI_REQ_IS_QUEUED RT_BIT_32(3)
226/** Flag whether the request is stored on the stack. */
227#define AHCI_REQ_IS_ON_STACK RT_BIT_32(4)
228/** Flag whether this request transfers data from the device to the HBA or
229 * the other way around .*/
230#define AHCI_REQ_XFER_2_HOST RT_BIT_32(5)
231
232/**
233 * A task state.
234 */
235typedef struct AHCIREQ
236{
237 /** The I/O request handle from the driver below associated with this request. */
238 PDMMEDIAEXIOREQ hIoReq;
239 /** Tag of the task. */
240 uint32_t uTag;
241 /** The command Fis for this task. */
242 uint8_t cmdFis[AHCI_CMDFIS_TYPE_H2D_SIZE];
243 /** The ATAPI command data. */
244 uint8_t aATAPICmd[ATAPI_PACKET_SIZE];
245 /** Size of one sector for the ATAPI transfer. */
246 uint32_t cbATAPISector;
247 /** Physical address of the command header. - GC */
248 RTGCPHYS GCPhysCmdHdrAddr;
249 /** Physical address of the PRDT */
250 RTGCPHYS GCPhysPrdtl;
251 /** Number of entries in the PRDTL. */
252 unsigned cPrdtlEntries;
253 /** Data direction. */
254 PDMMEDIAEXIOREQTYPE enmType;
255 /** Start offset. */
256 uint64_t uOffset;
257 /** Number of bytes to transfer. */
258 size_t cbTransfer;
259 /** Flags for this task. */
260 uint32_t fFlags;
261 /** SCSI status code. */
262 uint8_t u8ScsiSts;
263} AHCIREQ;
264
265/**
266 * Notifier queue item.
267 */
268typedef struct DEVPORTNOTIFIERQUEUEITEM
269{
270 /** The core part owned by the queue manager. */
271 PDMQUEUEITEMCORE Core;
272 /** The port to process. */
273 uint8_t iPort;
274} DEVPORTNOTIFIERQUEUEITEM, *PDEVPORTNOTIFIERQUEUEITEM;
275
276
277/**
278 * @implements PDMIBASE
279 * @implements PDMIMEDIAPORT
280 * @implements PDMIMEDIAEXPORT
281 */
282typedef struct AHCIPort
283{
284 /** Pointer to the device instance - HC ptr */
285 PPDMDEVINSR3 pDevInsR3;
286 /** Pointer to the device instance - R0 ptr */
287 PPDMDEVINSR0 pDevInsR0;
288 /** Pointer to the device instance - RC ptr. */
289 PPDMDEVINSRC pDevInsRC;
290
291#if HC_ARCH_BITS == 64
292 uint32_t Alignment0;
293#endif
294
295 /** Pointer to the parent AHCI structure - R3 ptr. */
296 R3PTRTYPE(struct AHCI *) pAhciR3;
297 /** Pointer to the parent AHCI structure - R0 ptr. */
298 R0PTRTYPE(struct AHCI *) pAhciR0;
299 /** Pointer to the parent AHCI structure - RC ptr. */
300 RCPTRTYPE(struct AHCI *) pAhciRC;
301
302 /** Command List Base Address. */
303 uint32_t regCLB;
304 /** Command List Base Address upper bits. */
305 uint32_t regCLBU;
306 /** FIS Base Address. */
307 uint32_t regFB;
308 /** FIS Base Address upper bits. */
309 uint32_t regFBU;
310 /** Interrupt Status. */
311 volatile uint32_t regIS;
312 /** Interrupt Enable. */
313 uint32_t regIE;
314 /** Command. */
315 uint32_t regCMD;
316 /** Task File Data. */
317 uint32_t regTFD;
318 /** Signature */
319 uint32_t regSIG;
320 /** Serial ATA Status. */
321 uint32_t regSSTS;
322 /** Serial ATA Control. */
323 uint32_t regSCTL;
324 /** Serial ATA Error. */
325 uint32_t regSERR;
326 /** Serial ATA Active. */
327 volatile uint32_t regSACT;
328 /** Command Issue. */
329 uint32_t regCI;
330
331 /** Current number of active tasks. */
332 volatile uint32_t cTasksActive;
333 /** Command List Base Address */
334 volatile RTGCPHYS GCPhysAddrClb;
335 /** FIS Base Address */
336 volatile RTGCPHYS GCPhysAddrFb;
337
338 /** Device is powered on. */
339 bool fPoweredOn;
340 /** Device has spun up. */
341 bool fSpunUp;
342 /** First D2H FIS was send. */
343 bool fFirstD2HFisSend;
344 /** Attached device is a CD/DVD drive. */
345 bool fATAPI;
346 /** Flag whether this port is in a reset state. */
347 volatile bool fPortReset;
348 /** Flag whether TRIM is supported. */
349 bool fTrimEnabled;
350 /** Flag if we are in a device reset. */
351 bool fResetDevice;
352 /** Flag whether this port is hot plug capable. */
353 bool fHotpluggable;
354 /** Flag whether the port is in redo task mode. */
355 volatile bool fRedo;
356 /** Flag whether the worker thread is sleeping. */
357 volatile bool fWrkThreadSleeping;
358
359 bool afAlignment[4];
360
361 /** Number of total sectors. */
362 uint64_t cTotalSectors;
363 /** Size of one sector. */
364 uint32_t cbSector;
365 /** Currently configured number of sectors in a multi-sector transfer. */
366 uint32_t cMultSectors;
367 /** Currently active transfer mode (MDMA/UDMA) and speed. */
368 uint8_t uATATransferMode;
369 /** ATAPI sense data. */
370 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
371 /** Exponent of logical sectors in a physical sector, number of logical sectors is 2^exp. */
372 uint8_t cLogSectorsPerPhysicalExp;
373 /** The LUN. */
374 RTUINT iLUN;
375
376 /** Bitmap for finished tasks (R3 -> Guest). */
377 volatile uint32_t u32TasksFinished;
378 /** Bitmap for finished queued tasks (R3 -> Guest). */
379 volatile uint32_t u32QueuedTasksFinished;
380 /** Bitmap for new queued tasks (Guest -> R3). */
381 volatile uint32_t u32TasksNew;
382 /** Bitmap of tasks which must be redone because of a non fatal error. */
383 volatile uint32_t u32TasksRedo;
384
385 /** Current command slot processed.
386 * Accessed by the guest by reading the CMD register.
387 * Holds the command slot of the command processed at the moment. */
388 volatile uint32_t u32CurrentCommandSlot;
389
390#if HC_ARCH_BITS == 64
391 uint32_t u32Alignment2;
392#endif
393
394 /** Device specific settings (R3 only stuff). */
395 /** Pointer to the attached driver's base interface. */
396 R3PTRTYPE(PPDMIBASE) pDrvBase;
397 /** Pointer to the attached driver's block interface. */
398 R3PTRTYPE(PPDMIMEDIA) pDrvMedia;
399 /** Pointer to the attached driver's extended interface. */
400 R3PTRTYPE(PPDMIMEDIAEX) pDrvMediaEx;
401 /** The base interface. */
402 PDMIBASE IBase;
403 /** The block port interface. */
404 PDMIMEDIAPORT IPort;
405 /** The extended media port interface. */
406 PDMIMEDIAEXPORT IMediaExPort;
407 /** Physical geometry of this image. */
408 PDMMEDIAGEOMETRY PCHSGeometry;
409 /** The status LED state for this drive. */
410 PDMLED Led;
411
412#if HC_ARCH_BITS == 64
413 uint32_t u32Alignment3;
414#endif
415
416 /** Async IO Thread. */
417 R3PTRTYPE(PPDMTHREAD) pAsyncIOThread;
418 /** First task throwing an error. */
419 R3PTRTYPE(volatile PAHCIREQ) pTaskErr;
420
421 /** The event semaphore the processing thread waits on. */
422 SUPSEMEVENT hEvtProcess;
423
424 /** Release statistics: number of DMA commands. */
425 STAMCOUNTER StatDMA;
426 /** Release statistics: number of bytes written. */
427 STAMCOUNTER StatBytesWritten;
428 /** Release statistics: number of bytes read. */
429 STAMCOUNTER StatBytesRead;
430 /** Release statistics: Number of I/O requests processed per second. */
431 STAMCOUNTER StatIORequestsPerSecond;
432#ifdef VBOX_WITH_STATISTICS
433 /** Statistics: Time to complete one request. */
434 STAMPROFILE StatProfileProcessTime;
435 /** Statistics: Amount of time to read/write data. */
436 STAMPROFILE StatProfileReadWrite;
437#endif /* VBOX_WITH_STATISTICS */
438
439 /** The serial numnber to use for IDENTIFY DEVICE commands. */
440 char szSerialNumber[AHCI_SERIAL_NUMBER_LENGTH+1]; /** < one extra byte for termination */
441 /** The firmware revision to use for IDENTIFY DEVICE commands. */
442 char szFirmwareRevision[AHCI_FIRMWARE_REVISION_LENGTH+1]; /** < one extra byte for termination */
443 /** The model number to use for IDENTIFY DEVICE commands. */
444 char szModelNumber[AHCI_MODEL_NUMBER_LENGTH+1]; /** < one extra byte for termination */
445 /** Error counter */
446 uint32_t cErrors;
447
448 uint32_t u32Alignment5;
449
450} AHCIPort;
451/** Pointer to the state of an AHCI port. */
452typedef AHCIPort *PAHCIPort;
453
454AssertCompileMemberAlignment(AHCIPort, StatDMA, 8);
455AssertCompileSizeAlignment(AHCIPort, 8);
456
457/**
458 * Main AHCI device state.
459 *
460 * @implements PDMILEDPORTS
461 */
462typedef struct AHCI
463{
464 /** The PCI device structure. */
465 PDMPCIDEV dev;
466 /** Pointer to the device instance - R3 ptr */
467 PPDMDEVINSR3 pDevInsR3;
468 /** Pointer to the device instance - R0 ptr */
469 PPDMDEVINSR0 pDevInsR0;
470 /** Pointer to the device instance - RC ptr. */
471 PPDMDEVINSRC pDevInsRC;
472
473#if HC_ARCH_BITS == 64
474 uint32_t Alignment0;
475#endif
476
477 /** Status LUN: The base interface. */
478 PDMIBASE IBase;
479 /** Status LUN: Leds interface. */
480 PDMILEDPORTS ILeds;
481 /** Status LUN: Partner of ILeds. */
482 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
483 /** Status LUN: Media Notifys. */
484 R3PTRTYPE(PPDMIMEDIANOTIFY) pMediaNotify;
485
486#if HC_ARCH_BITS == 32
487 uint32_t Alignment1;
488#endif
489
490 /** Base address of the MMIO region. */
491 RTGCPHYS MMIOBase;
492 /** Base address of the I/O port region for Idx/Data. */
493 RTIOPORT IOPortBase;
494
495 /** Global Host Control register of the HBA */
496
497 /** HBA Capabilities - Readonly */
498 uint32_t regHbaCap;
499 /** HBA Control */
500 uint32_t regHbaCtrl;
501 /** Interrupt Status */
502 uint32_t regHbaIs;
503 /** Ports Implemented - Readonly */
504 uint32_t regHbaPi;
505 /** AHCI Version - Readonly */
506 uint32_t regHbaVs;
507 /** Command completion coalescing control */
508 uint32_t regHbaCccCtl;
509 /** Command completion coalescing ports */
510 uint32_t regHbaCccPorts;
511
512 /** Index register for BIOS access. */
513 uint32_t regIdx;
514
515#if HC_ARCH_BITS == 64
516 uint32_t Alignment3;
517#endif
518
519 /** Countdown timer for command completion coalescing - R3 ptr */
520 PTMTIMERR3 pHbaCccTimerR3;
521 /** Countdown timer for command completion coalescing - R0 ptr */
522 PTMTIMERR0 pHbaCccTimerR0;
523 /** Countdown timer for command completion coalescing - RC ptr */
524 PTMTIMERRC pHbaCccTimerRC;
525
526#if HC_ARCH_BITS == 64
527 uint32_t Alignment4;
528#endif
529
530 /** Queue to send tasks to R3. - HC ptr */
531 R3PTRTYPE(PPDMQUEUE) pNotifierQueueR3;
532 /** Queue to send tasks to R3. - HC ptr */
533 R0PTRTYPE(PPDMQUEUE) pNotifierQueueR0;
534 /** Queue to send tasks to R3. - RC ptr */
535 RCPTRTYPE(PPDMQUEUE) pNotifierQueueRC;
536
537#if HC_ARCH_BITS == 64
538 uint32_t Alignment5;
539#endif
540
541
542 /** Which port number is used to mark an CCC interrupt */
543 uint8_t uCccPortNr;
544
545#if HC_ARCH_BITS == 64
546 uint32_t Alignment6;
547#endif
548
549 /** Timeout value */
550 uint64_t uCccTimeout;
551 /** Number of completions used to assert an interrupt */
552 uint32_t uCccNr;
553 /** Current number of completed commands */
554 uint32_t uCccCurrentNr;
555
556 /** Register structure per port */
557 AHCIPort ahciPort[AHCI_MAX_NR_PORTS_IMPL];
558
559 /** The critical section. */
560 PDMCRITSECT lock;
561
562 /** Bitmask of ports which asserted an interrupt. */
563 volatile uint32_t u32PortsInterrupted;
564 /** Number of I/O threads currently active - used for async controller reset handling. */
565 volatile uint32_t cThreadsActive;
566 /** Device is in a reset state. */
567 bool fReset;
568 /** Supports 64bit addressing */
569 bool f64BitAddr;
570 /** GC enabled. */
571 bool fGCEnabled;
572 /** R0 enabled. */
573 bool fR0Enabled;
574 /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
575 * a port is entering the idle state. */
576 bool volatile fSignalIdle;
577 /** Flag whether the controller has BIOS access enabled. */
578 bool fBootable;
579 /** Flag whether the legacy port reset method should be used to make it work with saved states. */
580 bool fLegacyPortResetMethod;
581
582 /** Number of usable ports on this controller. */
583 uint32_t cPortsImpl;
584 /** Number of usable command slots for each port. */
585 uint32_t cCmdSlotsAvail;
586
587 /** Flag whether we have written the first 4bytes in an 8byte MMIO write successfully. */
588 volatile bool f8ByteMMIO4BytesWrittenSuccessfully;
589
590#if HC_ARCH_BITS == 64
591 uint32_t Alignment7;
592#endif
593
594 /** The support driver session handle. */
595 R3R0PTRTYPE(PSUPDRVSESSION) pSupDrvSession;
596} AHCI;
597/** Pointer to the state of an AHCI device. */
598typedef AHCI *PAHCI;
599
600AssertCompileMemberAlignment(AHCI, ahciPort, 8);
601
602/**
603 * Scatter gather list entry.
604 */
605typedef struct
606{
607 /** Data Base Address. */
608 uint32_t u32DBA;
609 /** Data Base Address - Upper 32-bits. */
610 uint32_t u32DBAUp;
611 /** Reserved */
612 uint32_t u32Reserved;
613 /** Description information. */
614 uint32_t u32DescInf;
615} SGLEntry;
616AssertCompileSize(SGLEntry, 16);
617
618#ifdef IN_RING3
619/**
620 * Memory buffer callback.
621 *
622 * @returns nothing.
623 * @param pThis The NVME controller instance.
624 * @param GCPhys The guest physical address of the memory buffer.
625 * @param pSgBuf The pointer to the host R3 S/G buffer.
626 * @param cbCopy How many bytes to copy between the two buffers.
627 * @param pcbSkip Initially contains the amount of bytes to skip
628 * starting from the guest physical address before
629 * accessing the S/G buffer and start copying data.
630 * On return this contains the remaining amount if
631 * cbCopy < *pcbSkip or 0 otherwise.
632 */
633typedef DECLCALLBACK(void) AHCIR3MEMCOPYCALLBACK(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy,
634 size_t *pcbSkip);
635/** Pointer to a memory copy buffer callback. */
636typedef AHCIR3MEMCOPYCALLBACK *PAHCIR3MEMCOPYCALLBACK;
637#endif
638
639/** Defines for a scatter gather list entry. */
640#define SGLENTRY_DBA_READONLY ~(RT_BIT(0))
641#define SGLENTRY_DESCINF_I RT_BIT(31)
642#define SGLENTRY_DESCINF_DBC 0x3fffff
643#define SGLENTRY_DESCINF_READONLY 0x803fffff
644
645/* Defines for the global host control registers for the HBA. */
646
647#define AHCI_HBA_GLOBAL_SIZE 0x100
648
649/* Defines for the HBA Capabilities - Readonly */
650#define AHCI_HBA_CAP_S64A RT_BIT(31)
651#define AHCI_HBA_CAP_SNCQ RT_BIT(30)
652#define AHCI_HBA_CAP_SIS RT_BIT(28)
653#define AHCI_HBA_CAP_SSS RT_BIT(27)
654#define AHCI_HBA_CAP_SALP RT_BIT(26)
655#define AHCI_HBA_CAP_SAL RT_BIT(25)
656#define AHCI_HBA_CAP_SCLO RT_BIT(24)
657#define AHCI_HBA_CAP_ISS (RT_BIT(23) | RT_BIT(22) | RT_BIT(21) | RT_BIT(20))
658# define AHCI_HBA_CAP_ISS_SHIFT(x) (((x) << 20) & AHCI_HBA_CAP_ISS)
659# define AHCI_HBA_CAP_ISS_GEN1 RT_BIT(0)
660# define AHCI_HBA_CAP_ISS_GEN2 RT_BIT(1)
661#define AHCI_HBA_CAP_SNZO RT_BIT(19)
662#define AHCI_HBA_CAP_SAM RT_BIT(18)
663#define AHCI_HBA_CAP_SPM RT_BIT(17)
664#define AHCI_HBA_CAP_PMD RT_BIT(15)
665#define AHCI_HBA_CAP_SSC RT_BIT(14)
666#define AHCI_HBA_CAP_PSC RT_BIT(13)
667#define AHCI_HBA_CAP_NCS (RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8))
668#define AHCI_HBA_CAP_NCS_SET(x) (((x-1) << 8) & AHCI_HBA_CAP_NCS) /* 0's based */
669#define AHCI_HBA_CAP_CCCS RT_BIT(7)
670#define AHCI_HBA_CAP_NP (RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0))
671#define AHCI_HBA_CAP_NP_SET(x) ((x-1) & AHCI_HBA_CAP_NP) /* 0's based */
672
673/* Defines for the HBA Control register - Read/Write */
674#define AHCI_HBA_CTRL_AE RT_BIT(31)
675#define AHCI_HBA_CTRL_IE RT_BIT(1)
676#define AHCI_HBA_CTRL_HR RT_BIT(0)
677#define AHCI_HBA_CTRL_RW_MASK (RT_BIT(0) | RT_BIT(1)) /* Mask for the used bits */
678
679/* Defines for the HBA Version register - Readonly (We support AHCI 1.0) */
680#define AHCI_HBA_VS_MJR (1 << 16)
681#define AHCI_HBA_VS_MNR 0x100
682
683/* Defines for the command completion coalescing control register */
684#define AHCI_HBA_CCC_CTL_TV 0xffff0000
685#define AHCI_HBA_CCC_CTL_TV_SET(x) (x << 16)
686#define AHCI_HBA_CCC_CTL_TV_GET(x) ((x & AHCI_HBA_CCC_CTL_TV) >> 16)
687
688#define AHCI_HBA_CCC_CTL_CC 0xff00
689#define AHCI_HBA_CCC_CTL_CC_SET(x) (x << 8)
690#define AHCI_HBA_CCC_CTL_CC_GET(x) ((x & AHCI_HBA_CCC_CTL_CC) >> 8)
691
692#define AHCI_HBA_CCC_CTL_INT 0xf8
693#define AHCI_HBA_CCC_CTL_INT_SET(x) (x << 3)
694#define AHCI_HBA_CCC_CTL_INT_GET(x) ((x & AHCI_HBA_CCC_CTL_INT) >> 3)
695
696#define AHCI_HBA_CCC_CTL_EN RT_BIT(0)
697
698/* Defines for the port registers. */
699
700#define AHCI_PORT_REGISTER_SIZE 0x80
701
702#define AHCI_PORT_CLB_RESERVED 0xfffffc00 /* For masking out the reserved bits. */
703
704#define AHCI_PORT_FB_RESERVED 0xffffff00 /* For masking out the reserved bits. */
705
706#define AHCI_PORT_IS_CPDS RT_BIT(31)
707#define AHCI_PORT_IS_TFES RT_BIT(30)
708#define AHCI_PORT_IS_HBFS RT_BIT(29)
709#define AHCI_PORT_IS_HBDS RT_BIT(28)
710#define AHCI_PORT_IS_IFS RT_BIT(27)
711#define AHCI_PORT_IS_INFS RT_BIT(26)
712#define AHCI_PORT_IS_OFS RT_BIT(24)
713#define AHCI_PORT_IS_IPMS RT_BIT(23)
714#define AHCI_PORT_IS_PRCS RT_BIT(22)
715#define AHCI_PORT_IS_DIS RT_BIT(7)
716#define AHCI_PORT_IS_PCS RT_BIT(6)
717#define AHCI_PORT_IS_DPS RT_BIT(5)
718#define AHCI_PORT_IS_UFS RT_BIT(4)
719#define AHCI_PORT_IS_SDBS RT_BIT(3)
720#define AHCI_PORT_IS_DSS RT_BIT(2)
721#define AHCI_PORT_IS_PSS RT_BIT(1)
722#define AHCI_PORT_IS_DHRS RT_BIT(0)
723#define AHCI_PORT_IS_READONLY 0xfd8000af /* Readonly mask including reserved bits. */
724
725#define AHCI_PORT_IE_CPDE RT_BIT(31)
726#define AHCI_PORT_IE_TFEE RT_BIT(30)
727#define AHCI_PORT_IE_HBFE RT_BIT(29)
728#define AHCI_PORT_IE_HBDE RT_BIT(28)
729#define AHCI_PORT_IE_IFE RT_BIT(27)
730#define AHCI_PORT_IE_INFE RT_BIT(26)
731#define AHCI_PORT_IE_OFE RT_BIT(24)
732#define AHCI_PORT_IE_IPME RT_BIT(23)
733#define AHCI_PORT_IE_PRCE RT_BIT(22)
734#define AHCI_PORT_IE_DIE RT_BIT(7) /* Not supported for now, readonly. */
735#define AHCI_PORT_IE_PCE RT_BIT(6)
736#define AHCI_PORT_IE_DPE RT_BIT(5)
737#define AHCI_PORT_IE_UFE RT_BIT(4)
738#define AHCI_PORT_IE_SDBE RT_BIT(3)
739#define AHCI_PORT_IE_DSE RT_BIT(2)
740#define AHCI_PORT_IE_PSE RT_BIT(1)
741#define AHCI_PORT_IE_DHRE RT_BIT(0)
742#define AHCI_PORT_IE_READONLY (0xfdc000ff) /* Readonly mask including reserved bits. */
743
744#define AHCI_PORT_CMD_ICC (RT_BIT(28) | RT_BIT(29) | RT_BIT(30) | RT_BIT(31))
745#define AHCI_PORT_CMD_ICC_SHIFT(x) ((x) << 28)
746# define AHCI_PORT_CMD_ICC_IDLE 0x0
747# define AHCI_PORT_CMD_ICC_ACTIVE 0x1
748# define AHCI_PORT_CMD_ICC_PARTIAL 0x2
749# define AHCI_PORT_CMD_ICC_SLUMBER 0x6
750#define AHCI_PORT_CMD_ASP RT_BIT(27) /* Not supported - Readonly */
751#define AHCI_PORT_CMD_ALPE RT_BIT(26) /* Not supported - Readonly */
752#define AHCI_PORT_CMD_DLAE RT_BIT(25)
753#define AHCI_PORT_CMD_ATAPI RT_BIT(24)
754#define AHCI_PORT_CMD_CPD RT_BIT(20)
755#define AHCI_PORT_CMD_ISP RT_BIT(19) /* Readonly */
756#define AHCI_PORT_CMD_HPCP RT_BIT(18)
757#define AHCI_PORT_CMD_PMA RT_BIT(17) /* Not supported - Readonly */
758#define AHCI_PORT_CMD_CPS RT_BIT(16)
759#define AHCI_PORT_CMD_CR RT_BIT(15) /* Readonly */
760#define AHCI_PORT_CMD_FR RT_BIT(14) /* Readonly */
761#define AHCI_PORT_CMD_ISS RT_BIT(13) /* Readonly */
762#define AHCI_PORT_CMD_CCS (RT_BIT(8) | RT_BIT(9) | RT_BIT(10) | RT_BIT(11) | RT_BIT(12))
763#define AHCI_PORT_CMD_CCS_SHIFT(x) (x << 8) /* Readonly */
764#define AHCI_PORT_CMD_FRE RT_BIT(4)
765#define AHCI_PORT_CMD_CLO RT_BIT(3)
766#define AHCI_PORT_CMD_POD RT_BIT(2)
767#define AHCI_PORT_CMD_SUD RT_BIT(1)
768#define AHCI_PORT_CMD_ST RT_BIT(0)
769#define AHCI_PORT_CMD_READONLY (0xff02001f & ~(AHCI_PORT_CMD_ASP | AHCI_PORT_CMD_ALPE | AHCI_PORT_CMD_PMA))
770
771#define AHCI_PORT_SCTL_IPM (RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8))
772#define AHCI_PORT_SCTL_IPM_GET(x) ((x & AHCI_PORT_SCTL_IPM) >> 8)
773#define AHCI_PORT_SCTL_SPD (RT_BIT(7) | RT_BIT(6) | RT_BIT(5) | RT_BIT(4))
774#define AHCI_PORT_SCTL_SPD_GET(x) ((x & AHCI_PORT_SCTL_SPD) >> 4)
775#define AHCI_PORT_SCTL_DET (RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0))
776#define AHCI_PORT_SCTL_DET_GET(x) (x & AHCI_PORT_SCTL_DET)
777#define AHCI_PORT_SCTL_DET_NINIT 0
778#define AHCI_PORT_SCTL_DET_INIT 1
779#define AHCI_PORT_SCTL_DET_OFFLINE 4
780#define AHCI_PORT_SCTL_READONLY 0xfff
781
782#define AHCI_PORT_SSTS_IPM (RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8))
783#define AHCI_PORT_SSTS_IPM_GET(x) ((x & AHCI_PORT_SCTL_IPM) >> 8)
784#define AHCI_PORT_SSTS_SPD (RT_BIT(7) | RT_BIT(6) | RT_BIT(5) | RT_BIT(4))
785#define AHCI_PORT_SSTS_SPD_GET(x) ((x & AHCI_PORT_SCTL_SPD) >> 4)
786#define AHCI_PORT_SSTS_DET (RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0))
787#define AHCI_PORT_SSTS_DET_GET(x) (x & AHCI_PORT_SCTL_DET)
788
789#define AHCI_PORT_TFD_BSY RT_BIT(7)
790#define AHCI_PORT_TFD_DRQ RT_BIT(3)
791#define AHCI_PORT_TFD_ERR RT_BIT(0)
792
793#define AHCI_PORT_SERR_X RT_BIT(26)
794#define AHCI_PORT_SERR_W RT_BIT(18)
795#define AHCI_PORT_SERR_N RT_BIT(16)
796
797/* Signatures for attached storage devices. */
798#define AHCI_PORT_SIG_DISK 0x00000101
799#define AHCI_PORT_SIG_ATAPI 0xeb140101
800
801/*
802 * The AHCI spec defines an area of memory where the HBA posts received FIS's from the device.
803 * regFB points to the base of this area.
804 * Every FIS type has an offset where it is posted in this area.
805 */
806#define AHCI_RECFIS_DSFIS_OFFSET 0x00 /* DMA Setup FIS */
807#define AHCI_RECFIS_PSFIS_OFFSET 0x20 /* PIO Setup FIS */
808#define AHCI_RECFIS_RFIS_OFFSET 0x40 /* D2H Register FIS */
809#define AHCI_RECFIS_SDBFIS_OFFSET 0x58 /* Set Device Bits FIS */
810#define AHCI_RECFIS_UFIS_OFFSET 0x60 /* Unknown FIS type */
811
812/** Mask to get the LBA value from a LBA range. */
813#define AHCI_RANGE_LBA_MASK UINT64_C(0xffffffffffff)
814/** Mas to get the length value from a LBA range. */
815#define AHCI_RANGE_LENGTH_MASK UINT64_C(0xffff000000000000)
816/** Returns the length of the range in sectors. */
817#define AHCI_RANGE_LENGTH_GET(val) (((val) & AHCI_RANGE_LENGTH_MASK) >> 48)
818
819/**
820 * AHCI register operator.
821 */
822typedef struct ahci_opreg
823{
824 const char *pszName;
825 int (*pfnRead )(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value);
826 int (*pfnWrite)(PAHCI pAhci, uint32_t iReg, uint32_t u32Value);
827} AHCIOPREG;
828
829/**
830 * AHCI port register operator.
831 */
832typedef struct pAhciPort_opreg
833{
834 const char *pszName;
835 int (*pfnRead )(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value);
836 int (*pfnWrite)(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value);
837} AHCIPORTOPREG;
838
839#ifndef VBOX_DEVICE_STRUCT_TESTCASE
840RT_C_DECLS_BEGIN
841#ifdef IN_RING3
842static void ahciHBAReset(PAHCI pThis);
843static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *cmdFis);
844static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort);
845static size_t ahciR3CopyBufferToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, const void *pvSrc,
846 size_t cbSrc, size_t cbSkip);
847static bool ahciCancelActiveTasks(PAHCIPort pAhciPort);
848#endif
849RT_C_DECLS_END
850
851#define PCIDEV_2_PAHCI(pPciDev) ( (PAHCI)(pPciDev) )
852#define PDMIBASE_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCIPort, IBase)) )
853#define PDMIMEDIAPORT_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCIPort, IPort)) )
854#define PDMIBASE_2_PAHCI(pInterface) ( (PAHCI)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCI, IBase)) )
855#define PDMILEDPORTS_2_PAHCI(pInterface) ( (PAHCI)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCI, ILeds)) )
856
857#define AHCI_RTGCPHYS_FROM_U32(Hi, Lo) ( (RTGCPHYS)RT_MAKE_U64(Lo, Hi) )
858
859#ifdef IN_RING3
860
861# ifdef LOG_USE_C99
862# define ahciLog(a) \
863 Log(("R3 P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
864# else
865# define ahciLog(a) \
866 do { Log(("R3 P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
867# endif
868
869#elif defined(IN_RING0)
870
871# ifdef LOG_USE_C99
872# define ahciLog(a) \
873 Log(("R0 P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
874# else
875# define ahciLog(a) \
876 do { Log(("R0 P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
877# endif
878
879#elif defined(IN_RC)
880
881# ifdef LOG_USE_C99
882# define ahciLog(a) \
883 Log(("GC P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
884# else
885# define ahciLog(a) \
886 do { Log(("GC P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
887# endif
888
889#endif
890
891/**
892 * Update PCI IRQ levels
893 */
894static void ahciHbaClearInterrupt(PAHCI pAhci)
895{
896 Log(("%s: Clearing interrupt\n", __FUNCTION__));
897 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 0);
898}
899
900/**
901 * Updates the IRQ level and sets port bit in the global interrupt status register of the HBA.
902 */
903static int ahciHbaSetInterrupt(PAHCI pAhci, uint8_t iPort, int rcBusy)
904{
905 Log(("P%u: %s: Setting interrupt\n", iPort, __FUNCTION__));
906
907 int rc = PDMCritSectEnter(&pAhci->lock, rcBusy);
908 if (rc != VINF_SUCCESS)
909 return rc;
910
911 if (pAhci->regHbaCtrl & AHCI_HBA_CTRL_IE)
912 {
913 if ((pAhci->regHbaCccCtl & AHCI_HBA_CCC_CTL_EN) && (pAhci->regHbaCccPorts & (1 << iPort)))
914 {
915 pAhci->uCccCurrentNr++;
916 if (pAhci->uCccCurrentNr >= pAhci->uCccNr)
917 {
918 /* Reset command completion coalescing state. */
919 TMTimerSetMillies(pAhci->CTX_SUFF(pHbaCccTimer), pAhci->uCccTimeout);
920 pAhci->uCccCurrentNr = 0;
921
922 pAhci->u32PortsInterrupted |= (1 << pAhci->uCccPortNr);
923 if (!(pAhci->u32PortsInterrupted & ~(1 << pAhci->uCccPortNr)))
924 {
925 Log(("P%u: %s: Fire interrupt\n", iPort, __FUNCTION__));
926 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 1);
927 }
928 }
929 }
930 else
931 {
932 /* If only the bit of the actual port is set assert an interrupt
933 * because the interrupt status register was already read by the guest
934 * and we need to send a new notification.
935 * Otherwise an interrupt is still pending.
936 */
937 ASMAtomicOrU32((volatile uint32_t *)&pAhci->u32PortsInterrupted, (1 << iPort));
938 if (!(pAhci->u32PortsInterrupted & ~(1 << iPort)))
939 {
940 Log(("P%u: %s: Fire interrupt\n", iPort, __FUNCTION__));
941 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 1);
942 }
943 }
944 }
945
946 PDMCritSectLeave(&pAhci->lock);
947 return VINF_SUCCESS;
948}
949
950#ifdef IN_RING3
951
952/*
953 * Assert irq when an CCC timeout occurs
954 */
955static DECLCALLBACK(void) ahciCccTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
956{
957 RT_NOREF(pDevIns, pTimer);
958 PAHCI pAhci = (PAHCI)pvUser;
959
960 int rc = ahciHbaSetInterrupt(pAhci, pAhci->uCccPortNr, VERR_IGNORED);
961 AssertRC(rc);
962}
963
964/**
965 * Finishes the port reset of the given port.
966 *
967 * @returns nothing.
968 * @param pAhciPort The port to finish the reset on.
969 */
970static void ahciPortResetFinish(PAHCIPort pAhciPort)
971{
972 /* Cancel all tasks first. */
973 bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
974 Assert(fAllTasksCanceled); NOREF(fAllTasksCanceled);
975
976 /* Signature for SATA device. */
977 if (pAhciPort->fATAPI)
978 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
979 else
980 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
981
982 /* We received a COMINIT from the device. Tell the guest. */
983 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PCS);
984 pAhciPort->regSERR |= AHCI_PORT_SERR_X;
985 pAhciPort->regTFD |= ATA_STAT_BUSY;
986
987 if ((pAhciPort->regCMD & AHCI_PORT_CMD_FRE) && (!pAhciPort->fFirstD2HFisSend))
988 {
989 ahciPostFirstD2HFisIntoMemory(pAhciPort);
990 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
991
992 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
993 {
994 int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
995 AssertRC(rc);
996 }
997 }
998
999 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
1000 (0x03 << 0); /* Device detected and communication established. */
1001
1002 /*
1003 * Use the maximum allowed speed.
1004 * (Not that it changes anything really)
1005 */
1006 switch (AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL))
1007 {
1008 case 0x01:
1009 pAhciPort->regSSTS |= (0x01 << 4); /* Generation 1 (1.5GBps) speed. */
1010 break;
1011 case 0x02:
1012 case 0x00:
1013 default:
1014 pAhciPort->regSSTS |= (0x02 << 4); /* Generation 2 (3.0GBps) speed. */
1015 break;
1016 }
1017
1018 ASMAtomicXchgBool(&pAhciPort->fPortReset, false);
1019}
1020
1021#endif /* IN_RING3 */
1022
1023/**
1024 * Kicks the I/O thread from RC or R0.
1025 *
1026 * @returns nothing.
1027 * @param pAhci The AHCI controller instance.
1028 * @param pAhciPort The port to kick.
1029 */
1030static void ahciIoThreadKick(PAHCI pAhci, PAHCIPort pAhciPort)
1031{
1032#ifdef IN_RC
1033 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue));
1034 AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
1035
1036 if (pItem)
1037 {
1038 pItem->iPort = pAhciPort->iLUN;
1039 PDMQueueInsert(pAhci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
1040 }
1041#else
1042 LogFlowFunc(("Signal event semaphore\n"));
1043 int rc = SUPSemEventSignal(pAhci->pSupDrvSession, pAhciPort->hEvtProcess);
1044 AssertRC(rc);
1045#endif
1046}
1047
1048static int PortCmdIssue_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1049{
1050 RT_NOREF1(iReg);
1051 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1052
1053 /* Update the CI register first. */
1054 uint32_t uCIValue = ASMAtomicXchgU32(&pAhciPort->u32TasksFinished, 0);
1055 pAhciPort->regCI &= ~uCIValue;
1056
1057 if ( (pAhciPort->regCMD & AHCI_PORT_CMD_CR)
1058 && u32Value > 0)
1059 {
1060 /*
1061 * Clear all tasks which are already marked as busy. The guest
1062 * shouldn't write already busy tasks actually.
1063 */
1064 u32Value &= ~pAhciPort->regCI;
1065
1066 ASMAtomicOrU32(&pAhciPort->u32TasksNew, u32Value);
1067
1068 /* Send a notification to R3 if u32TasksNew was 0 before our write. */
1069 if (ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
1070 ahciIoThreadKick(pAhci, pAhciPort);
1071 }
1072
1073 pAhciPort->regCI |= u32Value;
1074
1075 return VINF_SUCCESS;
1076}
1077
1078static int PortCmdIssue_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1079{
1080 RT_NOREF2(pAhci, iReg);
1081
1082 uint32_t uCIValue = ASMAtomicXchgU32(&pAhciPort->u32TasksFinished, 0);
1083 ahciLog(("%s: read regCI=%#010x uCIValue=%#010x\n", __FUNCTION__, pAhciPort->regCI, uCIValue));
1084
1085 pAhciPort->regCI &= ~uCIValue;
1086 *pu32Value = pAhciPort->regCI;
1087
1088 return VINF_SUCCESS;
1089}
1090
1091static int PortSActive_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1092{
1093 RT_NOREF2(pAhci, iReg);
1094 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1095
1096 pAhciPort->regSACT |= u32Value;
1097
1098 return VINF_SUCCESS;
1099}
1100
1101static int PortSActive_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1102{
1103 RT_NOREF2(pAhci, iReg);
1104
1105 uint32_t u32TasksFinished = ASMAtomicXchgU32(&pAhciPort->u32QueuedTasksFinished, 0);
1106 pAhciPort->regSACT &= ~u32TasksFinished;
1107
1108 ahciLog(("%s: read regSACT=%#010x regCI=%#010x u32TasksFinished=%#010x\n",
1109 __FUNCTION__, pAhciPort->regSACT, pAhciPort->regCI, u32TasksFinished));
1110
1111 *pu32Value = pAhciPort->regSACT;
1112
1113 return VINF_SUCCESS;
1114}
1115
1116static int PortSError_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1117{
1118 RT_NOREF2(pAhci, iReg);
1119 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1120
1121 if ( (u32Value & AHCI_PORT_SERR_X)
1122 && (pAhciPort->regSERR & AHCI_PORT_SERR_X))
1123 {
1124 ASMAtomicAndU32(&pAhciPort->regIS, ~AHCI_PORT_IS_PCS);
1125 pAhciPort->regTFD |= ATA_STAT_ERR;
1126 pAhciPort->regTFD &= ~(ATA_STAT_DRQ | ATA_STAT_BUSY);
1127 }
1128
1129 if ( (u32Value & AHCI_PORT_SERR_N)
1130 && (pAhciPort->regSERR & AHCI_PORT_SERR_N))
1131 ASMAtomicAndU32(&pAhciPort->regIS, ~AHCI_PORT_IS_PRCS);
1132
1133 pAhciPort->regSERR &= ~u32Value;
1134
1135 return VINF_SUCCESS;
1136}
1137
1138static int PortSError_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1139{
1140 RT_NOREF2(pAhci, iReg);
1141 ahciLog(("%s: read regSERR=%#010x\n", __FUNCTION__, pAhciPort->regSERR));
1142 *pu32Value = pAhciPort->regSERR;
1143 return VINF_SUCCESS;
1144}
1145
1146static int PortSControl_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1147{
1148 RT_NOREF2(pAhci, iReg);
1149 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1150 ahciLog(("%s: IPM=%d SPD=%d DET=%d\n", __FUNCTION__,
1151 AHCI_PORT_SCTL_IPM_GET(u32Value), AHCI_PORT_SCTL_SPD_GET(u32Value), AHCI_PORT_SCTL_DET_GET(u32Value)));
1152
1153#ifndef IN_RING3
1154 RT_NOREF2(pAhciPort, u32Value);
1155 return VINF_IOM_R3_MMIO_WRITE;
1156#else
1157 if ((u32Value & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_INIT)
1158 {
1159 if (!ASMAtomicXchgBool(&pAhciPort->fPortReset, true))
1160 LogRel(("AHCI#%u: Port %d reset\n", pAhci->CTX_SUFF(pDevIns)->iInstance,
1161 pAhciPort->iLUN));
1162
1163 pAhciPort->regSSTS = 0;
1164 pAhciPort->regSIG = UINT32_MAX;
1165 pAhciPort->regTFD = 0x7f;
1166 pAhciPort->fFirstD2HFisSend = false;
1167 pAhciPort->regSCTL = u32Value;
1168 }
1169 else if ( (u32Value & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_NINIT
1170 && (pAhciPort->regSCTL & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_INIT
1171 && pAhciPort->pDrvBase)
1172 {
1173 /* Do the port reset here, so the guest sees the new status immediately. */
1174 if (pAhci->fLegacyPortResetMethod)
1175 {
1176 ahciPortResetFinish(pAhciPort);
1177 pAhciPort->regSCTL = u32Value; /* Update after finishing the reset, so the I/O thread doesn't get a chance to do the reset. */
1178 }
1179 else
1180 {
1181 pAhciPort->regSSTS = 0x1; /* Indicate device presence detected but communication not established. */
1182 pAhciPort->regSCTL = u32Value; /* Update before kicking the I/O thread. */
1183
1184 /* Kick the thread to finish the reset. */
1185 ahciIoThreadKick(pAhci, pAhciPort);
1186 }
1187 }
1188 else /* Just update the value if there is no device attached. */
1189 pAhciPort->regSCTL = u32Value;
1190
1191 return VINF_SUCCESS;
1192#endif
1193}
1194
1195static int PortSControl_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1196{
1197 RT_NOREF2(pAhci, iReg);
1198 ahciLog(("%s: read regSCTL=%#010x\n", __FUNCTION__, pAhciPort->regSCTL));
1199 ahciLog(("%s: IPM=%d SPD=%d DET=%d\n", __FUNCTION__,
1200 AHCI_PORT_SCTL_IPM_GET(pAhciPort->regSCTL), AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL),
1201 AHCI_PORT_SCTL_DET_GET(pAhciPort->regSCTL)));
1202
1203 *pu32Value = pAhciPort->regSCTL;
1204 return VINF_SUCCESS;
1205}
1206
1207static int PortSStatus_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1208{
1209 RT_NOREF2(pAhci, iReg);
1210 ahciLog(("%s: read regSSTS=%#010x\n", __FUNCTION__, pAhciPort->regSSTS));
1211 ahciLog(("%s: IPM=%d SPD=%d DET=%d\n", __FUNCTION__,
1212 AHCI_PORT_SSTS_IPM_GET(pAhciPort->regSSTS), AHCI_PORT_SSTS_SPD_GET(pAhciPort->regSSTS),
1213 AHCI_PORT_SSTS_DET_GET(pAhciPort->regSSTS)));
1214
1215 *pu32Value = pAhciPort->regSSTS;
1216 return VINF_SUCCESS;
1217}
1218
1219static int PortSignature_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1220{
1221 RT_NOREF2(pAhci, iReg);
1222 ahciLog(("%s: read regSIG=%#010x\n", __FUNCTION__, pAhciPort->regSIG));
1223 *pu32Value = pAhciPort->regSIG;
1224 return VINF_SUCCESS;
1225}
1226
1227static int PortTaskFileData_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1228{
1229 RT_NOREF2(pAhci, iReg);
1230 ahciLog(("%s: read regTFD=%#010x\n", __FUNCTION__, pAhciPort->regTFD));
1231 ahciLog(("%s: ERR=%x BSY=%d DRQ=%d ERR=%d\n", __FUNCTION__,
1232 (pAhciPort->regTFD >> 8), (pAhciPort->regTFD & AHCI_PORT_TFD_BSY) >> 7,
1233 (pAhciPort->regTFD & AHCI_PORT_TFD_DRQ) >> 3, (pAhciPort->regTFD & AHCI_PORT_TFD_ERR)));
1234 *pu32Value = pAhciPort->regTFD;
1235 return VINF_SUCCESS;
1236}
1237
1238/**
1239 * Read from the port command register.
1240 */
1241static int PortCmd_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1242{
1243 RT_NOREF2(pAhci, iReg);
1244 ahciLog(("%s: read regCMD=%#010x\n", __FUNCTION__, pAhciPort->regCMD | AHCI_PORT_CMD_CCS_SHIFT(pAhciPort->u32CurrentCommandSlot)));
1245 ahciLog(("%s: ICC=%d ASP=%d ALPE=%d DLAE=%d ATAPI=%d CPD=%d ISP=%d HPCP=%d PMA=%d CPS=%d CR=%d FR=%d ISS=%d CCS=%d FRE=%d CLO=%d POD=%d SUD=%d ST=%d\n",
1246 __FUNCTION__, (pAhciPort->regCMD & AHCI_PORT_CMD_ICC) >> 28, (pAhciPort->regCMD & AHCI_PORT_CMD_ASP) >> 27,
1247 (pAhciPort->regCMD & AHCI_PORT_CMD_ALPE) >> 26, (pAhciPort->regCMD & AHCI_PORT_CMD_DLAE) >> 25,
1248 (pAhciPort->regCMD & AHCI_PORT_CMD_ATAPI) >> 24, (pAhciPort->regCMD & AHCI_PORT_CMD_CPD) >> 20,
1249 (pAhciPort->regCMD & AHCI_PORT_CMD_ISP) >> 19, (pAhciPort->regCMD & AHCI_PORT_CMD_HPCP) >> 18,
1250 (pAhciPort->regCMD & AHCI_PORT_CMD_PMA) >> 17, (pAhciPort->regCMD & AHCI_PORT_CMD_CPS) >> 16,
1251 (pAhciPort->regCMD & AHCI_PORT_CMD_CR) >> 15, (pAhciPort->regCMD & AHCI_PORT_CMD_FR) >> 14,
1252 (pAhciPort->regCMD & AHCI_PORT_CMD_ISS) >> 13, pAhciPort->u32CurrentCommandSlot,
1253 (pAhciPort->regCMD & AHCI_PORT_CMD_FRE) >> 4, (pAhciPort->regCMD & AHCI_PORT_CMD_CLO) >> 3,
1254 (pAhciPort->regCMD & AHCI_PORT_CMD_POD) >> 2, (pAhciPort->regCMD & AHCI_PORT_CMD_SUD) >> 1,
1255 (pAhciPort->regCMD & AHCI_PORT_CMD_ST)));
1256 *pu32Value = pAhciPort->regCMD | AHCI_PORT_CMD_CCS_SHIFT(pAhciPort->u32CurrentCommandSlot);
1257 return VINF_SUCCESS;
1258}
1259
1260/**
1261 * Write to the port command register.
1262 * This is the register where all the data transfer is started
1263 */
1264static int PortCmd_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1265{
1266 RT_NOREF1(iReg);
1267 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1268 ahciLog(("%s: ICC=%d ASP=%d ALPE=%d DLAE=%d ATAPI=%d CPD=%d ISP=%d HPCP=%d PMA=%d CPS=%d CR=%d FR=%d ISS=%d CCS=%d FRE=%d CLO=%d POD=%d SUD=%d ST=%d\n",
1269 __FUNCTION__, (u32Value & AHCI_PORT_CMD_ICC) >> 28, (u32Value & AHCI_PORT_CMD_ASP) >> 27,
1270 (u32Value & AHCI_PORT_CMD_ALPE) >> 26, (u32Value & AHCI_PORT_CMD_DLAE) >> 25,
1271 (u32Value & AHCI_PORT_CMD_ATAPI) >> 24, (u32Value & AHCI_PORT_CMD_CPD) >> 20,
1272 (u32Value & AHCI_PORT_CMD_ISP) >> 19, (u32Value & AHCI_PORT_CMD_HPCP) >> 18,
1273 (u32Value & AHCI_PORT_CMD_PMA) >> 17, (u32Value & AHCI_PORT_CMD_CPS) >> 16,
1274 (u32Value & AHCI_PORT_CMD_CR) >> 15, (u32Value & AHCI_PORT_CMD_FR) >> 14,
1275 (u32Value & AHCI_PORT_CMD_ISS) >> 13, (u32Value & AHCI_PORT_CMD_CCS) >> 8,
1276 (u32Value & AHCI_PORT_CMD_FRE) >> 4, (u32Value & AHCI_PORT_CMD_CLO) >> 3,
1277 (u32Value & AHCI_PORT_CMD_POD) >> 2, (u32Value & AHCI_PORT_CMD_SUD) >> 1,
1278 (u32Value & AHCI_PORT_CMD_ST)));
1279
1280 /* The PxCMD.CCS bits are R/O and maintained separately. */
1281 u32Value &= ~AHCI_PORT_CMD_CCS;
1282
1283 if (pAhciPort->fPoweredOn && pAhciPort->fSpunUp)
1284 {
1285 if (u32Value & AHCI_PORT_CMD_CLO)
1286 {
1287 ahciLog(("%s: Command list override requested\n", __FUNCTION__));
1288 u32Value &= ~(AHCI_PORT_TFD_BSY | AHCI_PORT_TFD_DRQ);
1289 /* Clear the CLO bit. */
1290 u32Value &= ~(AHCI_PORT_CMD_CLO);
1291 }
1292
1293 if (u32Value & AHCI_PORT_CMD_ST)
1294 {
1295 /*
1296 * Set engine state to running if there is a device attached and
1297 * IS.PCS is clear.
1298 */
1299 if ( pAhciPort->pDrvBase
1300 && !(pAhciPort->regIS & AHCI_PORT_IS_PCS))
1301 {
1302 ahciLog(("%s: Engine starts\n", __FUNCTION__));
1303 u32Value |= AHCI_PORT_CMD_CR;
1304
1305 /* If there is something in CI, kick the I/O thread. */
1306 if ( pAhciPort->regCI > 0
1307 && ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
1308 {
1309 ASMAtomicOrU32(&pAhciPort->u32TasksNew, pAhciPort->regCI);
1310#ifdef IN_RC
1311 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue));
1312 AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
1313
1314 pItem->iPort = pAhciPort->iLUN;
1315 PDMQueueInsert(pAhci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
1316#else
1317 LogFlowFunc(("Signal event semaphore\n"));
1318 int rc = SUPSemEventSignal(pAhci->pSupDrvSession, pAhciPort->hEvtProcess);
1319 AssertRC(rc);
1320#endif
1321 }
1322 }
1323 else
1324 u32Value &= ~AHCI_PORT_CMD_CR;
1325 }
1326 else
1327 {
1328 ahciLog(("%s: Engine stops\n", __FUNCTION__));
1329 /* Clear command issue register. */
1330 pAhciPort->regCI = 0;
1331 pAhciPort->regSACT = 0;
1332 /* Clear current command slot. */
1333 pAhciPort->u32CurrentCommandSlot = 0;
1334 u32Value &= ~AHCI_PORT_CMD_CR;
1335 }
1336 }
1337 else if (pAhciPort->pDrvBase)
1338 {
1339 if ((u32Value & AHCI_PORT_CMD_POD) && (pAhciPort->regCMD & AHCI_PORT_CMD_CPS) && !pAhciPort->fPoweredOn)
1340 {
1341 ahciLog(("%s: Power on the device\n", __FUNCTION__));
1342 pAhciPort->fPoweredOn = true;
1343
1344 /*
1345 * Set states in the Port Signature and SStatus registers.
1346 */
1347 if (pAhciPort->fATAPI)
1348 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
1349 else
1350 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
1351 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
1352 (0x02 << 4) | /* Generation 2 (3.0GBps) speed. */
1353 (0x03 << 0); /* Device detected and communication established. */
1354
1355 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
1356 {
1357#ifndef IN_RING3
1358 return VINF_IOM_R3_MMIO_WRITE;
1359#else
1360 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1361 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
1362
1363 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
1364 {
1365 int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
1366 AssertRC(rc);
1367 }
1368#endif
1369 }
1370 }
1371
1372 if ((u32Value & AHCI_PORT_CMD_SUD) && pAhciPort->fPoweredOn && !pAhciPort->fSpunUp)
1373 {
1374 ahciLog(("%s: Spin up the device\n", __FUNCTION__));
1375 pAhciPort->fSpunUp = true;
1376 }
1377 }
1378
1379 if (u32Value & AHCI_PORT_CMD_FRE)
1380 {
1381 ahciLog(("%s: FIS receive enabled\n", __FUNCTION__));
1382
1383 u32Value |= AHCI_PORT_CMD_FR;
1384
1385 /* Send the first D2H FIS only if it wasn't already send. */
1386 if ( !pAhciPort->fFirstD2HFisSend
1387 && pAhciPort->pDrvBase)
1388 {
1389#ifndef IN_RING3
1390 return VINF_IOM_R3_MMIO_WRITE;
1391#else
1392 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1393 pAhciPort->fFirstD2HFisSend = true;
1394#endif
1395 }
1396 }
1397 else if (!(u32Value & AHCI_PORT_CMD_FRE))
1398 {
1399 ahciLog(("%s: FIS receive disabled\n", __FUNCTION__));
1400 u32Value &= ~AHCI_PORT_CMD_FR;
1401 }
1402
1403 pAhciPort->regCMD = u32Value;
1404
1405 return VINF_SUCCESS;
1406}
1407
1408/**
1409 * Read from the port interrupt enable register.
1410 */
1411static int PortIntrEnable_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1412{
1413 RT_NOREF2(pAhci, iReg);
1414 ahciLog(("%s: read regIE=%#010x\n", __FUNCTION__, pAhciPort->regIE));
1415 ahciLog(("%s: CPDE=%d TFEE=%d HBFE=%d HBDE=%d IFE=%d INFE=%d OFE=%d IPME=%d PRCE=%d DIE=%d PCE=%d DPE=%d UFE=%d SDBE=%d DSE=%d PSE=%d DHRE=%d\n",
1416 __FUNCTION__, (pAhciPort->regIE & AHCI_PORT_IE_CPDE) >> 31, (pAhciPort->regIE & AHCI_PORT_IE_TFEE) >> 30,
1417 (pAhciPort->regIE & AHCI_PORT_IE_HBFE) >> 29, (pAhciPort->regIE & AHCI_PORT_IE_HBDE) >> 28,
1418 (pAhciPort->regIE & AHCI_PORT_IE_IFE) >> 27, (pAhciPort->regIE & AHCI_PORT_IE_INFE) >> 26,
1419 (pAhciPort->regIE & AHCI_PORT_IE_OFE) >> 24, (pAhciPort->regIE & AHCI_PORT_IE_IPME) >> 23,
1420 (pAhciPort->regIE & AHCI_PORT_IE_PRCE) >> 22, (pAhciPort->regIE & AHCI_PORT_IE_DIE) >> 7,
1421 (pAhciPort->regIE & AHCI_PORT_IE_PCE) >> 6, (pAhciPort->regIE & AHCI_PORT_IE_DPE) >> 5,
1422 (pAhciPort->regIE & AHCI_PORT_IE_UFE) >> 4, (pAhciPort->regIE & AHCI_PORT_IE_SDBE) >> 3,
1423 (pAhciPort->regIE & AHCI_PORT_IE_DSE) >> 2, (pAhciPort->regIE & AHCI_PORT_IE_PSE) >> 1,
1424 (pAhciPort->regIE & AHCI_PORT_IE_DHRE)));
1425 *pu32Value = pAhciPort->regIE;
1426 return VINF_SUCCESS;
1427}
1428
1429/**
1430 * Write to the port interrupt enable register.
1431 */
1432static int PortIntrEnable_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1433{
1434 RT_NOREF1(iReg);
1435 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1436 ahciLog(("%s: CPDE=%d TFEE=%d HBFE=%d HBDE=%d IFE=%d INFE=%d OFE=%d IPME=%d PRCE=%d DIE=%d PCE=%d DPE=%d UFE=%d SDBE=%d DSE=%d PSE=%d DHRE=%d\n",
1437 __FUNCTION__, (u32Value & AHCI_PORT_IE_CPDE) >> 31, (u32Value & AHCI_PORT_IE_TFEE) >> 30,
1438 (u32Value & AHCI_PORT_IE_HBFE) >> 29, (u32Value & AHCI_PORT_IE_HBDE) >> 28,
1439 (u32Value & AHCI_PORT_IE_IFE) >> 27, (u32Value & AHCI_PORT_IE_INFE) >> 26,
1440 (u32Value & AHCI_PORT_IE_OFE) >> 24, (u32Value & AHCI_PORT_IE_IPME) >> 23,
1441 (u32Value & AHCI_PORT_IE_PRCE) >> 22, (u32Value & AHCI_PORT_IE_DIE) >> 7,
1442 (u32Value & AHCI_PORT_IE_PCE) >> 6, (u32Value & AHCI_PORT_IE_DPE) >> 5,
1443 (u32Value & AHCI_PORT_IE_UFE) >> 4, (u32Value & AHCI_PORT_IE_SDBE) >> 3,
1444 (u32Value & AHCI_PORT_IE_DSE) >> 2, (u32Value & AHCI_PORT_IE_PSE) >> 1,
1445 (u32Value & AHCI_PORT_IE_DHRE)));
1446
1447 u32Value &= AHCI_PORT_IE_READONLY;
1448
1449 /* Check if some a interrupt status bit changed*/
1450 uint32_t u32IntrStatus = ASMAtomicReadU32(&pAhciPort->regIS);
1451
1452 int rc = VINF_SUCCESS;
1453 if (u32Value & u32IntrStatus)
1454 rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VINF_IOM_R3_MMIO_WRITE);
1455
1456 if (rc == VINF_SUCCESS)
1457 pAhciPort->regIE = u32Value;
1458
1459 return rc;
1460}
1461
1462/**
1463 * Read from the port interrupt status register.
1464 */
1465static int PortIntrSts_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1466{
1467 RT_NOREF2(pAhci, iReg);
1468 ahciLog(("%s: read regIS=%#010x\n", __FUNCTION__, pAhciPort->regIS));
1469 ahciLog(("%s: CPDS=%d TFES=%d HBFS=%d HBDS=%d IFS=%d INFS=%d OFS=%d IPMS=%d PRCS=%d DIS=%d PCS=%d DPS=%d UFS=%d SDBS=%d DSS=%d PSS=%d DHRS=%d\n",
1470 __FUNCTION__, (pAhciPort->regIS & AHCI_PORT_IS_CPDS) >> 31, (pAhciPort->regIS & AHCI_PORT_IS_TFES) >> 30,
1471 (pAhciPort->regIS & AHCI_PORT_IS_HBFS) >> 29, (pAhciPort->regIS & AHCI_PORT_IS_HBDS) >> 28,
1472 (pAhciPort->regIS & AHCI_PORT_IS_IFS) >> 27, (pAhciPort->regIS & AHCI_PORT_IS_INFS) >> 26,
1473 (pAhciPort->regIS & AHCI_PORT_IS_OFS) >> 24, (pAhciPort->regIS & AHCI_PORT_IS_IPMS) >> 23,
1474 (pAhciPort->regIS & AHCI_PORT_IS_PRCS) >> 22, (pAhciPort->regIS & AHCI_PORT_IS_DIS) >> 7,
1475 (pAhciPort->regIS & AHCI_PORT_IS_PCS) >> 6, (pAhciPort->regIS & AHCI_PORT_IS_DPS) >> 5,
1476 (pAhciPort->regIS & AHCI_PORT_IS_UFS) >> 4, (pAhciPort->regIS & AHCI_PORT_IS_SDBS) >> 3,
1477 (pAhciPort->regIS & AHCI_PORT_IS_DSS) >> 2, (pAhciPort->regIS & AHCI_PORT_IS_PSS) >> 1,
1478 (pAhciPort->regIS & AHCI_PORT_IS_DHRS)));
1479 *pu32Value = pAhciPort->regIS;
1480 return VINF_SUCCESS;
1481}
1482
1483/**
1484 * Write to the port interrupt status register.
1485 */
1486static int PortIntrSts_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1487{
1488 RT_NOREF2(pAhci, iReg);
1489 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1490 ASMAtomicAndU32(&pAhciPort->regIS, ~(u32Value & AHCI_PORT_IS_READONLY));
1491
1492 return VINF_SUCCESS;
1493}
1494
1495/**
1496 * Read from the port FIS base address upper 32bit register.
1497 */
1498static int PortFisAddrUp_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1499{
1500 RT_NOREF2(pAhci, iReg);
1501 ahciLog(("%s: read regFBU=%#010x\n", __FUNCTION__, pAhciPort->regFBU));
1502 *pu32Value = pAhciPort->regFBU;
1503 return VINF_SUCCESS;
1504}
1505
1506/**
1507 * Write to the port FIS base address upper 32bit register.
1508 */
1509static int PortFisAddrUp_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1510{
1511 RT_NOREF2(pAhci, iReg);
1512 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1513
1514 pAhciPort->regFBU = u32Value;
1515 pAhciPort->GCPhysAddrFb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regFBU, pAhciPort->regFB);
1516
1517 return VINF_SUCCESS;
1518}
1519
1520/**
1521 * Read from the port FIS base address register.
1522 */
1523static int PortFisAddr_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1524{
1525 RT_NOREF2(pAhci, iReg);
1526 ahciLog(("%s: read regFB=%#010x\n", __FUNCTION__, pAhciPort->regFB));
1527 *pu32Value = pAhciPort->regFB;
1528 return VINF_SUCCESS;
1529}
1530
1531/**
1532 * Write to the port FIS base address register.
1533 */
1534static int PortFisAddr_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1535{
1536 RT_NOREF2(pAhci, iReg);
1537 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1538
1539 Assert(!(u32Value & ~AHCI_PORT_FB_RESERVED));
1540
1541 pAhciPort->regFB = (u32Value & AHCI_PORT_FB_RESERVED);
1542 pAhciPort->GCPhysAddrFb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regFBU, pAhciPort->regFB);
1543
1544 return VINF_SUCCESS;
1545}
1546
1547/**
1548 * Write to the port command list base address upper 32bit register.
1549 */
1550static int PortCmdLstAddrUp_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1551{
1552 RT_NOREF2(pAhci, iReg);
1553 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1554
1555 pAhciPort->regCLBU = u32Value;
1556 pAhciPort->GCPhysAddrClb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regCLBU, pAhciPort->regCLB);
1557
1558 return VINF_SUCCESS;
1559}
1560
1561/**
1562 * Read from the port command list base address upper 32bit register.
1563 */
1564static int PortCmdLstAddrUp_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1565{
1566 RT_NOREF2(pAhci, iReg);
1567 ahciLog(("%s: read regCLBU=%#010x\n", __FUNCTION__, pAhciPort->regCLBU));
1568 *pu32Value = pAhciPort->regCLBU;
1569 return VINF_SUCCESS;
1570}
1571
1572/**
1573 * Read from the port command list base address register.
1574 */
1575static int PortCmdLstAddr_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1576{
1577 RT_NOREF2(pAhci, iReg);
1578 ahciLog(("%s: read regCLB=%#010x\n", __FUNCTION__, pAhciPort->regCLB));
1579 *pu32Value = pAhciPort->regCLB;
1580 return VINF_SUCCESS;
1581}
1582
1583/**
1584 * Write to the port command list base address register.
1585 */
1586static int PortCmdLstAddr_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1587{
1588 RT_NOREF2(pAhci, iReg);
1589 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1590
1591 Assert(!(u32Value & ~AHCI_PORT_CLB_RESERVED));
1592
1593 pAhciPort->regCLB = (u32Value & AHCI_PORT_CLB_RESERVED);
1594 pAhciPort->GCPhysAddrClb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regCLBU, pAhciPort->regCLB);
1595
1596 return VINF_SUCCESS;
1597}
1598
1599/**
1600 * Read from the global Version register.
1601 */
1602static int HbaVersion_r(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value)
1603{
1604 RT_NOREF1(iReg);
1605 Log(("%s: read regHbaVs=%#010x\n", __FUNCTION__, pAhci->regHbaVs));
1606 *pu32Value = pAhci->regHbaVs;
1607 return VINF_SUCCESS;
1608}
1609
1610/**
1611 * Read from the global Ports implemented register.
1612 */
1613static int HbaPortsImplemented_r(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value)
1614{
1615 RT_NOREF1(iReg);
1616 Log(("%s: read regHbaPi=%#010x\n", __FUNCTION__, pAhci->regHbaPi));
1617 *pu32Value = pAhci->regHbaPi;
1618 return VINF_SUCCESS;
1619}
1620
1621/**
1622 * Write to the global interrupt status register.
1623 */
1624static int HbaInterruptStatus_w(PAHCI pAhci, uint32_t iReg, uint32_t u32Value)
1625{
1626 RT_NOREF1(iReg);
1627 Log(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1628
1629 int rc = PDMCritSectEnter(&pAhci->lock, VINF_IOM_R3_MMIO_WRITE);
1630 if (rc != VINF_SUCCESS)
1631 return rc;
1632
1633 pAhci->regHbaIs &= ~(u32Value);
1634
1635 /*
1636 * Update interrupt status register and check for ports who
1637 * set the interrupt inbetween.
1638 */
1639 bool fClear = true;
1640 pAhci->regHbaIs |= ASMAtomicXchgU32(&pAhci->u32PortsInterrupted, 0);
1641 if (!pAhci->regHbaIs)
1642 {
1643 unsigned i = 0;
1644
1645 /* Check if the cleared ports have a interrupt status bit set. */
1646 while ((u32Value > 0) && (i < AHCI_MAX_NR_PORTS_IMPL))
1647 {
1648 if (u32Value & 0x01)
1649 {
1650 PAHCIPort pAhciPort = &pAhci->ahciPort[i];
1651
1652 if (pAhciPort->regIE & pAhciPort->regIS)
1653 {
1654 Log(("%s: Interrupt status of port %u set -> Set interrupt again\n", __FUNCTION__, i));
1655 ASMAtomicOrU32(&pAhci->u32PortsInterrupted, 1 << i);
1656 fClear = false;
1657 break;
1658 }
1659 }
1660 u32Value >>= 1;
1661 i++;
1662 }
1663 }
1664 else
1665 fClear = false;
1666
1667 if (fClear)
1668 ahciHbaClearInterrupt(pAhci);
1669 else
1670 {
1671 Log(("%s: Not clearing interrupt: u32PortsInterrupted=%#010x\n", __FUNCTION__, pAhci->u32PortsInterrupted));
1672 /*
1673 * We need to set the interrupt again because the I/O APIC does not set it again even if the
1674 * line is still high.
1675 * We need to clear it first because the PCI bus only calls the interrupt controller if the state changes.
1676 */
1677 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 0);
1678 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 1);
1679 }
1680
1681 PDMCritSectLeave(&pAhci->lock);
1682 return VINF_SUCCESS;
1683}
1684
1685/**
1686 * Read from the global interrupt status register.
1687 */
1688static int HbaInterruptStatus_r(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value)
1689{
1690 RT_NOREF1(iReg);
1691
1692 int rc = PDMCritSectEnter(&pAhci->lock, VINF_IOM_R3_MMIO_READ);
1693 if (rc != VINF_SUCCESS)
1694 return rc;
1695
1696 uint32_t u32PortsInterrupted = ASMAtomicXchgU32(&pAhci->u32PortsInterrupted, 0);
1697
1698 PDMCritSectLeave(&pAhci->lock);
1699 Log(("%s: read regHbaIs=%#010x u32PortsInterrupted=%#010x\n", __FUNCTION__, pAhci->regHbaIs, u32PortsInterrupted));
1700
1701 pAhci->regHbaIs |= u32PortsInterrupted;
1702
1703#ifdef LOG_ENABLED
1704 Log(("%s:", __FUNCTION__));
1705 unsigned i;
1706 for (i = 0; i < pAhci->cPortsImpl; i++)
1707 {
1708 if ((pAhci->regHbaIs >> i) & 0x01)
1709 Log((" P%d", i));
1710 }
1711 Log(("\n"));
1712#endif
1713
1714 *pu32Value = pAhci->regHbaIs;
1715
1716 return VINF_SUCCESS;
1717}
1718
1719/**
1720 * Write to the global control register.
1721 */
1722static int HbaControl_w(PAHCI pAhci, uint32_t iReg, uint32_t u32Value)
1723{
1724 RT_NOREF1(iReg);
1725 Log(("%s: write u32Value=%#010x\n"
1726 "%s: AE=%d IE=%d HR=%d\n",
1727 __FUNCTION__, u32Value,
1728 __FUNCTION__, (u32Value & AHCI_HBA_CTRL_AE) >> 31, (u32Value & AHCI_HBA_CTRL_IE) >> 1,
1729 (u32Value & AHCI_HBA_CTRL_HR)));
1730
1731#ifndef IN_RING3
1732 RT_NOREF2(pAhci, u32Value);
1733 return VINF_IOM_R3_MMIO_WRITE;
1734#else
1735 /*
1736 * Increase the active thread counter because we might set the host controller
1737 * reset bit.
1738 */
1739 ASMAtomicIncU32(&pAhci->cThreadsActive);
1740 ASMAtomicWriteU32(&pAhci->regHbaCtrl, (u32Value & AHCI_HBA_CTRL_RW_MASK) | AHCI_HBA_CTRL_AE);
1741
1742 /*
1743 * Do the HBA reset if requested and there is no other active thread at the moment,
1744 * the work is deferred to the last active thread otherwise.
1745 */
1746 uint32_t cThreadsActive = ASMAtomicDecU32(&pAhci->cThreadsActive);
1747 if ( (u32Value & AHCI_HBA_CTRL_HR)
1748 && !cThreadsActive)
1749 ahciHBAReset(pAhci);
1750
1751 return VINF_SUCCESS;
1752#endif
1753}
1754
1755/**
1756 * Read the global control register.
1757 */
1758static int HbaControl_r(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value)
1759{
1760 RT_NOREF1(iReg);
1761 Log(("%s: read regHbaCtrl=%#010x\n"
1762 "%s: AE=%d IE=%d HR=%d\n",
1763 __FUNCTION__, pAhci->regHbaCtrl,
1764 __FUNCTION__, (pAhci->regHbaCtrl & AHCI_HBA_CTRL_AE) >> 31, (pAhci->regHbaCtrl & AHCI_HBA_CTRL_IE) >> 1,
1765 (pAhci->regHbaCtrl & AHCI_HBA_CTRL_HR)));
1766 *pu32Value = pAhci->regHbaCtrl;
1767 return VINF_SUCCESS;
1768}
1769
1770/**
1771 * Read the global capabilities register.
1772 */
1773static int HbaCapabilities_r(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value)
1774{
1775 RT_NOREF1(iReg);
1776 Log(("%s: read regHbaCap=%#010x\n"
1777 "%s: S64A=%d SNCQ=%d SIS=%d SSS=%d SALP=%d SAL=%d SCLO=%d ISS=%d SNZO=%d SAM=%d SPM=%d PMD=%d SSC=%d PSC=%d NCS=%d NP=%d\n",
1778 __FUNCTION__, pAhci->regHbaCap,
1779 __FUNCTION__, (pAhci->regHbaCap & AHCI_HBA_CAP_S64A) >> 31, (pAhci->regHbaCap & AHCI_HBA_CAP_SNCQ) >> 30,
1780 (pAhci->regHbaCap & AHCI_HBA_CAP_SIS) >> 28, (pAhci->regHbaCap & AHCI_HBA_CAP_SSS) >> 27,
1781 (pAhci->regHbaCap & AHCI_HBA_CAP_SALP) >> 26, (pAhci->regHbaCap & AHCI_HBA_CAP_SAL) >> 25,
1782 (pAhci->regHbaCap & AHCI_HBA_CAP_SCLO) >> 24, (pAhci->regHbaCap & AHCI_HBA_CAP_ISS) >> 20,
1783 (pAhci->regHbaCap & AHCI_HBA_CAP_SNZO) >> 19, (pAhci->regHbaCap & AHCI_HBA_CAP_SAM) >> 18,
1784 (pAhci->regHbaCap & AHCI_HBA_CAP_SPM) >> 17, (pAhci->regHbaCap & AHCI_HBA_CAP_PMD) >> 15,
1785 (pAhci->regHbaCap & AHCI_HBA_CAP_SSC) >> 14, (pAhci->regHbaCap & AHCI_HBA_CAP_PSC) >> 13,
1786 (pAhci->regHbaCap & AHCI_HBA_CAP_NCS) >> 8, (pAhci->regHbaCap & AHCI_HBA_CAP_NP)));
1787 *pu32Value = pAhci->regHbaCap;
1788 return VINF_SUCCESS;
1789}
1790
1791/**
1792 * Write to the global command completion coalescing control register.
1793 */
1794static int HbaCccCtl_w(PAHCI pAhci, uint32_t iReg, uint32_t u32Value)
1795{
1796 RT_NOREF1(iReg);
1797 Log(("%s: write u32Value=%#010x\n"
1798 "%s: TV=%d CC=%d INT=%d EN=%d\n",
1799 __FUNCTION__, u32Value,
1800 __FUNCTION__, AHCI_HBA_CCC_CTL_TV_GET(u32Value), AHCI_HBA_CCC_CTL_CC_GET(u32Value),
1801 AHCI_HBA_CCC_CTL_INT_GET(u32Value), (u32Value & AHCI_HBA_CCC_CTL_EN)));
1802
1803 pAhci->regHbaCccCtl = u32Value;
1804 pAhci->uCccTimeout = AHCI_HBA_CCC_CTL_TV_GET(u32Value);
1805 pAhci->uCccPortNr = AHCI_HBA_CCC_CTL_INT_GET(u32Value);
1806 pAhci->uCccNr = AHCI_HBA_CCC_CTL_CC_GET(u32Value);
1807
1808 if (u32Value & AHCI_HBA_CCC_CTL_EN)
1809 TMTimerSetMillies(pAhci->CTX_SUFF(pHbaCccTimer), pAhci->uCccTimeout); /* Arm the timer */
1810 else
1811 TMTimerStop(pAhci->CTX_SUFF(pHbaCccTimer));
1812
1813 return VINF_SUCCESS;
1814}
1815
1816/**
1817 * Read the global command completion coalescing control register.
1818 */
1819static int HbaCccCtl_r(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value)
1820{
1821 RT_NOREF1(iReg);
1822 Log(("%s: read regHbaCccCtl=%#010x\n"
1823 "%s: TV=%d CC=%d INT=%d EN=%d\n",
1824 __FUNCTION__, pAhci->regHbaCccCtl,
1825 __FUNCTION__, AHCI_HBA_CCC_CTL_TV_GET(pAhci->regHbaCccCtl), AHCI_HBA_CCC_CTL_CC_GET(pAhci->regHbaCccCtl),
1826 AHCI_HBA_CCC_CTL_INT_GET(pAhci->regHbaCccCtl), (pAhci->regHbaCccCtl & AHCI_HBA_CCC_CTL_EN)));
1827 *pu32Value = pAhci->regHbaCccCtl;
1828 return VINF_SUCCESS;
1829}
1830
1831/**
1832 * Write to the global command completion coalescing ports register.
1833 */
1834static int HbaCccPorts_w(PAHCI pAhci, uint32_t iReg, uint32_t u32Value)
1835{
1836 RT_NOREF1(iReg);
1837 Log(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1838
1839 pAhci->regHbaCccPorts = u32Value;
1840
1841 return VINF_SUCCESS;
1842}
1843
1844/**
1845 * Read the global command completion coalescing ports register.
1846 */
1847static int HbaCccPorts_r(PAHCI pAhci, uint32_t iReg, uint32_t *pu32Value)
1848{
1849 RT_NOREF1(iReg);
1850 Log(("%s: read regHbaCccPorts=%#010x\n", __FUNCTION__, pAhci->regHbaCccPorts));
1851
1852#ifdef LOG_ENABLED
1853 Log(("%s:", __FUNCTION__));
1854 unsigned i;
1855 for (i = 0; i < pAhci->cPortsImpl; i++)
1856 {
1857 if ((pAhci->regHbaCccPorts >> i) & 0x01)
1858 Log((" P%d", i));
1859 }
1860 Log(("\n"));
1861#endif
1862
1863 *pu32Value = pAhci->regHbaCccPorts;
1864 return VINF_SUCCESS;
1865}
1866
1867/**
1868 * Invalid write to global register
1869 */
1870static int HbaInvalid_w(PAHCI pAhci, uint32_t iReg, uint32_t u32Value)
1871{
1872 RT_NOREF3(pAhci, iReg, u32Value);
1873 Log(("%s: Write denied!!! iReg=%u u32Value=%#010x\n", __FUNCTION__, iReg, u32Value));
1874 return VINF_SUCCESS;
1875}
1876
1877/**
1878 * Invalid Port write.
1879 */
1880static int PortInvalid_w(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1881{
1882 RT_NOREF4(pAhci, pAhciPort, iReg, u32Value);
1883 ahciLog(("%s: Write denied!!! iReg=%u u32Value=%#010x\n", __FUNCTION__, iReg, u32Value));
1884 return VINF_SUCCESS;
1885}
1886
1887/**
1888 * Invalid Port read.
1889 */
1890static int PortInvalid_r(PAHCI pAhci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1891{
1892 RT_NOREF4(pAhci, pAhciPort, iReg, pu32Value);
1893 ahciLog(("%s: Read denied!!! iReg=%u\n", __FUNCTION__, iReg));
1894 return VINF_SUCCESS;
1895}
1896
1897/**
1898 * Register descriptor table for global HBA registers
1899 */
1900static const AHCIOPREG g_aOpRegs[] =
1901{
1902 {"HbaCapabilites", HbaCapabilities_r, HbaInvalid_w}, /* Readonly */
1903 {"HbaControl" , HbaControl_r, HbaControl_w},
1904 {"HbaInterruptStatus", HbaInterruptStatus_r, HbaInterruptStatus_w},
1905 {"HbaPortsImplemented", HbaPortsImplemented_r, HbaInvalid_w}, /* Readonly */
1906 {"HbaVersion", HbaVersion_r, HbaInvalid_w}, /* ReadOnly */
1907 {"HbaCccCtl", HbaCccCtl_r, HbaCccCtl_w},
1908 {"HbaCccPorts", HbaCccPorts_r, HbaCccPorts_w},
1909};
1910
1911/**
1912 * Register descriptor table for port registers
1913 */
1914static const AHCIPORTOPREG g_aPortOpRegs[] =
1915{
1916 {"PortCmdLstAddr", PortCmdLstAddr_r, PortCmdLstAddr_w},
1917 {"PortCmdLstAddrUp", PortCmdLstAddrUp_r, PortCmdLstAddrUp_w},
1918 {"PortFisAddr", PortFisAddr_r, PortFisAddr_w},
1919 {"PortFisAddrUp", PortFisAddrUp_r, PortFisAddrUp_w},
1920 {"PortIntrSts", PortIntrSts_r, PortIntrSts_w},
1921 {"PortIntrEnable", PortIntrEnable_r, PortIntrEnable_w},
1922 {"PortCmd", PortCmd_r, PortCmd_w},
1923 {"PortReserved1", PortInvalid_r, PortInvalid_w}, /* Not used. */
1924 {"PortTaskFileData", PortTaskFileData_r, PortInvalid_w}, /* Readonly */
1925 {"PortSignature", PortSignature_r, PortInvalid_w}, /* Readonly */
1926 {"PortSStatus", PortSStatus_r, PortInvalid_w}, /* Readonly */
1927 {"PortSControl", PortSControl_r, PortSControl_w},
1928 {"PortSError", PortSError_r, PortSError_w},
1929 {"PortSActive", PortSActive_r, PortSActive_w},
1930 {"PortCmdIssue", PortCmdIssue_r, PortCmdIssue_w},
1931 {"PortReserved2", PortInvalid_r, PortInvalid_w}, /* Not used. */
1932};
1933
1934#ifdef IN_RING3
1935/**
1936 * Reset initiated by system software for one port.
1937 *
1938 * @param pAhciPort The port to reset.
1939 */
1940static void ahciPortSwReset(PAHCIPort pAhciPort)
1941{
1942 bool fAllTasksCanceled;
1943
1944 /* Cancel all tasks first. */
1945 fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
1946 Assert(fAllTasksCanceled);
1947
1948 Assert(pAhciPort->cTasksActive == 0);
1949
1950 pAhciPort->regIS = 0;
1951 pAhciPort->regIE = 0;
1952 pAhciPort->regCMD = AHCI_PORT_CMD_CPD | /* Cold presence detection */
1953 AHCI_PORT_CMD_SUD | /* Device has spun up. */
1954 AHCI_PORT_CMD_POD; /* Port is powered on. */
1955
1956 /* Hotplugging supported?. */
1957 if (pAhciPort->fHotpluggable)
1958 pAhciPort->regCMD |= AHCI_PORT_CMD_HPCP;
1959
1960 pAhciPort->regTFD = (1 << 8) | ATA_STAT_SEEK | ATA_STAT_WRERR;
1961 pAhciPort->regSIG = UINT32_MAX;
1962 pAhciPort->regSSTS = 0;
1963 pAhciPort->regSCTL = 0;
1964 pAhciPort->regSERR = 0;
1965 pAhciPort->regSACT = 0;
1966 pAhciPort->regCI = 0;
1967
1968 pAhciPort->fResetDevice = false;
1969 pAhciPort->fPoweredOn = true;
1970 pAhciPort->fSpunUp = true;
1971 pAhciPort->cMultSectors = ATA_MAX_MULT_SECTORS;
1972 pAhciPort->uATATransferMode = ATA_MODE_UDMA | 6;
1973
1974 pAhciPort->u32TasksNew = 0;
1975 pAhciPort->u32TasksRedo = 0;
1976 pAhciPort->u32TasksFinished = 0;
1977 pAhciPort->u32QueuedTasksFinished = 0;
1978 pAhciPort->u32CurrentCommandSlot = 0;
1979
1980 if (pAhciPort->pDrvBase)
1981 {
1982 pAhciPort->regCMD |= AHCI_PORT_CMD_CPS; /* Indicate that there is a device on that port */
1983
1984 if (pAhciPort->fPoweredOn)
1985 {
1986 /*
1987 * Set states in the Port Signature and SStatus registers.
1988 */
1989 if (pAhciPort->fATAPI)
1990 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
1991 else
1992 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
1993 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
1994 (0x02 << 4) | /* Generation 2 (3.0GBps) speed. */
1995 (0x03 << 0); /* Device detected and communication established. */
1996 }
1997 }
1998}
1999
2000/**
2001 * Hardware reset used for machine power on and reset.
2002 *
2003 * @param pAhciPort The port to reset.
2004 */
2005static void ahciPortHwReset(PAHCIPort pAhciPort)
2006{
2007 /* Reset the address registers. */
2008 pAhciPort->regCLB = 0;
2009 pAhciPort->regCLBU = 0;
2010 pAhciPort->regFB = 0;
2011 pAhciPort->regFBU = 0;
2012
2013 /* Reset calculated addresses. */
2014 pAhciPort->GCPhysAddrClb = 0;
2015 pAhciPort->GCPhysAddrFb = 0;
2016}
2017
2018/**
2019 * Create implemented ports bitmap.
2020 *
2021 * @returns 32bit bitmask with a bit set for every implemented port.
2022 * @param cPorts Number of ports.
2023 */
2024static uint32_t ahciGetPortsImplemented(unsigned cPorts)
2025{
2026 uint32_t uPortsImplemented = 0;
2027
2028 for (unsigned i = 0; i < cPorts; i++)
2029 uPortsImplemented |= (1 << i);
2030
2031 return uPortsImplemented;
2032}
2033
2034/**
2035 * Reset the entire HBA.
2036 *
2037 * @param pThis The HBA state.
2038 */
2039static void ahciHBAReset(PAHCI pThis)
2040{
2041 unsigned i;
2042 int rc = VINF_SUCCESS;
2043
2044 LogRel(("AHCI#%u: Reset the HBA\n", pThis->CTX_SUFF(pDevIns)->iInstance));
2045
2046 /* Stop the CCC timer. */
2047 if (pThis->regHbaCccCtl & AHCI_HBA_CCC_CTL_EN)
2048 {
2049 rc = TMTimerStop(pThis->CTX_SUFF(pHbaCccTimer));
2050 if (RT_FAILURE(rc))
2051 AssertMsgFailed(("%s: Failed to stop timer!\n", __FUNCTION__));
2052 }
2053
2054 /* Reset every port */
2055 for (i = 0; i < pThis->cPortsImpl; i++)
2056 {
2057 PAHCIPort pAhciPort = &pThis->ahciPort[i];
2058
2059 pAhciPort->iLUN = i;
2060 ahciPortSwReset(pAhciPort);
2061 }
2062
2063 /* Init Global registers */
2064 pThis->regHbaCap = AHCI_HBA_CAP_ISS_SHIFT(AHCI_HBA_CAP_ISS_GEN2) |
2065 AHCI_HBA_CAP_S64A | /* 64bit addressing supported */
2066 AHCI_HBA_CAP_SAM | /* AHCI mode only */
2067 AHCI_HBA_CAP_SNCQ | /* Support native command queuing */
2068 AHCI_HBA_CAP_SSS | /* Staggered spin up */
2069 AHCI_HBA_CAP_CCCS | /* Support command completion coalescing */
2070 AHCI_HBA_CAP_NCS_SET(pThis->cCmdSlotsAvail) | /* Number of command slots we support */
2071 AHCI_HBA_CAP_NP_SET(pThis->cPortsImpl); /* Number of supported ports */
2072 pThis->regHbaCtrl = AHCI_HBA_CTRL_AE;
2073 pThis->regHbaPi = ahciGetPortsImplemented(pThis->cPortsImpl);
2074 pThis->regHbaVs = AHCI_HBA_VS_MJR | AHCI_HBA_VS_MNR;
2075 pThis->regHbaCccCtl = 0;
2076 pThis->regHbaCccPorts = 0;
2077 pThis->uCccTimeout = 0;
2078 pThis->uCccPortNr = 0;
2079 pThis->uCccNr = 0;
2080
2081 /* Clear pending interrupts. */
2082 pThis->regHbaIs = 0;
2083 pThis->u32PortsInterrupted = 0;
2084 ahciHbaClearInterrupt(pThis);
2085
2086 pThis->f64BitAddr = false;
2087 pThis->u32PortsInterrupted = 0;
2088 pThis->f8ByteMMIO4BytesWrittenSuccessfully = false;
2089 /* Clear the HBA Reset bit */
2090 pThis->regHbaCtrl &= ~AHCI_HBA_CTRL_HR;
2091}
2092#endif
2093
2094/**
2095 * Reads from a AHCI controller register.
2096 *
2097 * @returns VBox status code.
2098 *
2099 * @param pAhci The AHCI instance.
2100 * @param uReg The register to write.
2101 * @param pv Where to store the result.
2102 * @param cb Number of bytes read.
2103 */
2104static int ahciRegisterRead(PAHCI pAhci, uint32_t uReg, void *pv, unsigned cb)
2105{
2106 int rc = VINF_SUCCESS;
2107 uint32_t iReg;
2108
2109 /*
2110 * If the access offset is smaller than AHCI_HBA_GLOBAL_SIZE the guest accesses the global registers.
2111 * Otherwise it accesses the registers of a port.
2112 */
2113 if (uReg < AHCI_HBA_GLOBAL_SIZE)
2114 {
2115 iReg = uReg >> 2;
2116 Log3(("%s: Trying to read from global register %u\n", __FUNCTION__, iReg));
2117 if (iReg < RT_ELEMENTS(g_aOpRegs))
2118 {
2119 const AHCIOPREG *pReg = &g_aOpRegs[iReg];
2120 rc = pReg->pfnRead(pAhci, iReg, (uint32_t *)pv);
2121 }
2122 else
2123 {
2124 Log3(("%s: Trying to read global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs)));
2125 *(uint32_t *)pv = 0;
2126 }
2127 }
2128 else
2129 {
2130 uint32_t iRegOffset;
2131 uint32_t iPort;
2132
2133 /* Calculate accessed port. */
2134 uReg -= AHCI_HBA_GLOBAL_SIZE;
2135 iPort = uReg / AHCI_PORT_REGISTER_SIZE;
2136 iRegOffset = (uReg % AHCI_PORT_REGISTER_SIZE);
2137 iReg = iRegOffset >> 2;
2138
2139 Log3(("%s: Trying to read from port %u and register %u\n", __FUNCTION__, iPort, iReg));
2140
2141 if (RT_LIKELY( iPort < pAhci->cPortsImpl
2142 && iReg < RT_ELEMENTS(g_aPortOpRegs)))
2143 {
2144 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg];
2145 rc = pPortReg->pfnRead(pAhci, &pAhci->ahciPort[iPort], iReg, (uint32_t *)pv);
2146 }
2147 else
2148 {
2149 Log3(("%s: Trying to read port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs)));
2150 rc = VINF_IOM_MMIO_UNUSED_00;
2151 }
2152
2153 /*
2154 * Windows Vista tries to read one byte from some registers instead of four.
2155 * Correct the value according to the read size.
2156 */
2157 if (RT_SUCCESS(rc) && cb != sizeof(uint32_t))
2158 {
2159 switch (cb)
2160 {
2161 case 1:
2162 {
2163 uint8_t uNewValue;
2164 uint8_t *p = (uint8_t *)pv;
2165
2166 iRegOffset &= 3;
2167 Log3(("%s: iRegOffset=%u\n", __FUNCTION__, iRegOffset));
2168 uNewValue = p[iRegOffset];
2169 /* Clear old value */
2170 *(uint32_t *)pv = 0;
2171 *(uint8_t *)pv = uNewValue;
2172 break;
2173 }
2174 default:
2175 AssertMsgFailed(("%s: unsupported access width cb=%d iPort=%x iRegOffset=%x iReg=%x!!!\n",
2176 __FUNCTION__, cb, iPort, iRegOffset, iReg));
2177 }
2178 }
2179 }
2180
2181 return rc;
2182}
2183
2184/**
2185 * Writes a value to one of the AHCI controller registers.
2186 *
2187 * @returns VBox status code.
2188 *
2189 * @param pAhci The AHCI instance.
2190 * @param offReg The offset of the register to write to.
2191 * @param u32Value The value to write.
2192 */
2193static int ahciRegisterWrite(PAHCI pAhci, uint32_t offReg, uint32_t u32Value)
2194{
2195 int rc;
2196 uint32_t iReg;
2197
2198 /*
2199 * If the access offset is smaller than 100h the guest accesses the global registers.
2200 * Otherwise it accesses the registers of a port.
2201 */
2202 if (offReg < AHCI_HBA_GLOBAL_SIZE)
2203 {
2204 Log3(("Write global HBA register\n"));
2205 iReg = offReg >> 2;
2206 if (iReg < RT_ELEMENTS(g_aOpRegs))
2207 {
2208 const AHCIOPREG *pReg = &g_aOpRegs[iReg];
2209 rc = pReg->pfnWrite(pAhci, iReg, u32Value);
2210 }
2211 else
2212 {
2213 Log3(("%s: Trying to write global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs)));
2214 rc = VINF_SUCCESS;
2215 }
2216 }
2217 else
2218 {
2219 uint32_t iPort;
2220 Log3(("Write Port register\n"));
2221 /* Calculate accessed port. */
2222 offReg -= AHCI_HBA_GLOBAL_SIZE;
2223 iPort = offReg / AHCI_PORT_REGISTER_SIZE;
2224 iReg = (offReg % AHCI_PORT_REGISTER_SIZE) >> 2;
2225 Log3(("%s: Trying to write to port %u and register %u\n", __FUNCTION__, iPort, iReg));
2226 if (RT_LIKELY( iPort < pAhci->cPortsImpl
2227 && iReg < RT_ELEMENTS(g_aPortOpRegs)))
2228 {
2229 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg];
2230 rc = pPortReg->pfnWrite(pAhci, &pAhci->ahciPort[iPort], iReg, u32Value);
2231 }
2232 else
2233 {
2234 Log3(("%s: Trying to write port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs)));
2235 rc = VINF_SUCCESS;
2236 }
2237 }
2238
2239 return rc;
2240}
2241
2242/**
2243 * Memory mapped I/O Handler for read operations.
2244 *
2245 * @returns VBox status code.
2246 *
2247 * @param pDevIns The device instance.
2248 * @param pvUser User argument.
2249 * @param GCPhysAddr Physical address (in GC) where the read starts.
2250 * @param pv Where to store the result.
2251 * @param cb Number of bytes read.
2252 */
2253PDMBOTHCBDECL(int) ahciMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
2254{
2255 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2256 Log2(("#%d ahciMMIORead: pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp\n", pDevIns->iInstance, pv, cb, pv, cb, GCPhysAddr));
2257 RT_NOREF1(pvUser);
2258
2259 int rc = ahciRegisterRead(pAhci, GCPhysAddr - pAhci->MMIOBase, pv, cb);
2260
2261 Log2(("#%d ahciMMIORead: return pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp rc=%Rrc\n",
2262 pDevIns->iInstance, pv, cb, pv, cb, GCPhysAddr, rc));
2263 return rc;
2264}
2265
2266
2267/**
2268 * Memory mapped I/O Handler for write operations.
2269 *
2270 * @returns VBox status code.
2271 *
2272 * @param pDevIns The device instance.
2273 * @param pvUser User argument.
2274 * @param GCPhysAddr Physical address (in GC) where the read starts.
2275 * @param pv Where to fetch the result.
2276 * @param cb Number of bytes to write.
2277 */
2278PDMBOTHCBDECL(int) ahciMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
2279{
2280 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2281 Assert(cb == 4 || cb == 8);
2282 Assert(!(GCPhysAddr & (cb - 1)));
2283
2284 /* Break up 64 bits writes into two dword writes. */
2285 /** @todo Eliminate this code once the IOM/EM starts taking care of these
2286 * situations. */
2287 if (cb == 8)
2288 {
2289 /*
2290 * Only write the first 4 bytes if they weren't already.
2291 * It is possible that the last write to the register caused a world
2292 * switch and we entered this function again.
2293 * Writing the first 4 bytes again could cause indeterminate behavior
2294 * which can cause errors in the guest.
2295 */
2296 int rc = VINF_SUCCESS;
2297 if (!pAhci->f8ByteMMIO4BytesWrittenSuccessfully)
2298 {
2299 rc = ahciMMIOWrite(pDevIns, pvUser, GCPhysAddr, pv, 4);
2300 if (rc != VINF_SUCCESS)
2301 return rc;
2302
2303 pAhci->f8ByteMMIO4BytesWrittenSuccessfully = true;
2304 }
2305
2306 rc = ahciMMIOWrite(pDevIns, pvUser, GCPhysAddr + 4, (uint8_t *)pv + 4, 4);
2307 /*
2308 * Reset flag again so that the first 4 bytes are written again on the next
2309 * 8byte MMIO access.
2310 */
2311 if (rc == VINF_SUCCESS)
2312 pAhci->f8ByteMMIO4BytesWrittenSuccessfully = false;
2313
2314 return rc;
2315 }
2316
2317 /* Do the access. */
2318 Log2(("#%d ahciMMIOWrite: pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp\n", pDevIns->iInstance, pv, cb, pv, cb, GCPhysAddr));
2319 return ahciRegisterWrite(pAhci, GCPhysAddr - pAhci->MMIOBase, *(uint32_t const *)pv);
2320}
2321
2322PDMBOTHCBDECL(int) ahciLegacyFakeWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
2323{
2324 RT_NOREF5(pDevIns, pvUser, Port, u32, cb);
2325 AssertMsgFailed(("Should not happen\n"));
2326 return VINF_SUCCESS;
2327}
2328
2329PDMBOTHCBDECL(int) ahciLegacyFakeRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
2330{
2331 RT_NOREF5(pDevIns, pvUser, Port, pu32, cb);
2332 AssertMsgFailed(("Should not happen\n"));
2333 return VINF_SUCCESS;
2334}
2335
2336/**
2337 * I/O port handler for writes to the index/data register pair.
2338 *
2339 * @returns VBox status code.
2340 *
2341 * @param pDevIns The device instance.
2342 * @param pvUser User argument.
2343 * @param Port Port address where the write starts.
2344 * @param u32 Where to fetch the result.
2345 * @param cb Number of bytes to write.
2346 */
2347PDMBOTHCBDECL(int) ahciIdxDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
2348{
2349 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2350 int rc = VINF_SUCCESS;
2351 RT_NOREF2(pvUser, cb);
2352
2353 if (Port - pAhci->IOPortBase >= 8)
2354 {
2355 unsigned iReg = (Port - pAhci->IOPortBase - 8) / 4;
2356
2357 Assert(cb == 4);
2358
2359 if (iReg == 0)
2360 {
2361 /* Write the index register. */
2362 pAhci->regIdx = u32;
2363 }
2364 else
2365 {
2366 /** @todo range check? */
2367 Assert(iReg == 1);
2368 rc = ahciRegisterWrite(pAhci, pAhci->regIdx, u32);
2369 if (rc == VINF_IOM_R3_MMIO_WRITE)
2370 rc = VINF_IOM_R3_IOPORT_WRITE;
2371 }
2372 }
2373 /* else: ignore */
2374
2375 Log2(("#%d ahciIdxDataWrite: pu32=%p:{%.*Rhxs} cb=%d Port=%#x rc=%Rrc\n",
2376 pDevIns->iInstance, &u32, cb, &u32, cb, Port, rc));
2377 return rc;
2378}
2379
2380/**
2381 * I/O port handler for reads from the index/data register pair.
2382 *
2383 * @returns VBox status code.
2384 *
2385 * @param pDevIns The device instance.
2386 * @param pvUser User argument.
2387 * @param Port Port address where the read starts.
2388 * @param pu32 Where to fetch the result.
2389 * @param cb Number of bytes to write.
2390 */
2391PDMBOTHCBDECL(int) ahciIdxDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
2392{
2393 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2394 int rc = VINF_SUCCESS;
2395 RT_NOREF1(pvUser);
2396
2397 if (Port - pAhci->IOPortBase >= 8)
2398 {
2399 unsigned iReg = (Port - pAhci->IOPortBase - 8) / 4;
2400
2401 Assert(cb == 4);
2402
2403 if (iReg == 0)
2404 {
2405 /* Read the index register. */
2406 *pu32 = pAhci->regIdx;
2407 }
2408 else
2409 {
2410 Assert(iReg == 1);
2411 /** @todo range check? */
2412 rc = ahciRegisterRead(pAhci, pAhci->regIdx, pu32, cb);
2413 if (rc == VINF_IOM_R3_MMIO_READ)
2414 rc = VINF_IOM_R3_IOPORT_READ;
2415 else if (rc == VINF_IOM_MMIO_UNUSED_00)
2416 rc = VERR_IOM_IOPORT_UNUSED;
2417 }
2418 }
2419 else
2420 *pu32 = UINT32_C(0xffffffff);
2421
2422 Log2(("#%d ahciIdxDataRead: pu32=%p:{%.*Rhxs} cb=%d Port=%#x rc=%Rrc\n",
2423 pDevIns->iInstance, pu32, cb, pu32, cb, Port, rc));
2424 return rc;
2425}
2426
2427#ifdef IN_RING3
2428
2429/**
2430 * @callback_method_impl{FNPCIIOREGIONMAP}
2431 */
2432static DECLCALLBACK(int) ahciR3MMIOMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
2433 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
2434{
2435 RT_NOREF(iRegion, enmType);
2436 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev);
2437
2438 Log2(("%s: registering MMIO area at GCPhysAddr=%RGp cb=%RGp\n", __FUNCTION__, GCPhysAddress, cb));
2439
2440 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
2441 Assert(cb >= 4352);
2442
2443 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
2444 /** @todo change this to IOMMMIO_FLAGS_WRITE_ONLY_DWORD once EM/IOM starts
2445 * handling 2nd DWORD failures on split accesses correctly. */
2446 int rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
2447 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD,
2448 ahciMMIOWrite, ahciMMIORead, "AHCI");
2449 if (RT_FAILURE(rc))
2450 return rc;
2451
2452 if (pThis->fR0Enabled)
2453 {
2454 rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/, "ahciMMIOWrite", "ahciMMIORead");
2455 if (RT_FAILURE(rc))
2456 return rc;
2457 }
2458
2459 if (pThis->fGCEnabled)
2460 {
2461 rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/, "ahciMMIOWrite", "ahciMMIORead");
2462 if (RT_FAILURE(rc))
2463 return rc;
2464 }
2465
2466 pThis->MMIOBase = GCPhysAddress;
2467 return rc;
2468}
2469
2470
2471/**
2472 * @callback_method_impl{FNPCIIOREGIONMAP,
2473 * Map the legacy I/O port ranges to make Solaris work with the
2474 * controller.}
2475 */
2476static DECLCALLBACK(int) ahciR3LegacyFakeIORangeMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
2477 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
2478{
2479 RT_NOREF(iRegion, enmType);
2480 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev);
2481 int rc = VINF_SUCCESS;
2482
2483 Log2(("%s: registering fake I/O area at GCPhysAddr=%RGp cb=%RGp\n", __FUNCTION__, GCPhysAddress, cb));
2484
2485 Assert(enmType == PCI_ADDRESS_SPACE_IO);
2486
2487 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
2488 rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, cb, NULL,
2489 ahciLegacyFakeWrite, ahciLegacyFakeRead, NULL, NULL, "AHCI Fake");
2490 if (RT_FAILURE(rc))
2491 return rc;
2492
2493 if (pThis->fR0Enabled)
2494 {
2495 rc = PDMDevHlpIOPortRegisterR0(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
2496 "ahciLegacyFakeWrite", "ahciLegacyFakeRead", NULL, NULL, "AHCI Fake");
2497 if (RT_FAILURE(rc))
2498 return rc;
2499 }
2500
2501 if (pThis->fGCEnabled)
2502 {
2503 rc = PDMDevHlpIOPortRegisterRC(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
2504 "ahciLegacyFakeWrite", "ahciLegacyFakeRead", NULL, NULL, "AHCI Fake");
2505 if (RT_FAILURE(rc))
2506 return rc;
2507 }
2508
2509 return rc;
2510}
2511
2512/**
2513 * @callback_method_impl{FNPCIIOREGIONMAP,
2514 * Map the BMDMA I/O port range (used for the Index/Data pair register access)}
2515 */
2516static DECLCALLBACK(int) ahciR3IdxDataIORangeMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
2517 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
2518{
2519 RT_NOREF(iRegion, enmType);
2520 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev);
2521 int rc = VINF_SUCCESS;
2522
2523 Log2(("%s: registering fake I/O area at GCPhysAddr=%RGp cb=%RGp\n", __FUNCTION__, GCPhysAddress, cb));
2524
2525 Assert(enmType == PCI_ADDRESS_SPACE_IO);
2526
2527 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
2528 rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, cb, NULL,
2529 ahciIdxDataWrite, ahciIdxDataRead, NULL, NULL, "AHCI IDX/DATA");
2530 if (RT_FAILURE(rc))
2531 return rc;
2532
2533 if (pThis->fR0Enabled)
2534 {
2535 rc = PDMDevHlpIOPortRegisterR0(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
2536 "ahciIdxDataWrite", "ahciIdxDataRead", NULL, NULL, "AHCI IDX/DATA");
2537 if (RT_FAILURE(rc))
2538 return rc;
2539 }
2540
2541 if (pThis->fGCEnabled)
2542 {
2543 rc = PDMDevHlpIOPortRegisterRC(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
2544 "ahciIdxDataWrite", "ahciIdxDataRead", NULL, NULL, "AHCI IDX/DATA");
2545 if (RT_FAILURE(rc))
2546 return rc;
2547 }
2548
2549 pThis->IOPortBase = (RTIOPORT)GCPhysAddress;
2550 return rc;
2551}
2552
2553/* -=-=-=-=-=- PAHCI::ILeds -=-=-=-=-=- */
2554
2555/**
2556 * Gets the pointer to the status LED of a unit.
2557 *
2558 * @returns VBox status code.
2559 * @param pInterface Pointer to the interface structure containing the called function pointer.
2560 * @param iLUN The unit which status LED we desire.
2561 * @param ppLed Where to store the LED pointer.
2562 */
2563static DECLCALLBACK(int) ahciR3Status_QueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
2564{
2565 PAHCI pAhci = PDMILEDPORTS_2_PAHCI(pInterface);
2566 if (iLUN < AHCI_MAX_NR_PORTS_IMPL)
2567 {
2568 *ppLed = &pAhci->ahciPort[iLUN].Led;
2569 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
2570 return VINF_SUCCESS;
2571 }
2572 return VERR_PDM_LUN_NOT_FOUND;
2573}
2574
2575/**
2576 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
2577 */
2578static DECLCALLBACK(void *) ahciR3Status_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
2579{
2580 PAHCI pThis = PDMIBASE_2_PAHCI(pInterface);
2581 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
2582 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);
2583 return NULL;
2584}
2585
2586/**
2587 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
2588 */
2589static DECLCALLBACK(void *) ahciR3PortQueryInterface(PPDMIBASE pInterface, const char *pszIID)
2590{
2591 PAHCIPort pAhciPort = PDMIBASE_2_PAHCIPORT(pInterface);
2592 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pAhciPort->IBase);
2593 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pAhciPort->IPort);
2594 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pAhciPort->IMediaExPort);
2595 return NULL;
2596}
2597
2598/**
2599 * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation}
2600 */
2601static DECLCALLBACK(int) ahciR3PortQueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
2602 uint32_t *piInstance, uint32_t *piLUN)
2603{
2604 PAHCIPort pAhciPort = PDMIMEDIAPORT_2_PAHCIPORT(pInterface);
2605 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
2606
2607 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
2608 AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
2609 AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
2610
2611 *ppcszController = pDevIns->pReg->szName;
2612 *piInstance = pDevIns->iInstance;
2613 *piLUN = pAhciPort->iLUN;
2614
2615 return VINF_SUCCESS;
2616}
2617
2618#ifdef LOG_ENABLED
2619
2620/**
2621 * Dump info about the FIS
2622 *
2623 * @returns nothing
2624 * @param pAhciPort The port the command FIS was read from.
2625 * @param cmdFis The FIS to print info from.
2626 */
2627static void ahciDumpFisInfo(PAHCIPort pAhciPort, uint8_t *cmdFis)
2628{
2629 ahciLog(("%s: *** Begin FIS info dump. ***\n", __FUNCTION__));
2630 /* Print FIS type. */
2631 switch (cmdFis[AHCI_CMDFIS_TYPE])
2632 {
2633 case AHCI_CMDFIS_TYPE_H2D:
2634 {
2635 ahciLog(("%s: Command Fis type: H2D\n", __FUNCTION__));
2636 ahciLog(("%s: Command Fis size: %d bytes\n", __FUNCTION__, AHCI_CMDFIS_TYPE_H2D_SIZE));
2637 if (cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)
2638 ahciLog(("%s: Command register update\n", __FUNCTION__));
2639 else
2640 ahciLog(("%s: Control register update\n", __FUNCTION__));
2641 ahciLog(("%s: CMD=%#04x \"%s\"\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CMD], ATACmdText(cmdFis[AHCI_CMDFIS_CMD])));
2642 ahciLog(("%s: FEAT=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FET]));
2643 ahciLog(("%s: SECTN=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTN]));
2644 ahciLog(("%s: CYLL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLL]));
2645 ahciLog(("%s: CYLH=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLH]));
2646 ahciLog(("%s: HEAD=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_HEAD]));
2647
2648 ahciLog(("%s: SECTNEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTNEXP]));
2649 ahciLog(("%s: CYLLEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLLEXP]));
2650 ahciLog(("%s: CYLHEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLHEXP]));
2651 ahciLog(("%s: FETEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FETEXP]));
2652
2653 ahciLog(("%s: SECTC=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTC]));
2654 ahciLog(("%s: SECTCEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTCEXP]));
2655 ahciLog(("%s: CTL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CTL]));
2656 if (cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
2657 ahciLog(("%s: Reset bit is set\n", __FUNCTION__));
2658 break;
2659 }
2660 case AHCI_CMDFIS_TYPE_D2H:
2661 {
2662 ahciLog(("%s: Command Fis type D2H\n", __FUNCTION__));
2663 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_D2H_SIZE));
2664 break;
2665 }
2666 case AHCI_CMDFIS_TYPE_SETDEVBITS:
2667 {
2668 ahciLog(("%s: Command Fis type Set Device Bits\n", __FUNCTION__));
2669 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE));
2670 break;
2671 }
2672 case AHCI_CMDFIS_TYPE_DMAACTD2H:
2673 {
2674 ahciLog(("%s: Command Fis type DMA Activate H2D\n", __FUNCTION__));
2675 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMAACTD2H_SIZE));
2676 break;
2677 }
2678 case AHCI_CMDFIS_TYPE_DMASETUP:
2679 {
2680 ahciLog(("%s: Command Fis type DMA Setup\n", __FUNCTION__));
2681 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMASETUP_SIZE));
2682 break;
2683 }
2684 case AHCI_CMDFIS_TYPE_PIOSETUP:
2685 {
2686 ahciLog(("%s: Command Fis type PIO Setup\n", __FUNCTION__));
2687 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_PIOSETUP_SIZE));
2688 break;
2689 }
2690 case AHCI_CMDFIS_TYPE_DATA:
2691 {
2692 ahciLog(("%s: Command Fis type Data\n", __FUNCTION__));
2693 break;
2694 }
2695 default:
2696 ahciLog(("%s: ERROR Unknown command FIS type\n", __FUNCTION__));
2697 break;
2698 }
2699 ahciLog(("%s: *** End FIS info dump. ***\n", __FUNCTION__));
2700}
2701
2702/**
2703 * Dump info about the command header
2704 *
2705 * @returns nothing
2706 * @param pAhciPort Pointer to the port the command header was read from.
2707 * @param pCmdHdr The command header to print info from.
2708 */
2709static void ahciDumpCmdHdrInfo(PAHCIPort pAhciPort, CmdHdr *pCmdHdr)
2710{
2711 ahciLog(("%s: *** Begin command header info dump. ***\n", __FUNCTION__));
2712 ahciLog(("%s: Number of Scatter/Gatther List entries: %u\n", __FUNCTION__, AHCI_CMDHDR_PRDTL_ENTRIES(pCmdHdr->u32DescInf)));
2713 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_C)
2714 ahciLog(("%s: Clear busy upon R_OK\n", __FUNCTION__));
2715 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_B)
2716 ahciLog(("%s: BIST Fis\n", __FUNCTION__));
2717 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_R)
2718 ahciLog(("%s: Device Reset Fis\n", __FUNCTION__));
2719 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_P)
2720 ahciLog(("%s: Command prefetchable\n", __FUNCTION__));
2721 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_W)
2722 ahciLog(("%s: Device write\n", __FUNCTION__));
2723 else
2724 ahciLog(("%s: Device read\n", __FUNCTION__));
2725 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_A)
2726 ahciLog(("%s: ATAPI command\n", __FUNCTION__));
2727 else
2728 ahciLog(("%s: ATA command\n", __FUNCTION__));
2729
2730 ahciLog(("%s: Command FIS length %u DW\n", __FUNCTION__, (pCmdHdr->u32DescInf & AHCI_CMDHDR_CFL_MASK)));
2731 ahciLog(("%s: *** End command header info dump. ***\n", __FUNCTION__));
2732}
2733
2734#endif /* LOG_ENABLED */
2735
2736/**
2737 * Post the first D2H FIS from the device into guest memory.
2738 *
2739 * @returns nothing
2740 * @param pAhciPort Pointer to the port which "receives" the FIS.
2741 */
2742static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort)
2743{
2744 uint8_t d2hFis[AHCI_CMDFIS_TYPE_D2H_SIZE];
2745
2746 pAhciPort->fFirstD2HFisSend = true;
2747
2748 ahciLog(("%s: Sending First D2H FIS from FIFO\n", __FUNCTION__));
2749 memset(&d2hFis[0], 0, sizeof(d2hFis));
2750 d2hFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_D2H;
2751 d2hFis[AHCI_CMDFIS_ERR] = 0x01;
2752
2753 d2hFis[AHCI_CMDFIS_STS] = 0x00;
2754
2755 /* Set the signature based on the device type. */
2756 if (pAhciPort->fATAPI)
2757 {
2758 d2hFis[AHCI_CMDFIS_CYLL] = 0x14;
2759 d2hFis[AHCI_CMDFIS_CYLH] = 0xeb;
2760 }
2761 else
2762 {
2763 d2hFis[AHCI_CMDFIS_CYLL] = 0x00;
2764 d2hFis[AHCI_CMDFIS_CYLH] = 0x00;
2765 }
2766
2767 d2hFis[AHCI_CMDFIS_HEAD] = 0x00;
2768 d2hFis[AHCI_CMDFIS_SECTN] = 0x01;
2769 d2hFis[AHCI_CMDFIS_SECTC] = 0x01;
2770
2771 pAhciPort->regTFD = (1 << 8) | ATA_STAT_SEEK | ATA_STAT_WRERR;
2772 if (!pAhciPort->fATAPI)
2773 pAhciPort->regTFD |= ATA_STAT_READY;
2774
2775 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis);
2776}
2777
2778/**
2779 * Post the FIS in the memory area allocated by the guest and set interrupt if necessary.
2780 *
2781 * @returns VBox status code
2782 * @param pAhciPort The port which "receives" the FIS.
2783 * @param uFisType The type of the FIS.
2784 * @param pCmdFis Pointer to the FIS which is to be posted into memory.
2785 */
2786static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *pCmdFis)
2787{
2788 int rc = VINF_SUCCESS;
2789 RTGCPHYS GCPhysAddrRecFis = pAhciPort->GCPhysAddrFb;
2790 unsigned cbFis = 0;
2791
2792 ahciLog(("%s: pAhciPort=%p uFisType=%u pCmdFis=%p\n", __FUNCTION__, pAhciPort, uFisType, pCmdFis));
2793
2794 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
2795 {
2796 AssertMsg(GCPhysAddrRecFis, ("%s: GCPhysAddrRecFis is 0\n", __FUNCTION__));
2797
2798 /* Determine the offset and size of the FIS based on uFisType. */
2799 switch (uFisType)
2800 {
2801 case AHCI_CMDFIS_TYPE_D2H:
2802 {
2803 GCPhysAddrRecFis += AHCI_RECFIS_RFIS_OFFSET;
2804 cbFis = AHCI_CMDFIS_TYPE_D2H_SIZE;
2805 break;
2806 }
2807 case AHCI_CMDFIS_TYPE_SETDEVBITS:
2808 {
2809 GCPhysAddrRecFis += AHCI_RECFIS_SDBFIS_OFFSET;
2810 cbFis = AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE;
2811 break;
2812 }
2813 case AHCI_CMDFIS_TYPE_DMASETUP:
2814 {
2815 GCPhysAddrRecFis += AHCI_RECFIS_DSFIS_OFFSET;
2816 cbFis = AHCI_CMDFIS_TYPE_DMASETUP_SIZE;
2817 break;
2818 }
2819 case AHCI_CMDFIS_TYPE_PIOSETUP:
2820 {
2821 GCPhysAddrRecFis += AHCI_RECFIS_PSFIS_OFFSET;
2822 cbFis = AHCI_CMDFIS_TYPE_PIOSETUP_SIZE;
2823 break;
2824 }
2825 default:
2826 /*
2827 * We should post the unknown FIS into memory too but this never happens because
2828 * we know which FIS types we generate. ;)
2829 */
2830 AssertMsgFailed(("%s: Unknown FIS type!\n", __FUNCTION__));
2831 }
2832
2833 /* Post the FIS into memory. */
2834 ahciLog(("%s: PDMDevHlpPCIPhysWrite GCPhysAddrRecFis=%RGp cbFis=%u\n", __FUNCTION__, GCPhysAddrRecFis, cbFis));
2835 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrRecFis, pCmdFis, cbFis);
2836 }
2837
2838 return rc;
2839}
2840
2841DECLINLINE(void) ahciReqSetStatus(PAHCIREQ pAhciReq, uint8_t u8Error, uint8_t u8Status)
2842{
2843 pAhciReq->cmdFis[AHCI_CMDFIS_ERR] = u8Error;
2844 pAhciReq->cmdFis[AHCI_CMDFIS_STS] = u8Status;
2845}
2846
2847static void ataPadString(uint8_t *pbDst, const char *pbSrc, uint32_t cbSize)
2848{
2849 for (uint32_t i = 0; i < cbSize; i++)
2850 {
2851 if (*pbSrc)
2852 pbDst[i ^ 1] = *pbSrc++;
2853 else
2854 pbDst[i ^ 1] = ' ';
2855 }
2856}
2857
2858static uint32_t ataChecksum(void* ptr, size_t count)
2859{
2860 uint8_t u8Sum = 0xa5, *p = (uint8_t*)ptr;
2861 size_t i;
2862
2863 for (i = 0; i < count; i++)
2864 {
2865 u8Sum += *p++;
2866 }
2867
2868 return (uint8_t)-(int32_t)u8Sum;
2869}
2870
2871static int ahciIdentifySS(PAHCIPort pAhciPort, void *pvBuf)
2872{
2873 uint16_t *p = (uint16_t *)pvBuf;
2874 memset(p, 0, 512);
2875 p[0] = RT_H2LE_U16(0x0040);
2876 p[1] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383));
2877 p[3] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cHeads);
2878 /* Block size; obsolete, but required for the BIOS. */
2879 p[5] = RT_H2LE_U16(512);
2880 p[6] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cSectors);
2881 ataPadString((uint8_t *)(p + 10), pAhciPort->szSerialNumber, AHCI_SERIAL_NUMBER_LENGTH); /* serial number */
2882 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
2883 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
2884 p[22] = RT_H2LE_U16(0); /* ECC bytes per sector */
2885 ataPadString((uint8_t *)(p + 23), pAhciPort->szFirmwareRevision, AHCI_FIRMWARE_REVISION_LENGTH); /* firmware version */
2886 ataPadString((uint8_t *)(p + 27), pAhciPort->szModelNumber, AHCI_MODEL_NUMBER_LENGTH); /* model */
2887#if ATA_MAX_MULT_SECTORS > 1
2888 p[47] = RT_H2LE_U16(0x8000 | ATA_MAX_MULT_SECTORS);
2889#endif
2890 p[48] = RT_H2LE_U16(1); /* dword I/O, used by the BIOS */
2891 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
2892 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
2893 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
2894 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
2895 p[53] = RT_H2LE_U16(1 | 1 << 1 | 1 << 2); /* words 54-58,64-70,88 valid */
2896 p[54] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383));
2897 p[55] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cHeads);
2898 p[56] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cSectors);
2899 p[57] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors);
2900 p[58] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors >> 16);
2901 if (pAhciPort->cMultSectors)
2902 p[59] = RT_H2LE_U16(0x100 | pAhciPort->cMultSectors);
2903 if (pAhciPort->cTotalSectors <= (1 << 28) - 1)
2904 {
2905 p[60] = RT_H2LE_U16(pAhciPort->cTotalSectors);
2906 p[61] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 16);
2907 }
2908 else
2909 {
2910 /* Report maximum number of sectors possible with LBA28 */
2911 p[60] = RT_H2LE_U16(((1 << 28) - 1) & 0xffff);
2912 p[61] = RT_H2LE_U16(((1 << 28) - 1) >> 16);
2913 }
2914 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* MDMA modes supported / mode enabled */
2915 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
2916 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
2917 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
2918 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
2919 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
2920 if ( pAhciPort->fTrimEnabled
2921 || pAhciPort->cbSector != 512
2922 || pAhciPort->pDrvMedia->pfnIsNonRotational(pAhciPort->pDrvMedia))
2923 {
2924 p[80] = RT_H2LE_U16(0x1f0); /* support everything up to ATA/ATAPI-8 ACS */
2925 p[81] = RT_H2LE_U16(0x28); /* conforms to ATA/ATAPI-8 ACS */
2926 }
2927 else
2928 {
2929 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
2930 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
2931 }
2932 p[82] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* supports power management, write cache and look-ahead */
2933 p[83] = RT_H2LE_U16(1 << 14 | 1 << 10 | 1 << 12 | 1 << 13); /* supports LBA48, FLUSH CACHE and FLUSH CACHE EXT */
2934 p[84] = RT_H2LE_U16(1 << 14);
2935 p[85] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* enabled power management, write cache and look-ahead */
2936 p[86] = RT_H2LE_U16(1 << 10 | 1 << 12 | 1 << 13); /* enabled LBA48, FLUSH CACHE and FLUSH CACHE EXT */
2937 p[87] = RT_H2LE_U16(1 << 14);
2938 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* UDMA modes supported / mode enabled */
2939 p[93] = RT_H2LE_U16(0x00);
2940 p[100] = RT_H2LE_U16(pAhciPort->cTotalSectors);
2941 p[101] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 16);
2942 p[102] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 32);
2943 p[103] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 48);
2944
2945 /* valid information, more than one logical sector per physical sector, 2^cLogSectorsPerPhysicalExp logical sectors per physical sector */
2946 if (pAhciPort->cLogSectorsPerPhysicalExp)
2947 p[106] = RT_H2LE_U16(RT_BIT(14) | RT_BIT(13) | pAhciPort->cLogSectorsPerPhysicalExp);
2948
2949 if (pAhciPort->cbSector != 512)
2950 {
2951 uint32_t cSectorSizeInWords = pAhciPort->cbSector / sizeof(uint16_t);
2952 /* Enable reporting of logical sector size. */
2953 p[106] |= RT_H2LE_U16(RT_BIT(12) | RT_BIT(14));
2954 p[117] = RT_H2LE_U16(cSectorSizeInWords);
2955 p[118] = RT_H2LE_U16(cSectorSizeInWords >> 16);
2956 }
2957
2958 if (pAhciPort->pDrvMedia->pfnIsNonRotational(pAhciPort->pDrvMedia))
2959 p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
2960
2961 if (pAhciPort->fTrimEnabled) /** @todo Set bit 14 in word 69 too? (Deterministic read after TRIM). */
2962 p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */
2963
2964 /* The following are SATA specific */
2965 p[75] = RT_H2LE_U16(pAhciPort->CTX_SUFF(pAhci)->cCmdSlotsAvail-1); /* Number of commands we support, 0's based */
2966 p[76] = RT_H2LE_U16((1 << 8) | (1 << 2)); /* Native command queuing and Serial ATA Gen2 (3.0 Gbps) speed supported */
2967
2968 uint32_t uCsum = ataChecksum(p, 510);
2969 p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
2970
2971 return VINF_SUCCESS;
2972}
2973
2974static int ahciR3AtapiIdentify(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
2975{
2976 uint16_t p[256];
2977
2978 memset(p, 0, 512);
2979 /* Removable CDROM, 50us response, 12 byte packets */
2980 p[0] = RT_H2LE_U16(2 << 14 | 5 << 8 | 1 << 7 | 2 << 5 | 0 << 0);
2981 ataPadString((uint8_t *)(p + 10), pAhciPort->szSerialNumber, AHCI_SERIAL_NUMBER_LENGTH); /* serial number */
2982 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
2983 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
2984 ataPadString((uint8_t *)(p + 23), pAhciPort->szFirmwareRevision, AHCI_FIRMWARE_REVISION_LENGTH); /* firmware version */
2985 ataPadString((uint8_t *)(p + 27), pAhciPort->szModelNumber, AHCI_MODEL_NUMBER_LENGTH); /* model */
2986 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
2987 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
2988 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
2989 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
2990 p[53] = RT_H2LE_U16(1 << 1 | 1 << 2); /* words 64-70,88 are valid */
2991 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* MDMA modes supported / mode enabled */
2992 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
2993 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
2994 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
2995 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
2996 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
2997 p[73] = RT_H2LE_U16(0x003e); /* ATAPI CDROM major */
2998 p[74] = RT_H2LE_U16(9); /* ATAPI CDROM minor */
2999 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
3000 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
3001 p[82] = RT_H2LE_U16(1 << 4 | 1 << 9); /* supports packet command set and DEVICE RESET */
3002 p[83] = RT_H2LE_U16(1 << 14);
3003 p[84] = RT_H2LE_U16(1 << 14);
3004 p[85] = RT_H2LE_U16(1 << 4 | 1 << 9); /* enabled packet command set and DEVICE RESET */
3005 p[86] = RT_H2LE_U16(0);
3006 p[87] = RT_H2LE_U16(1 << 14);
3007 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* UDMA modes supported / mode enabled */
3008 p[93] = RT_H2LE_U16((1 | 1 << 1) << ((pAhciPort->iLUN & 1) == 0 ? 0 : 8) | 1 << 13 | 1 << 14);
3009
3010 /* The following are SATA specific */
3011 p[75] = RT_H2LE_U16(31); /* We support 32 commands */
3012 p[76] = RT_H2LE_U16((1 << 8) | (1 << 2)); /* Native command queuing and Serial ATA Gen2 (3.0 Gbps) speed supported */
3013
3014 /* Copy the buffer in to the scatter gather list. */
3015 *pcbData = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq, (void *)&p[0],
3016 RT_MIN(cbData, sizeof(p)), 0 /* cbSkip */);
3017 return VINF_SUCCESS;
3018}
3019
3020/**
3021 * Reset all values after a reset of the attached storage device.
3022 *
3023 * @returns nothing
3024 * @param pAhciPort The port the device is attached to.
3025 * @param pAhciReq The state to get the tag number from.
3026 */
3027static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
3028{
3029 int rc;
3030
3031 /* Send a status good D2H FIS. */
3032 pAhciPort->fResetDevice = false;
3033 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
3034 ahciPostFirstD2HFisIntoMemory(pAhciPort);
3035
3036 /* As this is the first D2H FIS after the reset update the signature in the SIG register of the port. */
3037 if (pAhciPort->fATAPI)
3038 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
3039 else
3040 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
3041 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
3042
3043 rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
3044 AssertRC(rc);
3045}
3046
3047/**
3048 * Initiates a device reset caused by ATA_DEVICE_RESET (ATAPI only).
3049 *
3050 * @returns nothing.
3051 * @param pAhciPort The device to reset.
3052 * @param pAhciReq The task state.
3053 */
3054static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
3055{
3056 ASMAtomicWriteBool(&pAhciPort->fResetDevice, true);
3057
3058 /*
3059 * Because this ATAPI only and ATAPI can't have
3060 * more than one command active at a time the task counter should be 0
3061 * and it is possible to finish the reset now.
3062 */
3063 Assert(ASMAtomicReadU32(&pAhciPort->cTasksActive) == 0);
3064 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
3065}
3066
3067/**
3068 * Create a PIO setup FIS and post it into the memory area of the guest.
3069 *
3070 * @returns nothing.
3071 * @param pAhciPort The port of the SATA controller.
3072 * @param cbTransfer Transfer size of the request.
3073 * @param pCmdFis Pointer to the command FIS from the guest.
3074 * @param fRead Flag whether this is a read request.
3075 * @param fInterrupt If an interrupt should be send to the guest.
3076 */
3077static void ahciSendPioSetupFis(PAHCIPort pAhciPort, size_t cbTransfer, uint8_t *pCmdFis,
3078 bool fRead, bool fInterrupt)
3079{
3080 uint8_t abPioSetupFis[20];
3081 bool fAssertIntr = false;
3082 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
3083
3084 ahciLog(("%s: building PIO setup Fis\n", __FUNCTION__));
3085
3086 AssertMsg( cbTransfer > 0
3087 && cbTransfer <= 65534,
3088 ("Can't send PIO setup FIS for requests with 0 bytes to transfer or greater than 65534\n"));
3089
3090 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
3091 {
3092 memset(&abPioSetupFis[0], 0, sizeof(abPioSetupFis));
3093 abPioSetupFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_PIOSETUP;
3094 abPioSetupFis[AHCI_CMDFIS_BITS] = (fInterrupt ? AHCI_CMDFIS_I : 0);
3095 if (fRead)
3096 abPioSetupFis[AHCI_CMDFIS_BITS] |= AHCI_CMDFIS_D;
3097 abPioSetupFis[AHCI_CMDFIS_STS] = pCmdFis[AHCI_CMDFIS_STS];
3098 abPioSetupFis[AHCI_CMDFIS_ERR] = pCmdFis[AHCI_CMDFIS_ERR];
3099 abPioSetupFis[AHCI_CMDFIS_SECTN] = pCmdFis[AHCI_CMDFIS_SECTN];
3100 abPioSetupFis[AHCI_CMDFIS_CYLL] = pCmdFis[AHCI_CMDFIS_CYLL];
3101 abPioSetupFis[AHCI_CMDFIS_CYLH] = pCmdFis[AHCI_CMDFIS_CYLH];
3102 abPioSetupFis[AHCI_CMDFIS_HEAD] = pCmdFis[AHCI_CMDFIS_HEAD];
3103 abPioSetupFis[AHCI_CMDFIS_SECTNEXP] = pCmdFis[AHCI_CMDFIS_SECTNEXP];
3104 abPioSetupFis[AHCI_CMDFIS_CYLLEXP] = pCmdFis[AHCI_CMDFIS_CYLLEXP];
3105 abPioSetupFis[AHCI_CMDFIS_CYLHEXP] = pCmdFis[AHCI_CMDFIS_CYLHEXP];
3106 abPioSetupFis[AHCI_CMDFIS_SECTC] = pCmdFis[AHCI_CMDFIS_SECTC];
3107 abPioSetupFis[AHCI_CMDFIS_SECTCEXP] = pCmdFis[AHCI_CMDFIS_SECTCEXP];
3108
3109 /* Set transfer count. */
3110 abPioSetupFis[16] = (cbTransfer >> 8) & 0xff;
3111 abPioSetupFis[17] = cbTransfer & 0xff;
3112
3113 /* Update registers. */
3114 pAhciPort->regTFD = (pCmdFis[AHCI_CMDFIS_ERR] << 8) | pCmdFis[AHCI_CMDFIS_STS];
3115
3116 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_PIOSETUP, abPioSetupFis);
3117
3118 if (fInterrupt)
3119 {
3120 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PSS);
3121 /* Check if we should assert an interrupt */
3122 if (pAhciPort->regIE & AHCI_PORT_IE_PSE)
3123 fAssertIntr = true;
3124 }
3125
3126 if (fAssertIntr)
3127 {
3128 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
3129 AssertRC(rc);
3130 }
3131 }
3132}
3133
3134/**
3135 * Build a D2H FIS and post into the memory area of the guest.
3136 *
3137 * @returns Nothing
3138 * @param pAhciPort The port of the SATA controller.
3139 * @param uTag The tag of the request.
3140 * @param pCmdFis Pointer to the command FIS from the guest.
3141 * @param fInterrupt If an interrupt should be send to the guest.
3142 */
3143static void ahciSendD2HFis(PAHCIPort pAhciPort, uint32_t uTag, uint8_t *pCmdFis, bool fInterrupt)
3144{
3145 uint8_t d2hFis[20];
3146 bool fAssertIntr = false;
3147 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
3148
3149 ahciLog(("%s: building D2H Fis\n", __FUNCTION__));
3150
3151 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
3152 {
3153 memset(&d2hFis[0], 0, sizeof(d2hFis));
3154 d2hFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_D2H;
3155 d2hFis[AHCI_CMDFIS_BITS] = (fInterrupt ? AHCI_CMDFIS_I : 0);
3156 d2hFis[AHCI_CMDFIS_STS] = pCmdFis[AHCI_CMDFIS_STS];
3157 d2hFis[AHCI_CMDFIS_ERR] = pCmdFis[AHCI_CMDFIS_ERR];
3158 d2hFis[AHCI_CMDFIS_SECTN] = pCmdFis[AHCI_CMDFIS_SECTN];
3159 d2hFis[AHCI_CMDFIS_CYLL] = pCmdFis[AHCI_CMDFIS_CYLL];
3160 d2hFis[AHCI_CMDFIS_CYLH] = pCmdFis[AHCI_CMDFIS_CYLH];
3161 d2hFis[AHCI_CMDFIS_HEAD] = pCmdFis[AHCI_CMDFIS_HEAD];
3162 d2hFis[AHCI_CMDFIS_SECTNEXP] = pCmdFis[AHCI_CMDFIS_SECTNEXP];
3163 d2hFis[AHCI_CMDFIS_CYLLEXP] = pCmdFis[AHCI_CMDFIS_CYLLEXP];
3164 d2hFis[AHCI_CMDFIS_CYLHEXP] = pCmdFis[AHCI_CMDFIS_CYLHEXP];
3165 d2hFis[AHCI_CMDFIS_SECTC] = pCmdFis[AHCI_CMDFIS_SECTC];
3166 d2hFis[AHCI_CMDFIS_SECTCEXP] = pCmdFis[AHCI_CMDFIS_SECTCEXP];
3167
3168 /* Update registers. */
3169 pAhciPort->regTFD = (pCmdFis[AHCI_CMDFIS_ERR] << 8) | pCmdFis[AHCI_CMDFIS_STS];
3170
3171 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis);
3172
3173 if (pCmdFis[AHCI_CMDFIS_STS] & ATA_STAT_ERR)
3174 {
3175 /* Error bit is set. */
3176 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
3177 if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
3178 fAssertIntr = true;
3179 /*
3180 * Don't mark the command slot as completed because the guest
3181 * needs it to identify the failed command.
3182 */
3183 }
3184 else if (fInterrupt)
3185 {
3186 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
3187 /* Check if we should assert an interrupt */
3188 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
3189 fAssertIntr = true;
3190
3191 /* Mark command as completed. */
3192 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, RT_BIT_32(uTag));
3193 }
3194
3195 if (fAssertIntr)
3196 {
3197 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
3198 AssertRC(rc);
3199 }
3200 }
3201}
3202
3203/**
3204 * Build a SDB Fis and post it into the memory area of the guest.
3205 *
3206 * @returns Nothing
3207 * @param pAhciPort The port for which the SDB Fis is send.
3208 * @param uFinishedTasks Bitmask of finished tasks.
3209 * @param fInterrupt If an interrupt should be asserted.
3210 */
3211static void ahciSendSDBFis(PAHCIPort pAhciPort, uint32_t uFinishedTasks, bool fInterrupt)
3212{
3213 uint32_t sdbFis[2];
3214 bool fAssertIntr = false;
3215 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
3216 PAHCIREQ pTaskErr = ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ);
3217
3218 ahciLog(("%s: Building SDB FIS\n", __FUNCTION__));
3219
3220 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
3221 {
3222 memset(&sdbFis[0], 0, sizeof(sdbFis));
3223 sdbFis[0] = AHCI_CMDFIS_TYPE_SETDEVBITS;
3224 sdbFis[0] |= (fInterrupt ? (1 << 14) : 0);
3225 if (RT_UNLIKELY(pTaskErr))
3226 {
3227 sdbFis[0] = pTaskErr->cmdFis[AHCI_CMDFIS_ERR];
3228 sdbFis[0] |= (pTaskErr->cmdFis[AHCI_CMDFIS_STS] & 0x77) << 16; /* Some bits are marked as reserved and thus are masked out. */
3229
3230 /* Update registers. */
3231 pAhciPort->regTFD = (pTaskErr->cmdFis[AHCI_CMDFIS_ERR] << 8) | pTaskErr->cmdFis[AHCI_CMDFIS_STS];
3232 }
3233 else
3234 {
3235 sdbFis[0] = 0;
3236 sdbFis[0] |= (ATA_STAT_READY | ATA_STAT_SEEK) << 16;
3237 pAhciPort->regTFD = ATA_STAT_READY | ATA_STAT_SEEK;
3238 }
3239
3240 sdbFis[1] = pAhciPort->u32QueuedTasksFinished | uFinishedTasks;
3241
3242 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_SETDEVBITS, (uint8_t *)sdbFis);
3243
3244 if (RT_UNLIKELY(pTaskErr))
3245 {
3246 /* Error bit is set. */
3247 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
3248 if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
3249 fAssertIntr = true;
3250 }
3251
3252 if (fInterrupt)
3253 {
3254 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_SDBS);
3255 /* Check if we should assert an interrupt */
3256 if (pAhciPort->regIE & AHCI_PORT_IE_SDBE)
3257 fAssertIntr = true;
3258 }
3259
3260 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, uFinishedTasks);
3261
3262 if (fAssertIntr)
3263 {
3264 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
3265 AssertRC(rc);
3266 }
3267 }
3268}
3269
3270static uint32_t ahciGetNSectors(uint8_t *pCmdFis, bool fLBA48)
3271{
3272 /* 0 means either 256 (LBA28) or 65536 (LBA48) sectors. */
3273 if (fLBA48)
3274 {
3275 if (!pCmdFis[AHCI_CMDFIS_SECTC] && !pCmdFis[AHCI_CMDFIS_SECTCEXP])
3276 return 65536;
3277 else
3278 return pCmdFis[AHCI_CMDFIS_SECTCEXP] << 8 | pCmdFis[AHCI_CMDFIS_SECTC];
3279 }
3280 else
3281 {
3282 if (!pCmdFis[AHCI_CMDFIS_SECTC])
3283 return 256;
3284 else
3285 return pCmdFis[AHCI_CMDFIS_SECTC];
3286 }
3287}
3288
3289static uint64_t ahciGetSector(PAHCIPort pAhciPort, uint8_t *pCmdFis, bool fLBA48)
3290{
3291 uint64_t iLBA;
3292 if (pCmdFis[AHCI_CMDFIS_HEAD] & 0x40)
3293 {
3294 /* any LBA variant */
3295 if (fLBA48)
3296 {
3297 /* LBA48 */
3298 iLBA = ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLHEXP] << 40) |
3299 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLLEXP] << 32) |
3300 ((uint64_t)pCmdFis[AHCI_CMDFIS_SECTNEXP] << 24) |
3301 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLH] << 16) |
3302 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLL] << 8) |
3303 pCmdFis[AHCI_CMDFIS_SECTN];
3304 }
3305 else
3306 {
3307 /* LBA */
3308 iLBA = ((pCmdFis[AHCI_CMDFIS_HEAD] & 0x0f) << 24) | (pCmdFis[AHCI_CMDFIS_CYLH] << 16) |
3309 (pCmdFis[AHCI_CMDFIS_CYLL] << 8) | pCmdFis[AHCI_CMDFIS_SECTN];
3310 }
3311 }
3312 else
3313 {
3314 /* CHS */
3315 iLBA = ((pCmdFis[AHCI_CMDFIS_CYLH] << 8) | pCmdFis[AHCI_CMDFIS_CYLL]) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors +
3316 (pCmdFis[AHCI_CMDFIS_HEAD] & 0x0f) * pAhciPort->PCHSGeometry.cSectors +
3317 (pCmdFis[AHCI_CMDFIS_SECTN] - 1);
3318 }
3319 return iLBA;
3320}
3321
3322static uint64_t ahciGetSectorQueued(uint8_t *pCmdFis)
3323{
3324 uint64_t uLBA;
3325
3326 uLBA = ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLHEXP] << 40) |
3327 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLLEXP] << 32) |
3328 ((uint64_t)pCmdFis[AHCI_CMDFIS_SECTNEXP] << 24) |
3329 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLH] << 16) |
3330 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLL] << 8) |
3331 pCmdFis[AHCI_CMDFIS_SECTN];
3332
3333 return uLBA;
3334}
3335
3336DECLINLINE(uint32_t) ahciGetNSectorsQueued(uint8_t *pCmdFis)
3337{
3338 if (!pCmdFis[AHCI_CMDFIS_FETEXP] && !pCmdFis[AHCI_CMDFIS_FET])
3339 return 65536;
3340 else
3341 return pCmdFis[AHCI_CMDFIS_FETEXP] << 8 | pCmdFis[AHCI_CMDFIS_FET];
3342}
3343
3344/**
3345 * Copy from guest to host memory worker.
3346 *
3347 * @copydoc AHCIR3MEMCOPYCALLBACK
3348 */
3349static DECLCALLBACK(void) ahciR3CopyBufferFromGuestWorker(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
3350 size_t cbCopy, size_t *pcbSkip)
3351{
3352 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
3353 cbCopy -= cbSkipped;
3354 GCPhys += cbSkipped;
3355 *pcbSkip -= cbSkipped;
3356
3357 while (cbCopy)
3358 {
3359 size_t cbSeg = cbCopy;
3360 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
3361
3362 AssertPtr(pvSeg);
3363 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
3364 GCPhys += cbSeg;
3365 cbCopy -= cbSeg;
3366 }
3367}
3368
3369/**
3370 * Copy from host to guest memory worker.
3371 *
3372 * @copydoc AHCIR3MEMCOPYCALLBACK
3373 */
3374static DECLCALLBACK(void) ahciR3CopyBufferToGuestWorker(PAHCI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf,
3375 size_t cbCopy, size_t *pcbSkip)
3376{
3377 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip);
3378 cbCopy -= cbSkipped;
3379 GCPhys += cbSkipped;
3380 *pcbSkip -= cbSkipped;
3381
3382 while (cbCopy)
3383 {
3384 size_t cbSeg = cbCopy;
3385 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg);
3386
3387 AssertPtr(pvSeg);
3388 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg);
3389 GCPhys += cbSeg;
3390 cbCopy -= cbSeg;
3391 }
3392}
3393
3394/**
3395 * Walks the PRDTL list copying data between the guest and host memory buffers.
3396 *
3397 * @returns Amount of bytes copied.
3398 * @param pThis The AHCI controller device instance.
3399 * @param pAhciReq AHCI request structure.
3400 * @param pfnCopyWorker The copy method to apply for each guest buffer.
3401 * @param pSgBuf The host S/G buffer.
3402 * @param cbSkip How many bytes to skip in advance before starting to copy.
3403 * @param cbCopy How many bytes to copy.
3404 */
3405static size_t ahciR3PrdtlWalk(PAHCI pThis, PAHCIREQ pAhciReq,
3406 PAHCIR3MEMCOPYCALLBACK pfnCopyWorker,
3407 PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy)
3408{
3409 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
3410 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
3411 size_t cbCopied = 0;
3412
3413 /*
3414 * Add the amount to skip to the host buffer size to avoid a
3415 * few conditionals later on.
3416 */
3417 cbCopy += cbSkip;
3418
3419 AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
3420
3421 do
3422 {
3423 SGLEntry aPrdtlEntries[32];
3424 uint32_t cPrdtlEntriesRead = cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)
3425 ? cPrdtlEntries
3426 : RT_ELEMENTS(aPrdtlEntries);
3427
3428 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysPrdtl, &aPrdtlEntries[0],
3429 cPrdtlEntriesRead * sizeof(SGLEntry));
3430
3431 for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbCopy; i++)
3432 {
3433 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
3434 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
3435
3436 cbThisCopy = (uint32_t)RT_MIN(cbThisCopy, cbCopy);
3437
3438 /* Copy into SG entry. */
3439 pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, cbThisCopy, &cbSkip);
3440
3441 cbCopy -= cbThisCopy;
3442 cbCopied += cbThisCopy;
3443 }
3444
3445 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry);
3446 cPrdtlEntries -= cPrdtlEntriesRead;
3447 } while (cPrdtlEntries && cbCopy);
3448
3449 if (cbCopied < cbCopy)
3450 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
3451
3452 return cbCopied;
3453}
3454
3455/**
3456 * Copies a data buffer into the S/G buffer set up by the guest.
3457 *
3458 * @returns Amount of bytes copied to the PRDTL.
3459 * @param pThis The AHCI controller device instance.
3460 * @param pAhciReq AHCI request structure.
3461 * @param pSgBuf The S/G buffer to copy from.
3462 * @param cbSkip How many bytes to skip in advance before starting to copy.
3463 * @param cbCopy How many bytes to copy.
3464 */
3465static size_t ahciR3CopySgBufToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, PRTSGBUF pSgBuf,
3466 size_t cbSkip, size_t cbCopy)
3467{
3468 return ahciR3PrdtlWalk(pThis, pAhciReq, ahciR3CopyBufferToGuestWorker,
3469 pSgBuf, cbSkip, cbCopy);
3470}
3471
3472/**
3473 * Copies the S/G buffer into a data buffer.
3474 *
3475 * @returns Amount of bytes copied from the PRDTL.
3476 * @param pThis The AHCI controller device instance.
3477 * @param pAhciReq AHCI request structure.
3478 * @param pSgBuf The S/G buffer to copy into.
3479 * @param cbSkip How many bytes to skip in advance before starting to copy.
3480 * @param cbCopy How many bytes to copy.
3481 */
3482static size_t ahciR3CopySgBufFromPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, PRTSGBUF pSgBuf,
3483 size_t cbSkip, size_t cbCopy)
3484{
3485 return ahciR3PrdtlWalk(pThis, pAhciReq, ahciR3CopyBufferFromGuestWorker,
3486 pSgBuf, cbSkip, cbCopy);
3487}
3488
3489/**
3490 * Copy a simple memory buffer to the guest memory buffer.
3491 *
3492 * @returns Amount of bytes copied from the PRDTL.
3493 * @param pThis The AHCI controller device instance.
3494 * @param pAhciReq AHCI request structure.
3495 * @param pvSrc The buffer to copy from.
3496 * @param cbSrc How many bytes to copy.
3497 * @param cbSkip How many bytes to skip initially.
3498 */
3499static size_t ahciR3CopyBufferToPrdtl(PAHCI pThis, PAHCIREQ pAhciReq, const void *pvSrc,
3500 size_t cbSrc, size_t cbSkip)
3501{
3502 RTSGSEG Seg;
3503 RTSGBUF SgBuf;
3504 Seg.pvSeg = (void *)pvSrc;
3505 Seg.cbSeg = cbSrc;
3506 RTSgBufInit(&SgBuf, &Seg, 1);
3507 return ahciR3CopySgBufToPrdtl(pThis, pAhciReq, &SgBuf, cbSkip, cbSrc);
3508}
3509
3510/**
3511 * Calculates the size of the guest buffer described by the PRDT.
3512 *
3513 * @returns VBox status code.
3514 * @param pThis The AHCI controller device instance.
3515 * @param pAhciReq AHCI request structure.
3516 * @param pcbPrdt Where to store the size of the guest buffer.
3517 */
3518static int ahciR3PrdtQuerySize(PAHCI pThis, PAHCIREQ pAhciReq, size_t *pcbPrdt)
3519{
3520 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
3521 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
3522 size_t cbPrdt = 0;
3523
3524 do
3525 {
3526 SGLEntry aPrdtlEntries[32];
3527 uint32_t cPrdtlEntriesRead = cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)
3528 ? cPrdtlEntries
3529 : RT_ELEMENTS(aPrdtlEntries);
3530
3531 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhysPrdtl, &aPrdtlEntries[0],
3532 cPrdtlEntriesRead * sizeof(SGLEntry));
3533
3534 for (uint32_t i = 0; i < cPrdtlEntriesRead; i++)
3535 cbPrdt += (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
3536
3537 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry);
3538 cPrdtlEntries -= cPrdtlEntriesRead;
3539 } while (cPrdtlEntries);
3540
3541 *pcbPrdt = cbPrdt;
3542 return VINF_SUCCESS;
3543}
3544
3545/**
3546 * Cancels all active tasks on the port.
3547 *
3548 * @returns Whether all active tasks were canceled.
3549 * @param pAhciPort The AHCI port.
3550 */
3551static bool ahciCancelActiveTasks(PAHCIPort pAhciPort)
3552{
3553 if (pAhciPort->pDrvMediaEx)
3554 {
3555 int rc = pAhciPort->pDrvMediaEx->pfnIoReqCancelAll(pAhciPort->pDrvMediaEx);
3556 AssertRC(rc);
3557 }
3558 return true; /* always true for now because tasks don't use guest memory as the buffer which makes canceling a task impossible. */
3559}
3560
3561/**
3562 * Creates the array of ranges to trim.
3563 *
3564 * @returns VBox status code.
3565 * @param pAhciPort AHCI port state.
3566 * @param pAhciReq The request handling the TRIM request.
3567 * @param idxRangeStart Index of the first range to start copying.
3568 * @param paRanges Where to store the ranges.
3569 * @param cRanges Number of ranges fitting into the array.
3570 * @param pcRanges Where to store the amount of ranges actually copied on success.
3571 */
3572static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t idxRangeStart,
3573 PRTRANGE paRanges, uint32_t cRanges, uint32_t *pcRanges)
3574{
3575 SGLEntry aPrdtlEntries[32];
3576 uint64_t aRanges[64];
3577 uint32_t cPrdtlEntries = pAhciReq->cPrdtlEntries;
3578 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
3579 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
3580 int rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
3581 uint32_t idxRange = 0;
3582
3583 LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq));
3584
3585 AssertMsgReturn(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);
3586
3587 if (!cPrdtlEntries)
3588 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
3589
3590 /* Convert the ranges from ATA to our format. */
3591 while ( cPrdtlEntries
3592 && idxRange < cRanges)
3593 {
3594 uint32_t cPrdtlEntriesRead = RT_MIN(cPrdtlEntries, RT_ELEMENTS(aPrdtlEntries));
3595
3596 rc = VINF_SUCCESS;
3597 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
3598
3599 for (uint32_t i = 0; i < cPrdtlEntriesRead && idxRange < cRanges; i++)
3600 {
3601 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
3602 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
3603
3604 cbThisCopy = RT_MIN(cbThisCopy, sizeof(aRanges));
3605
3606 /* Copy into buffer. */
3607 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy);
3608
3609 for (unsigned idxRangeSrc = 0; idxRangeSrc < RT_ELEMENTS(aRanges) && idxRange < cRanges; idxRangeSrc++)
3610 {
3611 /* Skip range if told to do so. */
3612 if (!idxRangeStart)
3613 {
3614 aRanges[idxRangeSrc] = RT_H2LE_U64(aRanges[idxRangeSrc]);
3615 if (AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) != 0)
3616 {
3617 paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * pAhciPort->cbSector;
3618 paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * pAhciPort->cbSector;
3619 idxRange++;
3620 }
3621 else
3622 break;
3623 }
3624 else
3625 idxRangeStart--;
3626 }
3627 }
3628
3629 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry);
3630 cPrdtlEntries -= cPrdtlEntriesRead;
3631 }
3632
3633 *pcRanges = idxRange;
3634
3635 LogFlowFunc(("returns rc=%Rrc\n", rc));
3636 return rc;
3637}
3638
3639/**
3640 * Allocates a new AHCI request.
3641 *
3642 * @returns A new AHCI request structure or NULL if out of memory.
3643 * @param pAhciPort The AHCI port.
3644 * @param uTag The tag to assign.
3645 */
3646static PAHCIREQ ahciR3ReqAlloc(PAHCIPort pAhciPort, uint32_t uTag)
3647{
3648 PAHCIREQ pAhciReq = NULL;
3649 PDMMEDIAEXIOREQ hIoReq = NULL;
3650
3651 int rc = pAhciPort->pDrvMediaEx->pfnIoReqAlloc(pAhciPort->pDrvMediaEx, &hIoReq, (void **)&pAhciReq,
3652 uTag, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR);
3653 if (RT_SUCCESS(rc))
3654 pAhciReq->hIoReq = hIoReq;
3655 else
3656 pAhciReq = NULL;
3657 return pAhciReq;
3658}
3659
3660/**
3661 * Frees a given AHCI request structure.
3662 *
3663 * @returns nothing.
3664 * @param pAhciPort The AHCI port.
3665 * @param pAhciReq The request to free.
3666 */
3667static void ahciR3ReqFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
3668{
3669 if ( pAhciReq
3670 && !(pAhciReq->fFlags & AHCI_REQ_IS_ON_STACK))
3671 {
3672 int rc = pAhciPort->pDrvMediaEx->pfnIoReqFree(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq);
3673 AssertRC(rc);
3674 }
3675}
3676
3677/**
3678 * Complete a data transfer task by freeing all occupied resources
3679 * and notifying the guest.
3680 *
3681 * @returns Flag whether the given request was canceled inbetween;
3682 *
3683 * @param pAhciPort Pointer to the port where to request completed.
3684 * @param pAhciReq Pointer to the task which finished.
3685 * @param rcReq IPRT status code of the completed request.
3686 */
3687static bool ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcReq)
3688{
3689 bool fCanceled = false;
3690
3691 LogFlowFunc(("pAhciPort=%p pAhciReq=%p rcReq=%d\n",
3692 pAhciPort, pAhciReq, rcReq));
3693
3694 VBOXDD_AHCI_REQ_COMPLETED(pAhciReq, rcReq, pAhciReq->uOffset, pAhciReq->cbTransfer);
3695
3696 if (rcReq != VERR_PDM_MEDIAEX_IOREQ_CANCELED)
3697 {
3698 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ)
3699 {
3700 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciReq->cbTransfer);
3701 pAhciPort->Led.Actual.s.fReading = 0;
3702 }
3703 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE)
3704 {
3705 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciReq->cbTransfer);
3706 pAhciPort->Led.Actual.s.fWriting = 0;
3707 }
3708 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
3709 pAhciPort->Led.Actual.s.fWriting = 0;
3710 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_SCSI)
3711 {
3712 pAhciPort->Led.Actual.s.fWriting = 0;
3713 pAhciPort->Led.Actual.s.fReading = 0;
3714 }
3715
3716 if (RT_FAILURE(rcReq))
3717 {
3718 /* Log the error. */
3719 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
3720 {
3721 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_FLUSH)
3722 LogRel(("AHCI#%uP%u: Flush returned rc=%Rrc\n",
3723 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
3724 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
3725 LogRel(("AHCI#%uP%u: Trim returned rc=%Rrc\n",
3726 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
3727 else
3728 LogRel(("AHCI#%uP%u: %s at offset %llu (%zu bytes left) returned rc=%Rrc\n",
3729 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
3730 pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
3731 ? "Read"
3732 : "Write",
3733 pAhciReq->uOffset,
3734 pAhciReq->cbTransfer, rcReq));
3735 }
3736
3737 ahciReqSetStatus(pAhciReq, ID_ERR, ATA_STAT_READY | ATA_STAT_ERR);
3738 /*
3739 * We have to duplicate the request here as the underlying I/O
3740 * request will be freed later.
3741 */
3742 PAHCIREQ pReqDup = (PAHCIREQ)RTMemDup(pAhciReq, sizeof(AHCIREQ));
3743 if ( pReqDup
3744 && !ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pReqDup, NULL))
3745 RTMemFree(pReqDup);
3746 }
3747 else
3748 {
3749 /* Status will be set already for non I/O requests. */
3750 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_SCSI)
3751 {
3752 if (pAhciReq->u8ScsiSts == SCSI_STATUS_OK)
3753 {
3754 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
3755 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7)
3756 | ((pAhciReq->fFlags & AHCI_REQ_XFER_2_HOST) ? ATAPI_INT_REASON_IO : 0)
3757 | (!pAhciReq->cbTransfer ? ATAPI_INT_REASON_CD : 0);
3758 }
3759 else
3760 {
3761 ahciReqSetStatus(pAhciReq, pAhciPort->abATAPISense[2] << 4, ATA_STAT_READY | ATA_STAT_ERR);
3762 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7) |
3763 ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
3764 pAhciReq->cbTransfer = 0;
3765 LogFlowFunc(("SCSI request completed with %u status\n", pAhciReq->u8ScsiSts));
3766 }
3767 }
3768 else if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_INVALID)
3769 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
3770
3771 /* Write updated command header into memory of the guest. */
3772 uint32_t u32PRDBC = 0;
3773 if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_INVALID)
3774 {
3775 size_t cbXfer = 0;
3776 int rc = pAhciPort->pDrvMediaEx->pfnIoReqQueryXferSize(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq, &cbXfer);
3777 AssertRC(rc);
3778 u32PRDBC = (uint32_t)RT_MIN(cbXfer, pAhciReq->cbTransfer);
3779 }
3780 else
3781 u32PRDBC = (uint32_t)pAhciReq->cbTransfer;
3782
3783 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr + RT_OFFSETOF(CmdHdr, u32PRDBC),
3784 &u32PRDBC, sizeof(u32PRDBC));
3785
3786 if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
3787 {
3788 /*
3789 * The guest tried to transfer more data than there is space in the buffer.
3790 * Terminate task and set the overflow bit.
3791 */
3792 /* Notify the guest. */
3793 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
3794 if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
3795 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
3796 }
3797 }
3798
3799 /*
3800 * Make a copy of the required data now and free the request. Otherwise the guest
3801 * might issue a new request with the same tag and we run into a conflict when allocating
3802 * a new request with the same tag later on.
3803 */
3804 uint32_t fFlags = pAhciReq->fFlags;
3805 uint32_t uTag = pAhciReq->uTag;
3806 size_t cbTransfer = pAhciReq->cbTransfer;
3807 bool fRead = pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ;
3808 uint8_t cmdFis[AHCI_CMDFIS_TYPE_H2D_SIZE];
3809 memcpy(&cmdFis[0], &pAhciReq->cmdFis[0], sizeof(cmdFis));
3810
3811 ahciR3ReqFree(pAhciPort, pAhciReq);
3812
3813 /* Post a PIO setup FIS first if this is a PIO command which transfers data. */
3814 if (fFlags & AHCI_REQ_PIO_DATA)
3815 ahciSendPioSetupFis(pAhciPort, cbTransfer, &cmdFis[0], fRead, false /* fInterrupt */);
3816
3817 if (fFlags & AHCI_REQ_CLEAR_SACT)
3818 {
3819 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ))
3820 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(uTag));
3821 }
3822
3823 if (fFlags & AHCI_REQ_IS_QUEUED)
3824 {
3825 /*
3826 * Always raise an interrupt after task completion; delaying
3827 * this (interrupt coalescing) increases latency and has a significant
3828 * impact on performance (see @bugref{5071})
3829 */
3830 ahciSendSDBFis(pAhciPort, 0, true);
3831 }
3832 else
3833 ahciSendD2HFis(pAhciPort, uTag, &cmdFis[0], true);
3834 }
3835 else
3836 {
3837 /*
3838 * Task was canceled, do the cleanup but DO NOT access the guest memory!
3839 * The guest might use it for other things now because it doesn't know about that task anymore.
3840 */
3841 fCanceled = true;
3842
3843 /* Leave a log message about the canceled request. */
3844 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
3845 {
3846 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_FLUSH)
3847 LogRel(("AHCI#%uP%u: Canceled flush returned rc=%Rrc\n",
3848 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
3849 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
3850 LogRel(("AHCI#%uP%u: Canceled trim returned rc=%Rrc\n",
3851 pAhciPort->CTX_SUFF(pDevIns)->iInstance,pAhciPort->iLUN, rcReq));
3852 else
3853 LogRel(("AHCI#%uP%u: Canceled %s at offset %llu (%zu bytes left) returned rc=%Rrc\n",
3854 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
3855 pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ
3856 ? "read"
3857 : "write",
3858 pAhciReq->uOffset,
3859 pAhciReq->cbTransfer, rcReq));
3860 }
3861
3862 ahciR3ReqFree(pAhciPort, pAhciReq);
3863 }
3864
3865 /*
3866 * Decrement the active task counter as the last step or we might run into a
3867 * hang during power off otherwise (see @bugref{7859}).
3868 * Before it could happen that we signal PDM that we are done while we still have to
3869 * copy the data to the guest but EMT might be busy destroying the driver chains
3870 * below us while we have to delegate copying data to EMT instead of doing it
3871 * on this thread.
3872 */
3873 ASMAtomicDecU32(&pAhciPort->cTasksActive);
3874
3875 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
3876 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
3877
3878 return fCanceled;
3879}
3880
3881/**
3882 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
3883 */
3884static DECLCALLBACK(int) ahciR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
3885 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
3886 size_t cbCopy)
3887{
3888 RT_NOREF1(hIoReq);
3889 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
3890 int rc = VINF_SUCCESS;
3891 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
3892
3893 ahciR3CopySgBufToPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pSgBuf, offDst, cbCopy);
3894
3895 if (pIoReq->fFlags & AHCI_REQ_OVERFLOW)
3896 rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
3897
3898 return rc;
3899}
3900
3901/**
3902 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
3903 */
3904static DECLCALLBACK(int) ahciR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
3905 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
3906 size_t cbCopy)
3907{
3908 RT_NOREF1(hIoReq);
3909 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
3910 int rc = VINF_SUCCESS;
3911 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
3912
3913 ahciR3CopySgBufFromPrdtl(pAhciPort->CTX_SUFF(pAhci), pIoReq, pSgBuf, offSrc, cbCopy);
3914 if (pIoReq->fFlags & AHCI_REQ_OVERFLOW)
3915 rc = VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
3916
3917 return rc;
3918}
3919
3920/**
3921 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqQueryDiscardRanges}
3922 */
3923static DECLCALLBACK(int) ahciR3IoReqQueryDiscardRanges(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
3924 void *pvIoReqAlloc, uint32_t idxRangeStart,
3925 uint32_t cRanges, PRTRANGE paRanges,
3926 uint32_t *pcRanges)
3927{
3928 RT_NOREF1(hIoReq);
3929 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
3930 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc;
3931
3932 return ahciTrimRangesCreate(pAhciPort, pIoReq, idxRangeStart, paRanges, cRanges, pcRanges);
3933}
3934
3935/**
3936 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
3937 */
3938static DECLCALLBACK(int) ahciR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
3939 void *pvIoReqAlloc, int rcReq)
3940{
3941 RT_NOREF(hIoReq);
3942 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
3943 ahciTransferComplete(pAhciPort, (PAHCIREQ)pvIoReqAlloc, rcReq);
3944 return VINF_SUCCESS;
3945}
3946
3947/**
3948 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
3949 */
3950static DECLCALLBACK(void) ahciR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
3951 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
3952{
3953 RT_NOREF2(hIoReq, pvIoReqAlloc);
3954 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
3955
3956 switch (enmState)
3957 {
3958 case PDMMEDIAEXIOREQSTATE_SUSPENDED:
3959 {
3960 /* Make sure the request is not accounted for so the VM can suspend successfully. */
3961 uint32_t cTasksActive = ASMAtomicDecU32(&pAhciPort->cTasksActive);
3962 if (!cTasksActive && pAhciPort->pAhciR3->fSignalIdle)
3963 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
3964 break;
3965 }
3966 case PDMMEDIAEXIOREQSTATE_ACTIVE:
3967 /* Make sure the request is accounted for so the VM suspends only when the request is complete. */
3968 ASMAtomicIncU32(&pAhciPort->cTasksActive);
3969 break;
3970 default:
3971 AssertMsgFailed(("Invalid request state given %u\n", enmState));
3972 }
3973}
3974
3975/**
3976 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
3977 */
3978static DECLCALLBACK(void) ahciR3MediumEjected(PPDMIMEDIAEXPORT pInterface)
3979{
3980 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort);
3981 PAHCI pThis = pAhciPort->CTX_SUFF(pAhci);
3982
3983 if (pThis->pMediaNotify)
3984 {
3985 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
3986 (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
3987 pThis->pMediaNotify, pAhciPort->iLUN);
3988 AssertRC(rc);
3989 }
3990}
3991
3992/**
3993 * Process an non read/write ATA command.
3994 *
3995 * @returns The direction of the data transfer
3996 * @param pAhciPort The AHCI port of the request.
3997 * @param pAhciReq The AHCI request state.
3998 * @param pCmdFis Pointer to the command FIS.
3999 */
4000static PDMMEDIAEXIOREQTYPE ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
4001{
4002 PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID;
4003 bool fLBA48 = false;
4004
4005 AssertMsg(pCmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D, ("FIS is not a host to device Fis!!\n"));
4006
4007 pAhciReq->cbTransfer = 0;
4008
4009 switch (pCmdFis[AHCI_CMDFIS_CMD])
4010 {
4011 case ATA_IDENTIFY_DEVICE:
4012 {
4013 if (pAhciPort->pDrvMedia && !pAhciPort->fATAPI)
4014 {
4015 uint16_t u16Temp[256];
4016
4017 /* Fill the buffer. */
4018 ahciIdentifySS(pAhciPort, u16Temp);
4019
4020 /* Copy the buffer. */
4021 size_t cbCopied = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq,
4022 &u16Temp[0], sizeof(u16Temp), 0 /* cbSkip */);
4023
4024 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
4025 pAhciReq->cbTransfer = cbCopied;
4026 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
4027 }
4028 else
4029 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_SEEK | ATA_STAT_ERR);
4030 break;
4031 }
4032 case ATA_READ_NATIVE_MAX_ADDRESS_EXT:
4033 case ATA_READ_NATIVE_MAX_ADDRESS:
4034 break;
4035 case ATA_SET_FEATURES:
4036 {
4037 switch (pCmdFis[AHCI_CMDFIS_FET])
4038 {
4039 case 0x02: /* write cache enable */
4040 case 0xaa: /* read look-ahead enable */
4041 case 0x55: /* read look-ahead disable */
4042 case 0xcc: /* reverting to power-on defaults enable */
4043 case 0x66: /* reverting to power-on defaults disable */
4044 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
4045 break;
4046 case 0x82: /* write cache disable */
4047 enmType = PDMMEDIAEXIOREQTYPE_FLUSH;
4048 break;
4049 case 0x03:
4050 {
4051 /* set transfer mode */
4052 Log2(("%s: transfer mode %#04x\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC]));
4053 switch (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8)
4054 {
4055 case 0x00: /* PIO default */
4056 case 0x08: /* PIO mode */
4057 break;
4058 case ATA_MODE_MDMA: /* MDMA mode */
4059 pAhciPort->uATATransferMode = (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8) | RT_MIN(pCmdFis[AHCI_CMDFIS_SECTC] & 0x07, ATA_MDMA_MODE_MAX);
4060 break;
4061 case ATA_MODE_UDMA: /* UDMA mode */
4062 pAhciPort->uATATransferMode = (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8) | RT_MIN(pCmdFis[AHCI_CMDFIS_SECTC] & 0x07, ATA_UDMA_MODE_MAX);
4063 break;
4064 }
4065 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
4066 break;
4067 }
4068 default:
4069 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4070 }
4071 break;
4072 }
4073 case ATA_DEVICE_RESET:
4074 {
4075 if (!pAhciPort->fATAPI)
4076 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4077 else
4078 {
4079 /* Reset the device. */
4080 ahciDeviceReset(pAhciPort, pAhciReq);
4081 }
4082 break;
4083 }
4084 case ATA_FLUSH_CACHE_EXT:
4085 case ATA_FLUSH_CACHE:
4086 enmType = PDMMEDIAEXIOREQTYPE_FLUSH;
4087 break;
4088 case ATA_PACKET:
4089 if (!pAhciPort->fATAPI)
4090 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4091 else
4092 enmType = PDMMEDIAEXIOREQTYPE_SCSI;
4093 break;
4094 case ATA_IDENTIFY_PACKET_DEVICE:
4095 if (!pAhciPort->fATAPI)
4096 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4097 else
4098 {
4099 size_t cbData;
4100 ahciR3AtapiIdentify(pAhciReq, pAhciPort, 512, &cbData);
4101
4102 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
4103 pAhciReq->cbTransfer = cbData;
4104 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7)
4105 | ((pAhciReq->fFlags & AHCI_REQ_XFER_2_HOST) ? ATAPI_INT_REASON_IO : 0)
4106 | (!pAhciReq->cbTransfer ? ATAPI_INT_REASON_CD : 0);
4107
4108 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
4109 }
4110 break;
4111 case ATA_SET_MULTIPLE_MODE:
4112 if ( pCmdFis[AHCI_CMDFIS_SECTC] != 0
4113 && ( pCmdFis[AHCI_CMDFIS_SECTC] > ATA_MAX_MULT_SECTORS
4114 || (pCmdFis[AHCI_CMDFIS_SECTC] & (pCmdFis[AHCI_CMDFIS_SECTC] - 1)) != 0))
4115 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4116 else
4117 {
4118 Log2(("%s: set multi sector count to %d\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC]));
4119 pAhciPort->cMultSectors = pCmdFis[AHCI_CMDFIS_SECTC];
4120 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
4121 }
4122 break;
4123 case ATA_STANDBY_IMMEDIATE:
4124 break; /* Do nothing. */
4125 case ATA_CHECK_POWER_MODE:
4126 pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] = 0xff; /* drive active or idle */
4127 /* fall through */
4128 case ATA_INITIALIZE_DEVICE_PARAMETERS:
4129 case ATA_IDLE_IMMEDIATE:
4130 case ATA_RECALIBRATE:
4131 case ATA_NOP:
4132 case ATA_READ_VERIFY_SECTORS_EXT:
4133 case ATA_READ_VERIFY_SECTORS:
4134 case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES:
4135 case ATA_SLEEP:
4136 ahciReqSetStatus(pAhciReq, 0, ATA_STAT_READY | ATA_STAT_SEEK);
4137 break;
4138 case ATA_READ_DMA_EXT:
4139 fLBA48 = true;
4140 case ATA_READ_DMA:
4141 {
4142 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
4143 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
4144 enmType = PDMMEDIAEXIOREQTYPE_READ;
4145 break;
4146 }
4147 case ATA_WRITE_DMA_EXT:
4148 fLBA48 = true;
4149 case ATA_WRITE_DMA:
4150 {
4151 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
4152 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
4153 enmType = PDMMEDIAEXIOREQTYPE_WRITE;
4154 break;
4155 }
4156 case ATA_READ_FPDMA_QUEUED:
4157 {
4158 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
4159 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
4160 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
4161 enmType = PDMMEDIAEXIOREQTYPE_READ;
4162 break;
4163 }
4164 case ATA_WRITE_FPDMA_QUEUED:
4165 {
4166 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
4167 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
4168 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
4169 enmType = PDMMEDIAEXIOREQTYPE_WRITE;
4170 break;
4171 }
4172 case ATA_READ_LOG_EXT:
4173 {
4174 size_t cbLogRead = ((pCmdFis[AHCI_CMDFIS_SECTCEXP] << 8) | pCmdFis[AHCI_CMDFIS_SECTC]) * 512;
4175 unsigned offLogRead = ((pCmdFis[AHCI_CMDFIS_CYLLEXP] << 8) | pCmdFis[AHCI_CMDFIS_CYLL]) * 512;
4176 unsigned iPage = pCmdFis[AHCI_CMDFIS_SECTN];
4177
4178 LogFlow(("Trying to read %zu bytes starting at offset %u from page %u\n", cbLogRead, offLogRead, iPage));
4179
4180 uint8_t aBuf[512];
4181
4182 memset(aBuf, 0, sizeof(aBuf));
4183
4184 if (offLogRead + cbLogRead <= sizeof(aBuf))
4185 {
4186 switch (iPage)
4187 {
4188 case 0x10:
4189 {
4190 LogFlow(("Reading error page\n"));
4191 PAHCIREQ pTaskErr = ASMAtomicXchgPtrT(&pAhciPort->pTaskErr, NULL, PAHCIREQ);
4192 if (pTaskErr)
4193 {
4194 aBuf[0] = (pTaskErr->fFlags & AHCI_REQ_IS_QUEUED) ? pTaskErr->uTag : (1 << 7);
4195 aBuf[2] = pTaskErr->cmdFis[AHCI_CMDFIS_STS];
4196 aBuf[3] = pTaskErr->cmdFis[AHCI_CMDFIS_ERR];
4197 aBuf[4] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTN];
4198 aBuf[5] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLL];
4199 aBuf[6] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLH];
4200 aBuf[7] = pTaskErr->cmdFis[AHCI_CMDFIS_HEAD];
4201 aBuf[8] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTNEXP];
4202 aBuf[9] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLLEXP];
4203 aBuf[10] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLHEXP];
4204 aBuf[12] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTC];
4205 aBuf[13] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTCEXP];
4206
4207 /* Calculate checksum */
4208 uint8_t uChkSum = 0;
4209 for (unsigned i = 0; i < RT_ELEMENTS(aBuf)-1; i++)
4210 uChkSum += aBuf[i];
4211
4212 aBuf[511] = (uint8_t)-(int8_t)uChkSum;
4213
4214 /* Finally free the error task state structure because it is completely unused now. */
4215 RTMemFree(pTaskErr);
4216 }
4217
4218 /*
4219 * Reading this log page results in an abort of all outstanding commands
4220 * and clearing the SActive register and TaskFile register.
4221 *
4222 * See SATA2 1.2 spec chapter 4.2.3.4
4223 */
4224 bool fAbortedAll = ahciCancelActiveTasks(pAhciPort);
4225 Assert(fAbortedAll); NOREF(fAbortedAll);
4226 ahciSendSDBFis(pAhciPort, 0xffffffff, true);
4227
4228 break;
4229 }
4230 }
4231
4232 /* Copy the buffer. */
4233 size_t cbCopied = ahciR3CopyBufferToPrdtl(pAhciPort->CTX_SUFF(pAhci), pAhciReq,
4234 &aBuf[offLogRead], cbLogRead, 0 /* cbSkip */);
4235
4236 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
4237 pAhciReq->cbTransfer = cbCopied;
4238 }
4239
4240 break;
4241 }
4242 case ATA_DATA_SET_MANAGEMENT:
4243 {
4244 if (pAhciPort->fTrimEnabled)
4245 {
4246 /* Check that the trim bit is set and all other bits are 0. */
4247 if ( !(pAhciReq->cmdFis[AHCI_CMDFIS_FET] & UINT16_C(0x01))
4248 || (pAhciReq->cmdFis[AHCI_CMDFIS_FET] & ~UINT16_C(0x1)))
4249 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4250 else
4251 enmType = PDMMEDIAEXIOREQTYPE_DISCARD;
4252 break;
4253 }
4254 /* else: fall through and report error to the guest. */
4255 }
4256 /* All not implemented commands go below. */
4257 case ATA_SECURITY_FREEZE_LOCK:
4258 case ATA_SMART:
4259 case ATA_NV_CACHE:
4260 case ATA_IDLE:
4261 case ATA_TRUSTED_RECEIVE_DMA: /* Windows 8+ */
4262 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4263 break;
4264 default: /* For debugging purposes. */
4265 AssertMsgFailed(("Unknown command issued (%#x)\n", pCmdFis[AHCI_CMDFIS_CMD]));
4266 ahciReqSetStatus(pAhciReq, ABRT_ERR, ATA_STAT_READY | ATA_STAT_ERR);
4267 }
4268
4269 return enmType;
4270}
4271
4272/**
4273 * Retrieve a command FIS from guest memory.
4274 *
4275 * @returns whether the H2D FIS was successfully read from the guest memory.
4276 * @param pAhciPort The AHCI port of the request.
4277 * @param pAhciReq The state of the actual task.
4278 */
4279static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
4280{
4281 AssertMsgReturn(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb,
4282 ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__),
4283 false);
4284
4285 /*
4286 * First we are reading the command header pointed to by regCLB.
4287 * From this we get the address of the command table which we are reading too.
4288 * We can process the Command FIS afterwards.
4289 */
4290 CmdHdr cmdHdr;
4291 pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr);
4292 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdLst=%RGp cbCmdHdr=%u\n", __FUNCTION__,
4293 pAhciReq->GCPhysCmdHdrAddr, sizeof(CmdHdr)));
4294 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &cmdHdr, sizeof(CmdHdr));
4295
4296#ifdef LOG_ENABLED
4297 /* Print some infos about the command header. */
4298 ahciDumpCmdHdrInfo(pAhciPort, &cmdHdr);
4299#endif
4300
4301 RTGCPHYS GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(cmdHdr.u32CmdTblAddrUp, cmdHdr.u32CmdTblAddr);
4302
4303 AssertMsgReturn((cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
4304 ("This is not a command FIS!!\n"),
4305 false);
4306
4307 /* Read the command Fis. */
4308 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdTbl=%RGp cbCmdFis=%u\n", __FUNCTION__, GCPhysAddrCmdTbl, AHCI_CMDFIS_TYPE_H2D_SIZE));
4309 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);
4310
4311 AssertMsgReturn(pAhciReq->cmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D,
4312 ("This is not a command FIS\n"),
4313 false);
4314
4315 /* Set transfer direction. */
4316 pAhciReq->fFlags |= (cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? 0 : AHCI_REQ_XFER_2_HOST;
4317
4318 /* If this is an ATAPI command read the atapi command. */
4319 if (cmdHdr.u32DescInf & AHCI_CMDHDR_A)
4320 {
4321 GCPhysAddrCmdTbl += AHCI_CMDHDR_ACMD_OFFSET;
4322 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->aATAPICmd[0], ATAPI_PACKET_SIZE);
4323 }
4324
4325 /* We "received" the FIS. Clear the BSY bit in regTFD. */
4326 if ((cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT))
4327 {
4328 /*
4329 * We need to send a FIS which clears the busy bit if this is a queued command so that the guest can queue other commands.
4330 * but this FIS does not assert an interrupt
4331 */
4332 ahciSendD2HFis(pAhciPort, pAhciReq->uTag, pAhciReq->cmdFis, false);
4333 pAhciPort->regTFD &= ~AHCI_PORT_TFD_BSY;
4334 }
4335
4336 pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32(cmdHdr.u32CmdTblAddrUp, cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
4337 pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES(cmdHdr.u32DescInf);
4338
4339#ifdef LOG_ENABLED
4340 /* Print some infos about the FIS. */
4341 ahciDumpFisInfo(pAhciPort, &pAhciReq->cmdFis[0]);
4342
4343 /* Print the PRDT */
4344 ahciLog(("PRDT address %RGp number of entries %u\n", pAhciReq->GCPhysPrdtl, pAhciReq->cPrdtlEntries));
4345 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
4346
4347 for (unsigned i = 0; i < pAhciReq->cPrdtlEntries; i++)
4348 {
4349 SGLEntry SGEntry;
4350
4351 ahciLog(("Entry %u at address %RGp\n", i, GCPhysPrdtl));
4352 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysPrdtl, &SGEntry, sizeof(SGLEntry));
4353
4354 RTGCPHYS GCPhysDataAddr = AHCI_RTGCPHYS_FROM_U32(SGEntry.u32DBAUp, SGEntry.u32DBA);
4355 ahciLog(("GCPhysAddr=%RGp Size=%u\n", GCPhysDataAddr, SGEntry.u32DescInf & SGLENTRY_DESCINF_DBC));
4356
4357 GCPhysPrdtl += sizeof(SGLEntry);
4358 }
4359#endif
4360
4361 return true;
4362}
4363
4364/**
4365 * Submits a given request for execution.
4366 *
4367 * @returns Flag whether the request was canceled inbetween.
4368 * @param pAhciPort The port the request is for.
4369 * @param pAhciReq The request to submit.
4370 * @param enmType The request type.
4371 */
4372static bool ahciR3ReqSubmit(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, PDMMEDIAEXIOREQTYPE enmType)
4373{
4374 int rc = VINF_SUCCESS;
4375 bool fReqCanceled = false;
4376
4377 VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, pAhciReq->enmType, pAhciReq->uOffset, pAhciReq->cbTransfer);
4378
4379 if (enmType == PDMMEDIAEXIOREQTYPE_FLUSH)
4380 rc = pAhciPort->pDrvMediaEx->pfnIoReqFlush(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq);
4381 else if (enmType == PDMMEDIAEXIOREQTYPE_DISCARD)
4382 {
4383 uint32_t cRangesMax;
4384
4385 /* The data buffer contains LBA range entries. Each range is 8 bytes big. */
4386 if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP])
4387 cRangesMax = 65536 * 512 / 8;
4388 else
4389 cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8;
4390
4391 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
4392 rc = pAhciPort->pDrvMediaEx->pfnIoReqDiscard(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
4393 cRangesMax);
4394 }
4395 else if (enmType == PDMMEDIAEXIOREQTYPE_READ)
4396 {
4397 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
4398 rc = pAhciPort->pDrvMediaEx->pfnIoReqRead(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
4399 pAhciReq->uOffset, pAhciReq->cbTransfer);
4400 }
4401 else if (enmType == PDMMEDIAEXIOREQTYPE_WRITE)
4402 {
4403 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
4404 rc = pAhciPort->pDrvMediaEx->pfnIoReqWrite(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
4405 pAhciReq->uOffset, pAhciReq->cbTransfer);
4406 }
4407 else if (enmType == PDMMEDIAEXIOREQTYPE_SCSI)
4408 {
4409 size_t cbBuf = 0;
4410
4411 if (pAhciReq->cPrdtlEntries)
4412 rc = ahciR3PrdtQuerySize(pAhciPort->CTX_SUFF(pAhci), pAhciReq, &cbBuf);
4413 pAhciReq->cbTransfer = cbBuf;
4414 if (RT_SUCCESS(rc))
4415 {
4416 if (cbBuf && (pAhciReq->fFlags & AHCI_REQ_XFER_2_HOST))
4417 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
4418 else if (cbBuf)
4419 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
4420 rc = pAhciPort->pDrvMediaEx->pfnIoReqSendScsiCmd(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq,
4421 0, &pAhciReq->aATAPICmd[0], ATAPI_PACKET_SIZE,
4422 PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, cbBuf,
4423 &pAhciPort->abATAPISense[0], sizeof(pAhciPort->abATAPISense),
4424 &pAhciReq->u8ScsiSts, 30 * RT_MS_1SEC);
4425 }
4426 }
4427
4428 if (rc == VINF_SUCCESS)
4429 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
4430 else if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
4431 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc);
4432
4433 return fReqCanceled;
4434}
4435
4436/**
4437 * Prepares the command for execution coping it from guest memory and doing a few
4438 * validation checks on it.
4439 *
4440 * @returns Whether the command was successfully fetched from guest memory and
4441 * can be continued.
4442 * @param pAhciPort The AHCI port the request is for.
4443 * @param pAhciReq Request structure to copy the command to.
4444 */
4445static bool ahciR3CmdPrepare(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
4446{
4447 /* Set current command slot */
4448 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
4449
4450 bool fContinue = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
4451 if (fContinue)
4452 {
4453 /* Mark the task as processed by the HBA if this is a queued task so that it doesn't occur in the CI register anymore. */
4454 if (pAhciPort->regSACT & RT_BIT_32(pAhciReq->uTag))
4455 {
4456 pAhciReq->fFlags |= AHCI_REQ_CLEAR_SACT;
4457 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, RT_BIT_32(pAhciReq->uTag));
4458 }
4459
4460 if (pAhciReq->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)
4461 {
4462 /*
4463 * It is possible that the request counter can get one higher than the maximum because
4464 * the request counter is decremented after the guest was notified about the completed
4465 * request (see @bugref{7859}). If the completing thread is preempted in between the
4466 * guest might already issue another request before the request counter is decremented
4467 * which would trigger the following assertion incorrectly in the past.
4468 */
4469 AssertLogRelMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) <= AHCI_NR_COMMAND_SLOTS,
4470 ("AHCI#%uP%u: There are more than %u (+1) requests active",
4471 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
4472 AHCI_NR_COMMAND_SLOTS));
4473 ASMAtomicIncU32(&pAhciPort->cTasksActive);
4474 }
4475 else
4476 {
4477 /* If the reset bit is set put the device into reset state. */
4478 if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
4479 {
4480 ahciLog(("%s: Setting device into reset state\n", __FUNCTION__));
4481 pAhciPort->fResetDevice = true;
4482 ahciSendD2HFis(pAhciPort, pAhciReq->uTag, pAhciReq->cmdFis, true);
4483 }
4484 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
4485 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
4486 else /* We are not in a reset state update the control registers. */
4487 AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__));
4488
4489 fContinue = false;
4490 }
4491 }
4492 else
4493 {
4494 /*
4495 * Couldn't find anything in either the AHCI or SATA spec which
4496 * indicates what should be done if the FIS is not read successfully.
4497 * The closest thing is in the state machine, stating that the device
4498 * should go into idle state again (SATA spec 1.0 chapter 8.7.1).
4499 * Do the same here and ignore any corrupt FIS types, after all
4500 * the guest messed up everything and this behavior is undefined.
4501 */
4502 fContinue = false;
4503 }
4504
4505 return fContinue;
4506}
4507
4508/**
4509 * Transmit queue consumer
4510 * Queue a new async task.
4511 *
4512 * @returns Success indicator.
4513 * If false the item will not be removed and the flushing will stop.
4514 * @param pDevIns The device instance.
4515 * @param pItem The item to consume. Upon return this item will be freed.
4516 */
4517static DECLCALLBACK(bool) ahciNotifyQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem)
4518{
4519 PDEVPORTNOTIFIERQUEUEITEM pNotifierItem = (PDEVPORTNOTIFIERQUEUEITEM)pItem;
4520 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
4521 PAHCIPort pAhciPort = &pThis->ahciPort[pNotifierItem->iPort];
4522 int rc = VINF_SUCCESS;
4523
4524 ahciLog(("%s: Got notification from GC\n", __FUNCTION__));
4525 /* Notify the async IO thread. */
4526 rc = SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
4527 AssertRC(rc);
4528
4529 return true;
4530}
4531
4532/* The async IO thread for one port. */
4533static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
4534{
4535 RT_NOREF(pDevIns);
4536 PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
4537 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
4538 int rc = VINF_SUCCESS;
4539
4540 ahciLog(("%s: Port %d entering async IO loop.\n", __FUNCTION__, pAhciPort->iLUN));
4541
4542 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
4543 return VINF_SUCCESS;
4544
4545 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
4546 {
4547 unsigned idx = 0;
4548 uint32_t u32Tasks = 0;
4549 uint32_t u32RegHbaCtrl = 0;
4550
4551 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, true);
4552 u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
4553 if (!u32Tasks)
4554 {
4555 Assert(ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping));
4556 rc = SUPSemEventWaitNoResume(pAhci->pSupDrvSession, pAhciPort->hEvtProcess, RT_INDEFINITE_WAIT);
4557 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
4558 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
4559 break;
4560 LogFlowFunc(("Woken up with rc=%Rrc\n", rc));
4561 u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
4562 }
4563
4564 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, false);
4565 ASMAtomicIncU32(&pAhci->cThreadsActive);
4566
4567 /* Check whether the thread should be suspended. */
4568 if (pAhci->fSignalIdle)
4569 {
4570 if (!ASMAtomicDecU32(&pAhci->cThreadsActive))
4571 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
4572 continue;
4573 }
4574
4575 /*
4576 * Check whether the global host controller bit is set and go to sleep immediately again
4577 * if it is set.
4578 */
4579 u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl);
4580 if ( u32RegHbaCtrl & AHCI_HBA_CTRL_HR
4581 && !ASMAtomicDecU32(&pAhci->cThreadsActive))
4582 {
4583 ahciHBAReset(pAhci);
4584 if (pAhci->fSignalIdle)
4585 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
4586 continue;
4587 }
4588
4589 idx = ASMBitFirstSetU32(u32Tasks);
4590 while ( idx
4591 && !pAhciPort->fPortReset)
4592 {
4593 bool fReqCanceled = false;
4594
4595 /* Decrement to get the slot number. */
4596 idx--;
4597 ahciLog(("%s: Processing command at slot %d\n", __FUNCTION__, idx));
4598
4599 PAHCIREQ pAhciReq = ahciR3ReqAlloc(pAhciPort, idx);
4600 if (RT_LIKELY(pAhciReq))
4601 {
4602 pAhciReq->uTag = idx;
4603 pAhciReq->fFlags = 0;
4604
4605 bool fContinue = ahciR3CmdPrepare(pAhciPort, pAhciReq);
4606 if (fContinue)
4607 {
4608 PDMMEDIAEXIOREQTYPE enmType = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);
4609 pAhciReq->enmType = enmType;
4610
4611 if (enmType != PDMMEDIAEXIOREQTYPE_INVALID)
4612 fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmType);
4613 else
4614 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);
4615 } /* Command */
4616 else
4617 ahciR3ReqFree(pAhciPort, pAhciReq);
4618 }
4619 else /* !Request allocated, use on stack variant to signal the error. */
4620 {
4621 AHCIREQ Req;
4622 Req.uTag = idx;
4623 Req.fFlags = AHCI_REQ_IS_ON_STACK;
4624
4625 bool fContinue = ahciR3CmdPrepare(pAhciPort, &Req);
4626 if (fContinue)
4627 fReqCanceled = ahciTransferComplete(pAhciPort, &Req, VERR_NO_MEMORY);
4628 }
4629
4630 /*
4631 * Don't process other requests if the last one was canceled,
4632 * the others are not valid anymore.
4633 */
4634 if (fReqCanceled)
4635 break;
4636
4637 u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */
4638 idx = ASMBitFirstSetU32(u32Tasks);
4639 } /* while tasks available */
4640
4641 /* Check whether a port reset was active. */
4642 if ( ASMAtomicReadBool(&pAhciPort->fPortReset)
4643 && (pAhciPort->regSCTL & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_NINIT)
4644 ahciPortResetFinish(pAhciPort);
4645
4646 /*
4647 * Check whether a host controller reset is pending and execute the reset
4648 * if this is the last active thread.
4649 */
4650 u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl);
4651 uint32_t cThreadsActive = ASMAtomicDecU32(&pAhci->cThreadsActive);
4652 if ( (u32RegHbaCtrl & AHCI_HBA_CTRL_HR)
4653 && !cThreadsActive)
4654 ahciHBAReset(pAhci);
4655
4656 if (!cThreadsActive && pAhci->fSignalIdle)
4657 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
4658 } /* While running */
4659
4660 ahciLog(("%s: Port %d async IO thread exiting\n", __FUNCTION__, pAhciPort->iLUN));
4661 return VINF_SUCCESS;
4662}
4663
4664/**
4665 * Unblock the async I/O thread so it can respond to a state change.
4666 *
4667 * @returns VBox status code.
4668 * @param pDevIns The device instance.
4669 * @param pThread The send thread.
4670 */
4671static DECLCALLBACK(int) ahciAsyncIOLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
4672{
4673 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
4674 PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
4675 return SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
4676}
4677
4678/* -=-=-=-=- DBGF -=-=-=-=- */
4679
4680/**
4681 * AHCI status info callback.
4682 *
4683 * @param pDevIns The device instance.
4684 * @param pHlp The output helpers.
4685 * @param pszArgs The arguments.
4686 */
4687static DECLCALLBACK(void) ahciR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4688{
4689 RT_NOREF(pszArgs);
4690 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
4691
4692 /*
4693 * Show info.
4694 */
4695 pHlp->pfnPrintf(pHlp,
4696 "%s#%d: mmio=%RGp ports=%u GC=%RTbool R0=%RTbool\n",
4697 pDevIns->pReg->szName,
4698 pDevIns->iInstance,
4699 pThis->MMIOBase,
4700 pThis->cPortsImpl,
4701 pThis->fGCEnabled ? true : false,
4702 pThis->fR0Enabled ? true : false);
4703
4704 /*
4705 * Show global registers.
4706 */
4707 pHlp->pfnPrintf(pHlp, "HbaCap=%#x\n", pThis->regHbaCap);
4708 pHlp->pfnPrintf(pHlp, "HbaCtrl=%#x\n", pThis->regHbaCtrl);
4709 pHlp->pfnPrintf(pHlp, "HbaIs=%#x\n", pThis->regHbaIs);
4710 pHlp->pfnPrintf(pHlp, "HbaPi=%#x", pThis->regHbaPi);
4711 pHlp->pfnPrintf(pHlp, "HbaVs=%#x\n", pThis->regHbaVs);
4712 pHlp->pfnPrintf(pHlp, "HbaCccCtl=%#x\n", pThis->regHbaCccCtl);
4713 pHlp->pfnPrintf(pHlp, "HbaCccPorts=%#x\n", pThis->regHbaCccPorts);
4714 pHlp->pfnPrintf(pHlp, "PortsInterrupted=%#x\n", pThis->u32PortsInterrupted);
4715
4716 /*
4717 * Per port data.
4718 */
4719 for (unsigned i = 0; i < pThis->cPortsImpl; i++)
4720 {
4721 PAHCIPort pThisPort = &pThis->ahciPort[i];
4722
4723 pHlp->pfnPrintf(pHlp, "Port %d: device-attached=%RTbool\n",
4724 pThisPort->iLUN, pThisPort->pDrvBase != NULL);
4725 pHlp->pfnPrintf(pHlp, "PortClb=%#x\n", pThisPort->regCLB);
4726 pHlp->pfnPrintf(pHlp, "PortClbU=%#x\n", pThisPort->regCLBU);
4727 pHlp->pfnPrintf(pHlp, "PortFb=%#x\n", pThisPort->regFB);
4728 pHlp->pfnPrintf(pHlp, "PortFbU=%#x\n", pThisPort->regFBU);
4729 pHlp->pfnPrintf(pHlp, "PortIs=%#x\n", pThisPort->regIS);
4730 pHlp->pfnPrintf(pHlp, "PortIe=%#x\n", pThisPort->regIE);
4731 pHlp->pfnPrintf(pHlp, "PortCmd=%#x\n", pThisPort->regCMD);
4732 pHlp->pfnPrintf(pHlp, "PortTfd=%#x\n", pThisPort->regTFD);
4733 pHlp->pfnPrintf(pHlp, "PortSig=%#x\n", pThisPort->regSIG);
4734 pHlp->pfnPrintf(pHlp, "PortSSts=%#x\n", pThisPort->regSSTS);
4735 pHlp->pfnPrintf(pHlp, "PortSCtl=%#x\n", pThisPort->regSCTL);
4736 pHlp->pfnPrintf(pHlp, "PortSErr=%#x\n", pThisPort->regSERR);
4737 pHlp->pfnPrintf(pHlp, "PortSAct=%#x\n", pThisPort->regSACT);
4738 pHlp->pfnPrintf(pHlp, "PortCi=%#x\n", pThisPort->regCI);
4739 pHlp->pfnPrintf(pHlp, "PortPhysClb=%RGp\n", pThisPort->GCPhysAddrClb);
4740 pHlp->pfnPrintf(pHlp, "PortPhysFb=%RGp\n", pThisPort->GCPhysAddrFb);
4741 pHlp->pfnPrintf(pHlp, "PortActTasksActive=%u\n", pThisPort->cTasksActive);
4742 pHlp->pfnPrintf(pHlp, "PortPoweredOn=%RTbool\n", pThisPort->fPoweredOn);
4743 pHlp->pfnPrintf(pHlp, "PortSpunUp=%RTbool\n", pThisPort->fSpunUp);
4744 pHlp->pfnPrintf(pHlp, "PortFirstD2HFisSend=%RTbool\n", pThisPort->fFirstD2HFisSend);
4745 pHlp->pfnPrintf(pHlp, "PortATAPI=%RTbool\n", pThisPort->fATAPI);
4746 pHlp->pfnPrintf(pHlp, "PortTasksFinished=%#x\n", pThisPort->u32TasksFinished);
4747 pHlp->pfnPrintf(pHlp, "PortQueuedTasksFinished=%#x\n", pThisPort->u32QueuedTasksFinished);
4748 pHlp->pfnPrintf(pHlp, "PortTasksNew=%#x\n", pThisPort->u32TasksNew);
4749 pHlp->pfnPrintf(pHlp, "\n");
4750 }
4751}
4752
4753/* -=-=-=-=- Helper -=-=-=-=- */
4754
4755/**
4756 * Checks if all asynchronous I/O is finished, both AHCI and IDE.
4757 *
4758 * Used by ahciR3Reset, ahciR3Suspend and ahciR3PowerOff. ahciR3SavePrep makes
4759 * use of it in strict builds (which is why it's up here).
4760 *
4761 * @returns true if quiesced, false if busy.
4762 * @param pDevIns The device instance.
4763 */
4764static bool ahciR3AllAsyncIOIsFinished(PPDMDEVINS pDevIns)
4765{
4766 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
4767
4768 if (pThis->cThreadsActive)
4769 return false;
4770
4771 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ahciPort); i++)
4772 {
4773 PAHCIPort pThisPort = &pThis->ahciPort[i];
4774 if (pThisPort->pDrvBase)
4775 {
4776 if ( (pThisPort->cTasksActive != 0)
4777 || (pThisPort->u32TasksNew != 0))
4778 return false;
4779 }
4780 }
4781 return true;
4782}
4783
4784/* -=-=-=-=- Saved State -=-=-=-=- */
4785
4786/**
4787 * @callback_method_impl{FNSSMDEVSAVEPREP}
4788 */
4789static DECLCALLBACK(int) ahciR3SavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
4790{
4791 RT_NOREF(pDevIns, pSSM);
4792 Assert(ahciR3AllAsyncIOIsFinished(pDevIns));
4793 return VINF_SUCCESS;
4794}
4795
4796/**
4797 * @callback_method_impl{FNSSMDEVLOADPREP}
4798 */
4799static DECLCALLBACK(int) ahciR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
4800{
4801 RT_NOREF(pDevIns, pSSM);
4802 Assert(ahciR3AllAsyncIOIsFinished(pDevIns));
4803 return VINF_SUCCESS;
4804}
4805
4806/**
4807 * @callback_method_impl{FNSSMDEVLIVEEXEC}
4808 */
4809static DECLCALLBACK(int) ahciR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
4810{
4811 RT_NOREF(uPass);
4812 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
4813
4814 /* config. */
4815 SSMR3PutU32(pSSM, pThis->cPortsImpl);
4816 for (uint32_t i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
4817 {
4818 SSMR3PutBool(pSSM, pThis->ahciPort[i].pDrvBase != NULL);
4819 SSMR3PutBool(pSSM, pThis->ahciPort[i].fHotpluggable);
4820 SSMR3PutStrZ(pSSM, pThis->ahciPort[i].szSerialNumber);
4821 SSMR3PutStrZ(pSSM, pThis->ahciPort[i].szFirmwareRevision);
4822 SSMR3PutStrZ(pSSM, pThis->ahciPort[i].szModelNumber);
4823 }
4824
4825 static const char *s_apszIdeEmuPortNames[4] = { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
4826 for (uint32_t i = 0; i < RT_ELEMENTS(s_apszIdeEmuPortNames); i++)
4827 {
4828 uint32_t iPort;
4829 int rc = CFGMR3QueryU32Def(pDevIns->pCfg, s_apszIdeEmuPortNames[i], &iPort, i);
4830 AssertRCReturn(rc, rc);
4831 SSMR3PutU32(pSSM, iPort);
4832 }
4833
4834 return VINF_SSM_DONT_CALL_AGAIN;
4835}
4836
4837/**
4838 * @callback_method_impl{FNSSMDEVSAVEEXEC}
4839 */
4840static DECLCALLBACK(int) ahciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
4841{
4842 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
4843 uint32_t i;
4844 int rc;
4845
4846 Assert(!pThis->f8ByteMMIO4BytesWrittenSuccessfully);
4847
4848 /* The config */
4849 rc = ahciR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
4850 AssertRCReturn(rc, rc);
4851
4852 /* The main device structure. */
4853 SSMR3PutU32(pSSM, pThis->regHbaCap);
4854 SSMR3PutU32(pSSM, pThis->regHbaCtrl);
4855 SSMR3PutU32(pSSM, pThis->regHbaIs);
4856 SSMR3PutU32(pSSM, pThis->regHbaPi);
4857 SSMR3PutU32(pSSM, pThis->regHbaVs);
4858 SSMR3PutU32(pSSM, pThis->regHbaCccCtl);
4859 SSMR3PutU32(pSSM, pThis->regHbaCccPorts);
4860 SSMR3PutU8(pSSM, pThis->uCccPortNr);
4861 SSMR3PutU64(pSSM, pThis->uCccTimeout);
4862 SSMR3PutU32(pSSM, pThis->uCccNr);
4863 SSMR3PutU32(pSSM, pThis->uCccCurrentNr);
4864 SSMR3PutU32(pSSM, pThis->u32PortsInterrupted);
4865 SSMR3PutBool(pSSM, pThis->fReset);
4866 SSMR3PutBool(pSSM, pThis->f64BitAddr);
4867 SSMR3PutBool(pSSM, pThis->fR0Enabled);
4868 SSMR3PutBool(pSSM, pThis->fGCEnabled);
4869 SSMR3PutBool(pSSM, pThis->fLegacyPortResetMethod);
4870
4871 /* Now every port. */
4872 for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
4873 {
4874 Assert(pThis->ahciPort[i].cTasksActive == 0);
4875 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCLB);
4876 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCLBU);
4877 SSMR3PutU32(pSSM, pThis->ahciPort[i].regFB);
4878 SSMR3PutU32(pSSM, pThis->ahciPort[i].regFBU);
4879 SSMR3PutGCPhys(pSSM, pThis->ahciPort[i].GCPhysAddrClb);
4880 SSMR3PutGCPhys(pSSM, pThis->ahciPort[i].GCPhysAddrFb);
4881 SSMR3PutU32(pSSM, pThis->ahciPort[i].regIS);
4882 SSMR3PutU32(pSSM, pThis->ahciPort[i].regIE);
4883 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCMD);
4884 SSMR3PutU32(pSSM, pThis->ahciPort[i].regTFD);
4885 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSIG);
4886 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSSTS);
4887 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSCTL);
4888 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSERR);
4889 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSACT);
4890 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCI);
4891 SSMR3PutU32(pSSM, pThis->ahciPort[i].PCHSGeometry.cCylinders);
4892 SSMR3PutU32(pSSM, pThis->ahciPort[i].PCHSGeometry.cHeads);
4893 SSMR3PutU32(pSSM, pThis->ahciPort[i].PCHSGeometry.cSectors);
4894 SSMR3PutU64(pSSM, pThis->ahciPort[i].cTotalSectors);
4895 SSMR3PutU32(pSSM, pThis->ahciPort[i].cMultSectors);
4896 SSMR3PutU8(pSSM, pThis->ahciPort[i].uATATransferMode);
4897 SSMR3PutBool(pSSM, pThis->ahciPort[i].fResetDevice);
4898 SSMR3PutBool(pSSM, pThis->ahciPort[i].fPoweredOn);
4899 SSMR3PutBool(pSSM, pThis->ahciPort[i].fSpunUp);
4900 SSMR3PutU32(pSSM, pThis->ahciPort[i].u32TasksFinished);
4901 SSMR3PutU32(pSSM, pThis->ahciPort[i].u32QueuedTasksFinished);
4902 SSMR3PutU32(pSSM, pThis->ahciPort[i].u32CurrentCommandSlot);
4903
4904 /* ATAPI saved state. */
4905 SSMR3PutBool(pSSM, pThis->ahciPort[i].fATAPI);
4906 SSMR3PutMem(pSSM, &pThis->ahciPort[i].abATAPISense[0], sizeof(pThis->ahciPort[i].abATAPISense));
4907 }
4908
4909 return SSMR3PutU32(pSSM, UINT32_MAX); /* sanity/terminator */
4910}
4911
4912/**
4913 * Loads a saved legacy ATA emulated device state.
4914 *
4915 * @returns VBox status code.
4916 * @param pSSM The handle to the saved state.
4917 */
4918static int ahciR3LoadLegacyEmulationState(PSSMHANDLE pSSM)
4919{
4920 int rc;
4921 uint32_t u32Version;
4922 uint32_t u32;
4923 uint32_t u32IOBuffer;
4924
4925 /* Test for correct version. */
4926 rc = SSMR3GetU32(pSSM, &u32Version);
4927 AssertRCReturn(rc, rc);
4928 LogFlow(("LoadOldSavedStates u32Version = %d\n", u32Version));
4929
4930 if ( u32Version != ATA_CTL_SAVED_STATE_VERSION
4931 && u32Version != ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE
4932 && u32Version != ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
4933 {
4934 AssertMsgFailed(("u32Version=%d\n", u32Version));
4935 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
4936 }
4937
4938 SSMR3Skip(pSSM, 19 + 5 * sizeof(bool) + sizeof(BMDMAState));
4939
4940 for (uint32_t j = 0; j < 2; j++)
4941 {
4942 SSMR3Skip(pSSM, 88 + 5 * sizeof(bool) );
4943
4944 if (u32Version > ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE)
4945 SSMR3Skip(pSSM, 64);
4946 else
4947 SSMR3Skip(pSSM, 2);
4948 /** @todo triple-check this hack after passthrough is working */
4949 SSMR3Skip(pSSM, 1);
4950
4951 if (u32Version > ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
4952 SSMR3Skip(pSSM, 4);
4953
4954 SSMR3Skip(pSSM, sizeof(PDMLED));
4955 SSMR3GetU32(pSSM, &u32IOBuffer);
4956 if (u32IOBuffer)
4957 SSMR3Skip(pSSM, u32IOBuffer);
4958 }
4959
4960 rc = SSMR3GetU32(pSSM, &u32);
4961 if (RT_FAILURE(rc))
4962 return rc;
4963 if (u32 != ~0U)
4964 {
4965 AssertMsgFailed(("u32=%#x expected ~0\n", u32));
4966 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
4967 return rc;
4968 }
4969
4970 return VINF_SUCCESS;
4971}
4972
4973/**
4974 * @callback_method_impl{FNSSMDEVLOADEXEC}
4975 */
4976static DECLCALLBACK(int) ahciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
4977{
4978 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
4979 uint32_t u32;
4980 int rc;
4981
4982 if ( uVersion > AHCI_SAVED_STATE_VERSION
4983 || uVersion < AHCI_SAVED_STATE_VERSION_VBOX_30)
4984 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
4985
4986 /* Deal with the priod after removing the saved IDE bits where the saved
4987 state version remained unchanged. */
4988 if ( uVersion == AHCI_SAVED_STATE_VERSION_IDE_EMULATION
4989 && SSMR3HandleRevision(pSSM) >= 79045
4990 && SSMR3HandleRevision(pSSM) < 79201)
4991 uVersion++;
4992
4993 /*
4994 * Check whether we have to resort to the legacy port reset method to
4995 * prevent older BIOS versions from failing after a reset.
4996 */
4997 if (uVersion <= AHCI_SAVED_STATE_VERSION_PRE_PORT_RESET_CHANGES)
4998 pThis->fLegacyPortResetMethod = true;
4999
5000 /* Verify config. */
5001 if (uVersion > AHCI_SAVED_STATE_VERSION_VBOX_30)
5002 {
5003 rc = SSMR3GetU32(pSSM, &u32);
5004 AssertRCReturn(rc, rc);
5005 if (u32 != pThis->cPortsImpl)
5006 {
5007 LogRel(("AHCI: Config mismatch: cPortsImpl - saved=%u config=%u\n", u32, pThis->cPortsImpl));
5008 if ( u32 < pThis->cPortsImpl
5009 || u32 > AHCI_MAX_NR_PORTS_IMPL)
5010 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch: cPortsImpl - saved=%u config=%u"),
5011 u32, pThis->cPortsImpl);
5012 }
5013
5014 for (uint32_t i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
5015 {
5016 bool fInUse;
5017 rc = SSMR3GetBool(pSSM, &fInUse);
5018 AssertRCReturn(rc, rc);
5019 if (fInUse != (pThis->ahciPort[i].pDrvBase != NULL))
5020 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
5021 N_("The %s VM is missing a device on port %u. Please make sure the source and target VMs have compatible storage configurations"),
5022 fInUse ? "target" : "source", i );
5023
5024 if (uVersion > AHCI_SAVED_STATE_VERSION_PRE_HOTPLUG_FLAG)
5025 {
5026 bool fHotpluggable;
5027 rc = SSMR3GetBool(pSSM, &fHotpluggable);
5028 AssertRCReturn(rc, rc);
5029 if (fHotpluggable != pThis->ahciPort[i].fHotpluggable)
5030 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
5031 N_("AHCI: Port %u config mismatch: Hotplug flag - saved=%RTbool config=%RTbool\n"),
5032 i, fHotpluggable, pThis->ahciPort[i].fHotpluggable);
5033 }
5034 else
5035 Assert(pThis->ahciPort[i].fHotpluggable);
5036
5037 char szSerialNumber[AHCI_SERIAL_NUMBER_LENGTH+1];
5038 rc = SSMR3GetStrZ(pSSM, szSerialNumber, sizeof(szSerialNumber));
5039 AssertRCReturn(rc, rc);
5040 if (strcmp(szSerialNumber, pThis->ahciPort[i].szSerialNumber))
5041 LogRel(("AHCI: Port %u config mismatch: Serial number - saved='%s' config='%s'\n",
5042 i, szSerialNumber, pThis->ahciPort[i].szSerialNumber));
5043
5044 char szFirmwareRevision[AHCI_FIRMWARE_REVISION_LENGTH+1];
5045 rc = SSMR3GetStrZ(pSSM, szFirmwareRevision, sizeof(szFirmwareRevision));
5046 AssertRCReturn(rc, rc);
5047 if (strcmp(szFirmwareRevision, pThis->ahciPort[i].szFirmwareRevision))
5048 LogRel(("AHCI: Port %u config mismatch: Firmware revision - saved='%s' config='%s'\n",
5049 i, szFirmwareRevision, pThis->ahciPort[i].szFirmwareRevision));
5050
5051 char szModelNumber[AHCI_MODEL_NUMBER_LENGTH+1];
5052 rc = SSMR3GetStrZ(pSSM, szModelNumber, sizeof(szModelNumber));
5053 AssertRCReturn(rc, rc);
5054 if (strcmp(szModelNumber, pThis->ahciPort[i].szModelNumber))
5055 LogRel(("AHCI: Port %u config mismatch: Model number - saved='%s' config='%s'\n",
5056 i, szModelNumber, pThis->ahciPort[i].szModelNumber));
5057 }
5058
5059 static const char *s_apszIdeEmuPortNames[4] = { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
5060 for (uint32_t i = 0; i < RT_ELEMENTS(s_apszIdeEmuPortNames); i++)
5061 {
5062 uint32_t iPort;
5063 rc = CFGMR3QueryU32Def(pDevIns->pCfg, s_apszIdeEmuPortNames[i], &iPort, i);
5064 AssertRCReturn(rc, rc);
5065
5066 uint32_t iPortSaved;
5067 rc = SSMR3GetU32(pSSM, &iPortSaved);
5068 AssertRCReturn(rc, rc);
5069
5070 if (iPortSaved != iPort)
5071 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("IDE %s config mismatch: saved=%u config=%u"),
5072 s_apszIdeEmuPortNames[i], iPortSaved, iPort);
5073 }
5074 }
5075
5076 if (uPass == SSM_PASS_FINAL)
5077 {
5078 /* Restore data. */
5079
5080 /* The main device structure. */
5081 SSMR3GetU32(pSSM, &pThis->regHbaCap);
5082 SSMR3GetU32(pSSM, &pThis->regHbaCtrl);
5083 SSMR3GetU32(pSSM, &pThis->regHbaIs);
5084 SSMR3GetU32(pSSM, &pThis->regHbaPi);
5085 SSMR3GetU32(pSSM, &pThis->regHbaVs);
5086 SSMR3GetU32(pSSM, &pThis->regHbaCccCtl);
5087 SSMR3GetU32(pSSM, &pThis->regHbaCccPorts);
5088 SSMR3GetU8(pSSM, &pThis->uCccPortNr);
5089 SSMR3GetU64(pSSM, &pThis->uCccTimeout);
5090 SSMR3GetU32(pSSM, &pThis->uCccNr);
5091 SSMR3GetU32(pSSM, &pThis->uCccCurrentNr);
5092
5093 SSMR3GetU32(pSSM, (uint32_t *)&pThis->u32PortsInterrupted);
5094 SSMR3GetBool(pSSM, &pThis->fReset);
5095 SSMR3GetBool(pSSM, &pThis->f64BitAddr);
5096 SSMR3GetBool(pSSM, &pThis->fR0Enabled);
5097 SSMR3GetBool(pSSM, &pThis->fGCEnabled);
5098 if (uVersion > AHCI_SAVED_STATE_VERSION_PRE_PORT_RESET_CHANGES)
5099 SSMR3GetBool(pSSM, &pThis->fLegacyPortResetMethod);
5100
5101 /* Now every port. */
5102 for (uint32_t i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
5103 {
5104 PAHCIPort pAhciPort = &pThis->ahciPort[i];
5105
5106 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regCLB);
5107 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regCLBU);
5108 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regFB);
5109 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regFBU);
5110 SSMR3GetGCPhys(pSSM, (RTGCPHYS *)&pThis->ahciPort[i].GCPhysAddrClb);
5111 SSMR3GetGCPhys(pSSM, (RTGCPHYS *)&pThis->ahciPort[i].GCPhysAddrFb);
5112 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].regIS);
5113 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regIE);
5114 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regCMD);
5115 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regTFD);
5116 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSIG);
5117 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSSTS);
5118 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSCTL);
5119 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSERR);
5120 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].regSACT);
5121 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].regCI);
5122 SSMR3GetU32(pSSM, &pThis->ahciPort[i].PCHSGeometry.cCylinders);
5123 SSMR3GetU32(pSSM, &pThis->ahciPort[i].PCHSGeometry.cHeads);
5124 SSMR3GetU32(pSSM, &pThis->ahciPort[i].PCHSGeometry.cSectors);
5125 SSMR3GetU64(pSSM, &pThis->ahciPort[i].cTotalSectors);
5126 SSMR3GetU32(pSSM, &pThis->ahciPort[i].cMultSectors);
5127 SSMR3GetU8(pSSM, &pThis->ahciPort[i].uATATransferMode);
5128 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fResetDevice);
5129
5130 if (uVersion <= AHCI_SAVED_STATE_VERSION_VBOX_30)
5131 SSMR3Skip(pSSM, AHCI_NR_COMMAND_SLOTS * sizeof(uint8_t)); /* no active data here */
5132
5133 if (uVersion < AHCI_SAVED_STATE_VERSION_IDE_EMULATION)
5134 {
5135 /* The old positions in the FIFO, not required. */
5136 SSMR3Skip(pSSM, 2*sizeof(uint8_t));
5137 }
5138 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fPoweredOn);
5139 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fSpunUp);
5140 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].u32TasksFinished);
5141 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].u32QueuedTasksFinished);
5142
5143 if (uVersion >= AHCI_SAVED_STATE_VERSION_IDE_EMULATION)
5144 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].u32CurrentCommandSlot);
5145
5146 if (uVersion > AHCI_SAVED_STATE_VERSION_PRE_ATAPI)
5147 {
5148 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fATAPI);
5149 SSMR3GetMem(pSSM, pThis->ahciPort[i].abATAPISense, sizeof(pThis->ahciPort[i].abATAPISense));
5150 if (uVersion <= AHCI_SAVED_STATE_VERSION_PRE_ATAPI_REMOVE)
5151 {
5152 SSMR3Skip(pSSM, 1); /* cNotifiedMediaChange. */
5153 SSMR3Skip(pSSM, 4); /* MediaEventStatus */
5154 }
5155 }
5156 else if (pThis->ahciPort[i].fATAPI)
5157 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch: atapi - saved=false config=true"));
5158
5159 /* Check if we have tasks pending. */
5160 uint32_t fTasksOutstanding = pAhciPort->regCI & ~pAhciPort->u32TasksFinished;
5161 uint32_t fQueuedTasksOutstanding = pAhciPort->regSACT & ~pAhciPort->u32QueuedTasksFinished;
5162
5163 pAhciPort->u32TasksNew = fTasksOutstanding | fQueuedTasksOutstanding;
5164
5165 if (pAhciPort->u32TasksNew)
5166 {
5167 /*
5168 * There are tasks pending. The VM was saved after a task failed
5169 * because of non-fatal error. Set the redo flag.
5170 */
5171 pAhciPort->fRedo = true;
5172 }
5173 }
5174
5175 if (uVersion <= AHCI_SAVED_STATE_VERSION_IDE_EMULATION)
5176 {
5177 for (uint32_t i = 0; i < 2; i++)
5178 {
5179 rc = ahciR3LoadLegacyEmulationState(pSSM);
5180 if(RT_FAILURE(rc))
5181 return rc;
5182 }
5183 }
5184
5185 rc = SSMR3GetU32(pSSM, &u32);
5186 if (RT_FAILURE(rc))
5187 return rc;
5188 AssertMsgReturn(u32 == UINT32_MAX, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
5189 }
5190
5191 return VINF_SUCCESS;
5192}
5193
5194/* -=-=-=-=- device PDM interface -=-=-=-=- */
5195
5196static DECLCALLBACK(void) ahciR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
5197{
5198 uint32_t i;
5199 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
5200
5201 pAhci->pDevInsRC += offDelta;
5202 pAhci->pHbaCccTimerRC = TMTimerRCPtr(pAhci->pHbaCccTimerR3);
5203 pAhci->pNotifierQueueRC = PDMQueueRCPtr(pAhci->pNotifierQueueR3);
5204
5205 /* Relocate every port. */
5206 for (i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)
5207 {
5208 PAHCIPort pAhciPort = &pAhci->ahciPort[i];
5209 pAhciPort->pAhciRC += offDelta;
5210 pAhciPort->pDevInsRC += offDelta;
5211 }
5212}
5213
5214/**
5215 * Configure the attached device for a port.
5216 *
5217 * Used by ahciR3Construct and ahciR3Attach.
5218 *
5219 * @returns VBox status code
5220 * @param pDevIns The device instance data.
5221 * @param pAhciPort The port for which the device is to be configured.
5222 */
5223static int ahciR3ConfigureLUN(PPDMDEVINS pDevIns, PAHCIPort pAhciPort)
5224{
5225 /* Query the media interface. */
5226 pAhciPort->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIA);
5227 AssertMsgReturn(VALID_PTR(pAhciPort->pDrvMedia),
5228 ("AHCI configuration error: LUN#%d misses the basic media interface!\n", pAhciPort->iLUN),
5229 VERR_PDM_MISSING_INTERFACE);
5230
5231 /* Get the extended media interface. */
5232 pAhciPort->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIAEX);
5233 AssertMsgReturn(VALID_PTR(pAhciPort->pDrvMediaEx),
5234 ("AHCI configuration error: LUN#%d misses the extended media interface!\n", pAhciPort->iLUN),
5235 VERR_PDM_MISSING_INTERFACE);
5236
5237 /*
5238 * Validate type.
5239 */
5240 PDMMEDIATYPE enmType = pAhciPort->pDrvMedia->pfnGetType(pAhciPort->pDrvMedia);
5241 AssertMsgReturn(enmType == PDMMEDIATYPE_HARD_DISK || enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD,
5242 ("AHCI configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%u\n", pAhciPort->iLUN, enmType),
5243 VERR_PDM_UNSUPPORTED_BLOCK_TYPE);
5244
5245 int rc = pAhciPort->pDrvMediaEx->pfnIoReqAllocSizeSet(pAhciPort->pDrvMediaEx, sizeof(AHCIREQ));
5246 if (RT_FAILURE(rc))
5247 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
5248 N_("AHCI configuration error: LUN#%u: Failed to set I/O request size!"),
5249 pAhciPort->iLUN);
5250
5251 uint32_t fFeatures = 0;
5252 rc = pAhciPort->pDrvMediaEx->pfnQueryFeatures(pAhciPort->pDrvMediaEx, &fFeatures);
5253 if (RT_FAILURE(rc))
5254 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
5255 N_("AHCI configuration error: LUN#%u: Failed to query features of device"),
5256 pAhciPort->iLUN);
5257
5258 if (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD)
5259 pAhciPort->fTrimEnabled = true;
5260
5261 pAhciPort->fATAPI = (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD)
5262 && RT_BOOL(fFeatures & PDMIMEDIAEX_FEATURE_F_RAWSCSICMD);
5263 if (pAhciPort->fATAPI)
5264 {
5265 pAhciPort->PCHSGeometry.cCylinders = 0;
5266 pAhciPort->PCHSGeometry.cHeads = 0;
5267 pAhciPort->PCHSGeometry.cSectors = 0;
5268 LogRel(("AHCI: LUN#%d: CD/DVD\n", pAhciPort->iLUN));
5269 }
5270 else
5271 {
5272 pAhciPort->cbSector = pAhciPort->pDrvMedia->pfnGetSectorSize(pAhciPort->pDrvMedia);
5273 pAhciPort->cTotalSectors = pAhciPort->pDrvMedia->pfnGetSize(pAhciPort->pDrvMedia) / pAhciPort->cbSector;
5274 rc = pAhciPort->pDrvMedia->pfnBiosGetPCHSGeometry(pAhciPort->pDrvMedia, &pAhciPort->PCHSGeometry);
5275 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED)
5276 {
5277 pAhciPort->PCHSGeometry.cCylinders = 0;
5278 pAhciPort->PCHSGeometry.cHeads = 16; /*??*/
5279 pAhciPort->PCHSGeometry.cSectors = 63; /*??*/
5280 }
5281 else if (rc == VERR_PDM_GEOMETRY_NOT_SET)
5282 {
5283 pAhciPort->PCHSGeometry.cCylinders = 0; /* autodetect marker */
5284 rc = VINF_SUCCESS;
5285 }
5286 AssertRC(rc);
5287
5288 if ( pAhciPort->PCHSGeometry.cCylinders == 0
5289 || pAhciPort->PCHSGeometry.cHeads == 0
5290 || pAhciPort->PCHSGeometry.cSectors == 0)
5291 {
5292 uint64_t cCylinders = pAhciPort->cTotalSectors / (16 * 63);
5293 pAhciPort->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
5294 pAhciPort->PCHSGeometry.cHeads = 16;
5295 pAhciPort->PCHSGeometry.cSectors = 63;
5296 /* Set the disk geometry information. Ignore errors. */
5297 pAhciPort->pDrvMedia->pfnBiosSetPCHSGeometry(pAhciPort->pDrvMedia, &pAhciPort->PCHSGeometry);
5298 rc = VINF_SUCCESS;
5299 }
5300 LogRel(("AHCI: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n",
5301 pAhciPort->iLUN, pAhciPort->PCHSGeometry.cCylinders,
5302 pAhciPort->PCHSGeometry.cHeads, pAhciPort->PCHSGeometry.cSectors,
5303 pAhciPort->cTotalSectors));
5304 if (pAhciPort->fTrimEnabled)
5305 LogRel(("AHCI: LUN#%d: Enabled TRIM support\n", pAhciPort->iLUN));
5306 }
5307 return rc;
5308}
5309
5310/**
5311 * Callback employed by ahciR3Suspend and ahciR3PowerOff.
5312 *
5313 * @returns true if we've quiesced, false if we're still working.
5314 * @param pDevIns The device instance.
5315 */
5316static DECLCALLBACK(bool) ahciR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)
5317{
5318 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
5319 return false;
5320
5321 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
5322 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
5323 return true;
5324}
5325
5326/**
5327 * Common worker for ahciR3Suspend and ahciR3PowerOff.
5328 */
5329static void ahciR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
5330{
5331 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
5332
5333 ASMAtomicWriteBool(&pThis->fSignalIdle, true);
5334 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
5335 PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncSuspendOrPowerOffDone);
5336 else
5337 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
5338}
5339
5340/**
5341 * Suspend notification.
5342 *
5343 * @param pDevIns The device instance data.
5344 */
5345static DECLCALLBACK(void) ahciR3Suspend(PPDMDEVINS pDevIns)
5346{
5347 Log(("ahciR3Suspend\n"));
5348 ahciR3SuspendOrPowerOff(pDevIns);
5349}
5350
5351/**
5352 * Resume notification.
5353 *
5354 * @param pDevIns The device instance data.
5355 */
5356static DECLCALLBACK(void) ahciR3Resume(PPDMDEVINS pDevIns)
5357{
5358 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
5359
5360 /*
5361 * Check if one of the ports has pending tasks.
5362 * Queue a notification item again in this case.
5363 */
5364 for (unsigned i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)
5365 {
5366 PAHCIPort pAhciPort = &pAhci->ahciPort[i];
5367
5368 if (pAhciPort->u32TasksRedo)
5369 {
5370 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue));
5371 AssertMsg(pItem, ("Allocating item for queue failed\n"));
5372
5373 pAhciPort->u32TasksNew |= pAhciPort->u32TasksRedo;
5374 pAhciPort->u32TasksRedo = 0;
5375
5376 Assert(pAhciPort->fRedo);
5377 pAhciPort->fRedo = false;
5378
5379 pItem->iPort = pAhci->ahciPort[i].iLUN;
5380 PDMQueueInsert(pAhci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
5381 }
5382 }
5383
5384 Log(("%s:\n", __FUNCTION__));
5385}
5386
5387/**
5388 * Initializes the VPD data of a attached device.
5389 *
5390 * @returns VBox status code.
5391 * @param pDevIns The device instance.
5392 * @param pAhciPort The attached device.
5393 * @param pszName Name of the port to get the CFGM node.
5394 */
5395static int ahciR3VpdInit(PPDMDEVINS pDevIns, PAHCIPort pAhciPort, const char *pszName)
5396{
5397
5398 /* Generate a default serial number. */
5399 char szSerial[AHCI_SERIAL_NUMBER_LENGTH+1];
5400 RTUUID Uuid;
5401
5402 int rc = VINF_SUCCESS;
5403 if (pAhciPort->pDrvMedia)
5404 rc = pAhciPort->pDrvMedia->pfnGetUuid(pAhciPort->pDrvMedia, &Uuid);
5405 else
5406 RTUuidClear(&Uuid);
5407
5408 if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
5409 {
5410 /* Generate a predictable serial for drives which don't have a UUID. */
5411 RTStrPrintf(szSerial, sizeof(szSerial), "VB%x-1a2b3c4d",
5412 pAhciPort->iLUN);
5413 }
5414 else
5415 RTStrPrintf(szSerial, sizeof(szSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
5416
5417 /* Get user config if present using defaults otherwise. */
5418 PCFGMNODE pCfgNode = CFGMR3GetChild(pDevIns->pCfg, pszName);
5419 rc = CFGMR3QueryStringDef(pCfgNode, "SerialNumber", pAhciPort->szSerialNumber, sizeof(pAhciPort->szSerialNumber),
5420 szSerial);
5421 if (RT_FAILURE(rc))
5422 {
5423 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
5424 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
5425 N_("AHCI configuration error: \"SerialNumber\" is longer than 20 bytes"));
5426 return PDMDEV_SET_ERROR(pDevIns, rc,
5427 N_("AHCI configuration error: failed to read \"SerialNumber\" as string"));
5428 }
5429
5430 rc = CFGMR3QueryStringDef(pCfgNode, "FirmwareRevision", pAhciPort->szFirmwareRevision, sizeof(pAhciPort->szFirmwareRevision),
5431 "1.0");
5432 if (RT_FAILURE(rc))
5433 {
5434 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
5435 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
5436 N_("AHCI configuration error: \"FirmwareRevision\" is longer than 8 bytes"));
5437 return PDMDEV_SET_ERROR(pDevIns, rc,
5438 N_("AHCI configuration error: failed to read \"FirmwareRevision\" as string"));
5439 }
5440
5441 rc = CFGMR3QueryStringDef(pCfgNode, "ModelNumber", pAhciPort->szModelNumber, sizeof(pAhciPort->szModelNumber),
5442 pAhciPort->fATAPI ? "VBOX CD-ROM" : "VBOX HARDDISK");
5443 if (RT_FAILURE(rc))
5444 {
5445 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
5446 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
5447 N_("AHCI configuration error: \"ModelNumber\" is longer than 40 bytes"));
5448 return PDMDEV_SET_ERROR(pDevIns, rc,
5449 N_("AHCI configuration error: failed to read \"ModelNumber\" as string"));
5450 }
5451
5452 rc = CFGMR3QueryU8Def(pCfgNode, "LogicalSectorsPerPhysical", &pAhciPort->cLogSectorsPerPhysicalExp, 0);
5453 if (RT_FAILURE(rc))
5454 return PDMDEV_SET_ERROR(pDevIns, rc,
5455 N_("AHCI configuration error: failed to read \"LogicalSectorsPerPhysical\" as integer"));
5456 if (pAhciPort->cLogSectorsPerPhysicalExp >= 16)
5457 return PDMDEV_SET_ERROR(pDevIns, rc,
5458 N_("AHCI configuration error: \"LogicalSectorsPerPhysical\" must be between 0 and 15"));
5459
5460 return rc;
5461}
5462
5463
5464/**
5465 * Detach notification.
5466 *
5467 * One harddisk at one port has been unplugged.
5468 * The VM is suspended at this point.
5469 *
5470 * @param pDevIns The device instance.
5471 * @param iLUN The logical unit which is being detached.
5472 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
5473 */
5474static DECLCALLBACK(void) ahciR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
5475{
5476 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
5477 PAHCIPort pAhciPort = &pAhci->ahciPort[iLUN];
5478 int rc = VINF_SUCCESS;
5479
5480 Log(("%s:\n", __FUNCTION__));
5481
5482 AssertMsg(iLUN < pAhci->cPortsImpl, ("iLUN=%u", iLUN));
5483 AssertMsgReturnVoid( pAhciPort->fHotpluggable
5484 || (fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
5485 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN));
5486
5487
5488 if (pAhciPort->pAsyncIOThread)
5489 {
5490 int rcThread;
5491 /* Destroy the thread. */
5492 rc = PDMR3ThreadDestroy(pAhciPort->pAsyncIOThread, &rcThread);
5493 if (RT_FAILURE(rc) || RT_FAILURE(rcThread))
5494 AssertMsgFailed(("%s Failed to destroy async IO thread rc=%Rrc rcThread=%Rrc\n", __FUNCTION__, rc, rcThread));
5495
5496 pAhciPort->pAsyncIOThread = NULL;
5497 pAhciPort->fWrkThreadSleeping = true;
5498 }
5499
5500 if (!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG))
5501 {
5502 /*
5503 * Inform the guest about the removed device.
5504 */
5505 pAhciPort->regSSTS = 0;
5506 pAhciPort->regSIG = 0;
5507 /*
5508 * Clear CR bit too to prevent submission of new commands when CI is written
5509 * (AHCI Spec 1.2: 7.4 Interaction of the Command List and Port Change Status).
5510 */
5511 ASMAtomicAndU32(&pAhciPort->regCMD, ~(AHCI_PORT_CMD_CPS | AHCI_PORT_CMD_CR));
5512 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS);
5513 ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_X | AHCI_PORT_SERR_N);
5514 if ( (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
5515 || (pAhciPort->regIE & AHCI_PORT_IE_PCE)
5516 || (pAhciPort->regIE & AHCI_PORT_IE_PRCE))
5517 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
5518 }
5519
5520 /*
5521 * Zero some important members.
5522 */
5523 pAhciPort->pDrvBase = NULL;
5524 pAhciPort->pDrvMedia = NULL;
5525 pAhciPort->pDrvMediaEx = NULL;
5526}
5527
5528/**
5529 * Attach command.
5530 *
5531 * This is called when we change block driver for one port.
5532 * The VM is suspended at this point.
5533 *
5534 * @returns VBox status code.
5535 * @param pDevIns The device instance.
5536 * @param iLUN The logical unit which is being detached.
5537 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
5538 */
5539static DECLCALLBACK(int) ahciR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
5540{
5541 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
5542 PAHCIPort pAhciPort = &pThis->ahciPort[iLUN];
5543 int rc;
5544
5545 Log(("%s:\n", __FUNCTION__));
5546
5547 /* the usual paranoia */
5548 AssertMsg(iLUN < pThis->cPortsImpl, ("iLUN=%u", iLUN));
5549 AssertRelease(!pAhciPort->pDrvBase);
5550 AssertRelease(!pAhciPort->pDrvMedia);
5551 AssertRelease(!pAhciPort->pDrvMediaEx);
5552 Assert(pAhciPort->iLUN == iLUN);
5553
5554 AssertMsgReturn( pAhciPort->fHotpluggable
5555 || (fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
5556 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN),
5557 VERR_INVALID_PARAMETER);
5558
5559 /*
5560 * Try attach the block device and get the interfaces,
5561 * required as well as optional.
5562 */
5563 rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, NULL);
5564 if (RT_SUCCESS(rc))
5565 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort);
5566 else
5567 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", pAhciPort->iLUN, rc));
5568
5569 if (RT_FAILURE(rc))
5570 {
5571 pAhciPort->pDrvBase = NULL;
5572 pAhciPort->pDrvMedia = NULL;
5573 }
5574 else
5575 {
5576 char szName[24];
5577 RTStrPrintf(szName, sizeof(szName), "Port%d", iLUN);
5578
5579 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
5580 if (RT_FAILURE(rc))
5581 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
5582 N_("AHCI: Failed to create SUP event semaphore"));
5583
5584 /* Create the async IO thread. */
5585 rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop, ahciAsyncIOLoopWakeUp, 0,
5586 RTTHREADTYPE_IO, szName);
5587 if (RT_FAILURE(rc))
5588 return rc;
5589
5590 /*
5591 * Init vendor product data.
5592 */
5593 if (RT_SUCCESS(rc))
5594 rc = ahciR3VpdInit(pDevIns, pAhciPort, szName);
5595
5596 /* Inform the guest about the added device in case of hotplugging. */
5597 if ( RT_SUCCESS(rc)
5598 && !(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG))
5599 {
5600 AssertMsgReturn(pAhciPort->fHotpluggable,
5601 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN),
5602 VERR_NOT_SUPPORTED);
5603
5604 /*
5605 * Initialize registers
5606 */
5607 ASMAtomicOrU32(&pAhciPort->regCMD, AHCI_PORT_CMD_CPS);
5608 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS);
5609 ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_X | AHCI_PORT_SERR_N);
5610
5611 if (pAhciPort->fATAPI)
5612 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
5613 else
5614 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
5615 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
5616 (0x02 << 4) | /* Generation 2 (3.0GBps) speed. */
5617 (0x03 << 0); /* Device detected and communication established. */
5618
5619 if ( (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
5620 || (pAhciPort->regIE & AHCI_PORT_IE_PCE)
5621 || (pAhciPort->regIE & AHCI_PORT_IE_PRCE))
5622 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
5623 }
5624
5625 }
5626
5627 return rc;
5628}
5629
5630/**
5631 * Common reset worker.
5632 *
5633 * @param pDevIns The device instance data.
5634 */
5635static int ahciR3ResetCommon(PPDMDEVINS pDevIns)
5636{
5637 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
5638
5639 ahciHBAReset(pAhci);
5640
5641 /* Hardware reset for the ports. */
5642 for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)
5643 ahciPortHwReset(&pAhci->ahciPort[i]);
5644 return VINF_SUCCESS;
5645}
5646
5647/**
5648 * Callback employed by ahciR3Reset.
5649 *
5650 * @returns true if we've quiesced, false if we're still working.
5651 * @param pDevIns The device instance.
5652 */
5653static DECLCALLBACK(bool) ahciR3IsAsyncResetDone(PPDMDEVINS pDevIns)
5654{
5655 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
5656
5657 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
5658 return false;
5659 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
5660
5661 ahciR3ResetCommon(pDevIns);
5662 return true;
5663}
5664
5665/**
5666 * Reset notification.
5667 *
5668 * @param pDevIns The device instance data.
5669 */
5670static DECLCALLBACK(void) ahciR3Reset(PPDMDEVINS pDevIns)
5671{
5672 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
5673
5674 ASMAtomicWriteBool(&pThis->fSignalIdle, true);
5675 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
5676 PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncResetDone);
5677 else
5678 {
5679 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
5680 ahciR3ResetCommon(pDevIns);
5681 }
5682}
5683
5684/**
5685 * Poweroff notification.
5686 *
5687 * @param pDevIns Pointer to the device instance
5688 */
5689static DECLCALLBACK(void) ahciR3PowerOff(PPDMDEVINS pDevIns)
5690{
5691 Log(("achiR3PowerOff\n"));
5692 ahciR3SuspendOrPowerOff(pDevIns);
5693}
5694
5695/**
5696 * Destroy a driver instance.
5697 *
5698 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
5699 * resources can be freed correctly.
5700 *
5701 * @param pDevIns The device instance data.
5702 */
5703static DECLCALLBACK(int) ahciR3Destruct(PPDMDEVINS pDevIns)
5704{
5705 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
5706 int rc = VINF_SUCCESS;
5707 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
5708
5709 /*
5710 * At this point the async I/O thread is suspended and will not enter
5711 * this module again. So, no coordination is needed here and PDM
5712 * will take care of terminating and cleaning up the thread.
5713 */
5714 if (PDMCritSectIsInitialized(&pThis->lock))
5715 {
5716 TMR3TimerDestroy(pThis->CTX_SUFF(pHbaCccTimer));
5717 pThis->CTX_SUFF(pHbaCccTimer) = NULL;
5718
5719 Log(("%s: Destruct every port\n", __FUNCTION__));
5720 for (unsigned iActPort = 0; iActPort < pThis->cPortsImpl; iActPort++)
5721 {
5722 PAHCIPort pAhciPort = &pThis->ahciPort[iActPort];
5723
5724 if (pAhciPort->hEvtProcess != NIL_SUPSEMEVENT)
5725 {
5726 SUPSemEventClose(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
5727 pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
5728 }
5729 }
5730
5731 PDMR3CritSectDelete(&pThis->lock);
5732 }
5733
5734 return rc;
5735}
5736
5737/**
5738 * @interface_method_impl{PDMDEVREG,pfnConstruct}
5739 */
5740static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
5741{
5742 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
5743 PPDMIBASE pBase;
5744 int rc = VINF_SUCCESS;
5745 unsigned i = 0;
5746 bool fGCEnabled = false;
5747 bool fR0Enabled = false;
5748 uint32_t cbTotalBufferSize = 0;
5749 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
5750
5751 LogFlowFunc(("pThis=%#p\n", pThis));
5752
5753 /*
5754 * Validate and read configuration.
5755 */
5756 if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0"
5757 "R0Enabled\0"
5758 "PrimaryMaster\0"
5759 "PrimarySlave\0"
5760 "SecondaryMaster\0"
5761 "SecondarySlave\0"
5762 "PortCount\0"
5763 "Bootable\0"
5764 "CmdSlotsAvail\0"))
5765 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
5766 N_("AHCI configuration error: unknown option specified"));
5767
5768 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
5769 if (RT_FAILURE(rc))
5770 return PDMDEV_SET_ERROR(pDevIns, rc,
5771 N_("AHCI configuration error: failed to read GCEnabled as boolean"));
5772 Log(("%s: fGCEnabled=%d\n", __FUNCTION__, fGCEnabled));
5773
5774 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
5775 if (RT_FAILURE(rc))
5776 return PDMDEV_SET_ERROR(pDevIns, rc,
5777 N_("AHCI configuration error: failed to read R0Enabled as boolean"));
5778 Log(("%s: fR0Enabled=%d\n", __FUNCTION__, fR0Enabled));
5779
5780 rc = CFGMR3QueryU32Def(pCfg, "PortCount", &pThis->cPortsImpl, AHCI_MAX_NR_PORTS_IMPL);
5781 if (RT_FAILURE(rc))
5782 return PDMDEV_SET_ERROR(pDevIns, rc,
5783 N_("AHCI configuration error: failed to read PortCount as integer"));
5784 Log(("%s: cPortsImpl=%u\n", __FUNCTION__, pThis->cPortsImpl));
5785 if (pThis->cPortsImpl > AHCI_MAX_NR_PORTS_IMPL)
5786 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
5787 N_("AHCI configuration error: PortCount=%u should not exceed %u"),
5788 pThis->cPortsImpl, AHCI_MAX_NR_PORTS_IMPL);
5789 if (pThis->cPortsImpl < 1)
5790 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
5791 N_("AHCI configuration error: PortCount=%u should be at least 1"),
5792 pThis->cPortsImpl);
5793
5794 rc = CFGMR3QueryBoolDef(pCfg, "Bootable", &pThis->fBootable, true);
5795 if (RT_FAILURE(rc))
5796 return PDMDEV_SET_ERROR(pDevIns, rc,
5797 N_("AHCI configuration error: failed to read Bootable as boolean"));
5798
5799 rc = CFGMR3QueryU32Def(pCfg, "CmdSlotsAvail", &pThis->cCmdSlotsAvail, AHCI_NR_COMMAND_SLOTS);
5800 if (RT_FAILURE(rc))
5801 return PDMDEV_SET_ERROR(pDevIns, rc,
5802 N_("AHCI configuration error: failed to read CmdSlotsAvail as integer"));
5803 Log(("%s: cCmdSlotsAvail=%u\n", __FUNCTION__, pThis->cCmdSlotsAvail));
5804 if (pThis->cCmdSlotsAvail > AHCI_NR_COMMAND_SLOTS)
5805 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
5806 N_("AHCI configuration error: CmdSlotsAvail=%u should not exceed %u"),
5807 pThis->cPortsImpl, AHCI_NR_COMMAND_SLOTS);
5808 if (pThis->cCmdSlotsAvail < 1)
5809 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
5810 N_("AHCI configuration error: CmdSlotsAvail=%u should be at least 1"),
5811 pThis->cCmdSlotsAvail);
5812
5813 /*
5814 * Initialize the instance data (everything touched by the destructor need
5815 * to be initialized here!).
5816 */
5817 pThis->fR0Enabled = fR0Enabled;
5818 pThis->fGCEnabled = fGCEnabled;
5819 pThis->pDevInsR3 = pDevIns;
5820 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
5821 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
5822 pThis->pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns);
5823
5824 PCIDevSetVendorId (&pThis->dev, 0x8086); /* Intel */
5825 PCIDevSetDeviceId (&pThis->dev, 0x2829); /* ICH-8M */
5826 PCIDevSetCommand (&pThis->dev, 0x0000);
5827#ifdef VBOX_WITH_MSI_DEVICES
5828 PCIDevSetStatus (&pThis->dev, VBOX_PCI_STATUS_CAP_LIST);
5829 PCIDevSetCapabilityList(&pThis->dev, 0x80);
5830#else
5831 PCIDevSetCapabilityList(&pThis->dev, 0x70);
5832#endif
5833 PCIDevSetRevisionId (&pThis->dev, 0x02);
5834 PCIDevSetClassProg (&pThis->dev, 0x01);
5835 PCIDevSetClassSub (&pThis->dev, 0x06);
5836 PCIDevSetClassBase (&pThis->dev, 0x01);
5837 PCIDevSetBaseAddress (&pThis->dev, 5, false, false, false, 0x00000000);
5838
5839 PCIDevSetInterruptLine(&pThis->dev, 0x00);
5840 PCIDevSetInterruptPin (&pThis->dev, 0x01);
5841
5842 pThis->dev.abConfig[0x70] = VBOX_PCI_CAP_ID_PM; /* Capability ID: PCI Power Management Interface */
5843 pThis->dev.abConfig[0x71] = 0xa8; /* next */
5844 pThis->dev.abConfig[0x72] = 0x03; /* version ? */
5845
5846 pThis->dev.abConfig[0x90] = 0x40; /* AHCI mode. */
5847 pThis->dev.abConfig[0x92] = 0x3f;
5848 pThis->dev.abConfig[0x94] = 0x80;
5849 pThis->dev.abConfig[0x95] = 0x01;
5850 pThis->dev.abConfig[0x97] = 0x78;
5851
5852 pThis->dev.abConfig[0xa8] = 0x12; /* SATACR capability */
5853 pThis->dev.abConfig[0xa9] = 0x00; /* next */
5854 PCIDevSetWord(&pThis->dev, 0xaa, 0x0010); /* Revision */
5855 PCIDevSetDWord(&pThis->dev, 0xac, 0x00000028); /* SATA Capability Register 1 */
5856
5857 pThis->cThreadsActive = 0;
5858
5859 /* Initialize port members. */
5860 for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
5861 {
5862 PAHCIPort pAhciPort = &pThis->ahciPort[i];
5863 pAhciPort->pDevInsR3 = pDevIns;
5864 pAhciPort->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
5865 pAhciPort->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
5866 pAhciPort->iLUN = i;
5867 pAhciPort->pAhciR3 = pThis;
5868 pAhciPort->pAhciR0 = PDMINS_2_DATA_R0PTR(pDevIns);
5869 pAhciPort->pAhciRC = PDMINS_2_DATA_RCPTR(pDevIns);
5870 pAhciPort->Led.u32Magic = PDMLED_MAGIC;
5871 pAhciPort->pDrvBase = NULL;
5872 pAhciPort->pAsyncIOThread = NULL;
5873 pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
5874 pAhciPort->fHotpluggable = true;
5875 }
5876
5877 /*
5878 * Init locks, using explicit locking where necessary.
5879 */
5880 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
5881 if (RT_FAILURE(rc))
5882 return rc;
5883
5884 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->lock, RT_SRC_POS, "AHCI#%u", iInstance);
5885 if (RT_FAILURE(rc))
5886 {
5887 Log(("%s: Failed to create critical section.\n", __FUNCTION__));
5888 return rc;
5889 }
5890
5891 /*
5892 * Register the PCI device, it's I/O regions.
5893 */
5894 rc = PDMDevHlpPCIRegister (pDevIns, &pThis->dev);
5895 if (RT_FAILURE(rc))
5896 return rc;
5897
5898#ifdef VBOX_WITH_MSI_DEVICES
5899 PDMMSIREG MsiReg;
5900 RT_ZERO(MsiReg);
5901 MsiReg.cMsiVectors = 1;
5902 MsiReg.iMsiCapOffset = 0x80;
5903 MsiReg.iMsiNextOffset = 0x70;
5904 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
5905 if (RT_FAILURE(rc))
5906 {
5907 PCIDevSetCapabilityList(&pThis->dev, 0x70);
5908 /* That's OK, we can work without MSI */
5909 }
5910#endif
5911
5912 /*
5913 * Solaris 10 U5 fails to map the AHCI register space when the sets (0..5) for the legacy
5914 * IDE registers are not available.
5915 * We set up "fake" entries in the PCI configuration register.
5916 * That means they are available but read and writes from/to them have no effect.
5917 * No guest should access them anyway because the controller is marked as AHCI in the Programming interface
5918 * and we don't have an option to change to IDE emulation (real hardware provides an option in the BIOS
5919 * to switch to it which also changes device Id and other things in the PCI configuration space).
5920 */
5921 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
5922 if (RT_FAILURE(rc))
5923 return PDMDEV_SET_ERROR(pDevIns, rc,
5924 N_("AHCI cannot register PCI I/O region"));
5925
5926 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 1, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
5927 if (RT_FAILURE(rc))
5928 return PDMDEV_SET_ERROR(pDevIns, rc,
5929 N_("AHCI cannot register PCI I/O region"));
5930
5931 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, 8, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
5932 if (RT_FAILURE(rc))
5933 return PDMDEV_SET_ERROR(pDevIns, rc,
5934 N_("AHCI cannot register PCI I/O region"));
5935
5936 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 3, 1, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
5937 if (RT_FAILURE(rc))
5938 return PDMDEV_SET_ERROR(pDevIns, rc,
5939 N_("AHCI cannot register PCI I/O region"));
5940
5941 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 4, 0x10, PCI_ADDRESS_SPACE_IO, ahciR3IdxDataIORangeMap);
5942 if (RT_FAILURE(rc))
5943 return PDMDEV_SET_ERROR(pDevIns, rc,
5944 N_("AHCI cannot register PCI I/O region for BMDMA"));
5945
5946 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 5, 4352, PCI_ADDRESS_SPACE_MEM, ahciR3MMIOMap);
5947 if (RT_FAILURE(rc))
5948 return PDMDEV_SET_ERROR(pDevIns, rc,
5949 N_("AHCI cannot register PCI memory region for registers"));
5950
5951 /* Create the timer for command completion coalescing feature. */
5952 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ahciCccTimer, pThis,
5953 TMTIMER_FLAGS_NO_CRIT_SECT, "AHCI CCC Timer", &pThis->pHbaCccTimerR3);
5954 if (RT_FAILURE(rc))
5955 {
5956 AssertMsgFailed(("pfnTMTimerCreate -> %Rrc\n", rc));
5957 return rc;
5958 }
5959 pThis->pHbaCccTimerR0 = TMTimerR0Ptr(pThis->pHbaCccTimerR3);
5960 pThis->pHbaCccTimerRC = TMTimerRCPtr(pThis->pHbaCccTimerR3);
5961
5962 /* Status LUN. */
5963 pThis->IBase.pfnQueryInterface = ahciR3Status_QueryInterface;
5964 pThis->ILeds.pfnQueryStatusLed = ahciR3Status_QueryStatusLed;
5965
5966 /*
5967 * Create the notification queue.
5968 *
5969 * We need 2 items for every port because of SMP races.
5970 */
5971 rc = PDMDevHlpQueueCreate(pDevIns, sizeof(DEVPORTNOTIFIERQUEUEITEM), AHCI_MAX_NR_PORTS_IMPL * 2, 0,
5972 ahciNotifyQueueConsumer, true, "AHCI-Xmit", &pThis->pNotifierQueueR3);
5973 if (RT_FAILURE(rc))
5974 return rc;
5975 pThis->pNotifierQueueR0 = PDMQueueR0Ptr(pThis->pNotifierQueueR3);
5976 pThis->pNotifierQueueRC = PDMQueueRCPtr(pThis->pNotifierQueueR3);
5977
5978 /* Initialize static members on every port. */
5979 for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
5980 {
5981 PAHCIPort pAhciPort = &pThis->ahciPort[i];
5982
5983 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatDMA, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
5984 "Number of DMA transfers.", "/Devices/SATA%d/Port%d/DMA", iInstance, i);
5985 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
5986 "Amount of data read.", "/Devices/SATA%d/Port%d/ReadBytes", iInstance, i);
5987 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
5988 "Amount of data written.", "/Devices/SATA%d/Port%d/WrittenBytes", iInstance, i);
5989 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatIORequestsPerSecond, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
5990 "Number of processed I/O requests per second.", "/Devices/SATA%d/Port%d/IORequestsPerSecond", iInstance, i);
5991#ifdef VBOX_WITH_STATISTICS
5992 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatProfileProcessTime, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_NS_PER_CALL,
5993 "Amount of time to process one request.", "/Devices/SATA%d/Port%d/ProfileProcessTime", iInstance, i);
5994 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatProfileReadWrite, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_NS_PER_CALL,
5995 "Amount of time for the read/write operation to complete.", "/Devices/SATA%d/Port%d/ProfileReadWrite", iInstance, i);
5996#endif
5997
5998 ahciPortHwReset(pAhciPort);
5999 }
6000
6001 /* Attach drivers to every available port. */
6002 for (i = 0; i < pThis->cPortsImpl; i++)
6003 {
6004 char szName[24];
6005 RTStrPrintf(szName, sizeof(szName), "Port%u", i);
6006
6007 PAHCIPort pAhciPort = &pThis->ahciPort[i];
6008 /*
6009 * Init interfaces.
6010 */
6011 pAhciPort->IBase.pfnQueryInterface = ahciR3PortQueryInterface;
6012 pAhciPort->IMediaExPort.pfnIoReqCompleteNotify = ahciR3IoReqCompleteNotify;
6013 pAhciPort->IMediaExPort.pfnIoReqCopyFromBuf = ahciR3IoReqCopyFromBuf;
6014 pAhciPort->IMediaExPort.pfnIoReqCopyToBuf = ahciR3IoReqCopyToBuf;
6015 pAhciPort->IMediaExPort.pfnIoReqQueryBuf = NULL;
6016 pAhciPort->IMediaExPort.pfnIoReqQueryDiscardRanges = ahciR3IoReqQueryDiscardRanges;
6017 pAhciPort->IMediaExPort.pfnIoReqStateChanged = ahciR3IoReqStateChanged;
6018 pAhciPort->IMediaExPort.pfnMediumEjected = ahciR3MediumEjected;
6019 pAhciPort->IPort.pfnQueryDeviceLocation = ahciR3PortQueryDeviceLocation;
6020 pAhciPort->fWrkThreadSleeping = true;
6021
6022 /* Query per port configuration options if available. */
6023 PCFGMNODE pCfgPort = CFGMR3GetChild(pDevIns->pCfg, szName);
6024 if (pCfgPort)
6025 {
6026 rc = CFGMR3QueryBoolDef(pCfgPort, "Hotpluggable", &pAhciPort->fHotpluggable, true);
6027 if (RT_FAILURE(rc))
6028 return PDMDEV_SET_ERROR(pDevIns, rc,
6029 N_("AHCI configuration error: failed to read Hotpluggable as boolean"));
6030 }
6031
6032 /*
6033 * Attach the block driver
6034 */
6035 rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, szName);
6036 if (RT_SUCCESS(rc))
6037 {
6038 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort);
6039 if (RT_FAILURE(rc))
6040 {
6041 Log(("%s: Failed to configure the %s.\n", __FUNCTION__, szName));
6042 return rc;
6043 }
6044
6045 /* Mark that a device is present on that port */
6046 if (i < 6)
6047 pThis->dev.abConfig[0x93] |= (1 << i);
6048
6049 /*
6050 * Init vendor product data.
6051 */
6052 rc = ahciR3VpdInit(pDevIns, pAhciPort, szName);
6053 if (RT_FAILURE(rc))
6054 return rc;
6055
6056 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
6057 if (RT_FAILURE(rc))
6058 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
6059 N_("AHCI: Failed to create SUP event semaphore"));
6060
6061 rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop,
6062 ahciAsyncIOLoopWakeUp, 0, RTTHREADTYPE_IO, szName);
6063 if (RT_FAILURE(rc))
6064 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
6065 N_("AHCI: Failed to create worker thread %s"), szName);
6066 }
6067 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
6068 {
6069 pAhciPort->pDrvBase = NULL;
6070 rc = VINF_SUCCESS;
6071 LogRel(("AHCI: %s: No driver attached\n", szName));
6072 }
6073 else
6074 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
6075 N_("AHCI: Failed to attach drive to %s"), szName);
6076 }
6077
6078 /*
6079 * Attach status driver (optional).
6080 */
6081 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThis->IBase, &pBase, "Status Port");
6082 if (RT_SUCCESS(rc))
6083 {
6084 pThis->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS);
6085 pThis->pMediaNotify = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIANOTIFY);
6086 }
6087 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
6088 {
6089 AssertMsgFailed(("Failed to attach to status driver. rc=%Rrc\n", rc));
6090 return PDMDEV_SET_ERROR(pDevIns, rc, N_("AHCI cannot attach to status driver"));
6091 }
6092 rc = PDMDevHlpSSMRegisterEx(pDevIns, AHCI_SAVED_STATE_VERSION, sizeof(*pThis) + cbTotalBufferSize, NULL,
6093 NULL, ahciR3LiveExec, NULL,
6094 ahciR3SavePrep, ahciR3SaveExec, NULL,
6095 ahciR3LoadPrep, ahciR3LoadExec, NULL);
6096 if (RT_FAILURE(rc))
6097 return rc;
6098
6099 /*
6100 * Register the info item.
6101 */
6102 char szTmp[128];
6103 RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance);
6104 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "AHCI info", ahciR3Info);
6105
6106 return ahciR3ResetCommon(pDevIns);
6107}
6108
6109/**
6110 * The device registration structure.
6111 */
6112const PDMDEVREG g_DeviceAHCI =
6113{
6114 /* u32Version */
6115 PDM_DEVREG_VERSION,
6116 /* szName */
6117 "ahci",
6118 /* szRCMod */
6119 "VBoxDDRC.rc",
6120 /* szR0Mod */
6121 "VBoxDDR0.r0",
6122 /* pszDescription */
6123 "Intel AHCI controller.\n",
6124 /* fFlags */
6125 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0 |
6126 PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION |
6127 PDM_DEVREG_FLAGS_FIRST_RESET_NOTIFICATION,
6128 /* fClass */
6129 PDM_DEVREG_CLASS_STORAGE,
6130 /* cMaxInstances */
6131 ~0U,
6132 /* cbInstance */
6133 sizeof(AHCI),
6134 /* pfnConstruct */
6135 ahciR3Construct,
6136 /* pfnDestruct */
6137 ahciR3Destruct,
6138 /* pfnRelocate */
6139 ahciR3Relocate,
6140 /* pfnMemSetup */
6141 NULL,
6142 /* pfnPowerOn */
6143 NULL,
6144 /* pfnReset */
6145 ahciR3Reset,
6146 /* pfnSuspend */
6147 ahciR3Suspend,
6148 /* pfnResume */
6149 ahciR3Resume,
6150 /* pfnAttach */
6151 ahciR3Attach,
6152 /* pfnDetach */
6153 ahciR3Detach,
6154 /* pfnQueryInterface. */
6155 NULL,
6156 /* pfnInitComplete */
6157 NULL,
6158 /* pfnPowerOff */
6159 ahciR3PowerOff,
6160 /* pfnSoftReset */
6161 NULL,
6162 /* u32VersionEnd */
6163 PDM_DEVREG_VERSION
6164};
6165
6166#endif /* IN_RING3 */
6167#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette