VirtualBox

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

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

AHCI: fix loading older saved states

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