VirtualBox

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

Last change on this file since 50453 was 50294, checked in by vboxsync, 11 years ago

AHCI: Fixes for hotplugging, should fix problems with Windows 7 guests

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 318.3 KB
Line 
1/* $Id: DevAHCI.cpp 50294 2014-01-30 18:27:35Z 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-2013 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 transferred in an asynchronous way using one thread per implemented
32 * port or using the new async completion interface which is still under
33 * development. [not quite up to date]
34 */
35
36/*******************************************************************************
37* Header Files *
38*******************************************************************************/
39#define LOG_GROUP LOG_GROUP_DEV_AHCI
40#include <VBox/vmm/pdmdev.h>
41#include <VBox/vmm/pdmqueue.h>
42#include <VBox/vmm/pdmthread.h>
43#include <VBox/vmm/pdmcritsect.h>
44#include <VBox/sup.h>
45#include <VBox/scsi.h>
46#include <iprt/assert.h>
47#include <iprt/asm.h>
48#include <iprt/string.h>
49#ifdef IN_RING3
50# include <iprt/param.h>
51# include <iprt/thread.h>
52# include <iprt/semaphore.h>
53# include <iprt/alloc.h>
54# include <iprt/uuid.h>
55# include <iprt/time.h>
56#endif
57#include "PIIX3ATABmDma.h"
58#include "ide.h"
59#include "ATAPIPassthrough.h"
60#include "VBoxDD.h"
61
62#if defined(VBOX_WITH_DTRACE) \
63 && defined(IN_RING3) \
64 && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
65# include "dtrace/VBoxDD.h"
66#else
67# define VBOXDD_AHCI_REQ_SUBMIT(a,b,c,d) do { } while (0)
68# define VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(a,b) do { } while (0)
69# define VBOXDD_AHCI_REQ_COMPLETED(a,b,c,d,e) do { } while (0)
70# define VBOXDD_AHCI_REQ_COMPLETED_TIMESTAMP(a,b) 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#define AHCI_MAX_ALLOC_TOO_MUCH 20
82
83/** The current saved state version. */
84#define AHCI_SAVED_STATE_VERSION 7
85/** Saved state version before the per port hotplug port was added. */
86#define AHCI_SAVED_STATE_VERSION_PRE_HOTPLUG_FLAG 6
87/** Saved state version before legacy ATA emulation was dropped. */
88#define AHCI_SAVED_STATE_VERSION_IDE_EMULATION 5
89/** Saved state version before ATAPI support was added. */
90#define AHCI_SAVED_STATE_VERSION_PRE_ATAPI 3
91/** The saved state version use in VirtualBox 3.0 and earlier.
92 * This was before the config was added and ahciIOTasks was dropped. */
93#define AHCI_SAVED_STATE_VERSION_VBOX_30 2
94/* for Older ATA state Read handling */
95#define ATA_CTL_SAVED_STATE_VERSION 3
96#define ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE 1
97#define ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS 2
98
99/** The maximum number of release log entries per device. */
100#define MAX_LOG_REL_ERRORS 1024
101
102/**
103 * Maximum number of sectors to transfer in a READ/WRITE MULTIPLE request.
104 * Set to 1 to disable multi-sector read support. According to the ATA
105 * specification this must be a power of 2 and it must fit in an 8 bit
106 * value. Thus the only valid values are 1, 2, 4, 8, 16, 32, 64 and 128.
107 */
108#define ATA_MAX_MULT_SECTORS 128
109
110/**
111 * Fastest PIO mode supported by the drive.
112 */
113#define ATA_PIO_MODE_MAX 4
114/**
115 * Fastest MDMA mode supported by the drive.
116 */
117#define ATA_MDMA_MODE_MAX 2
118/**
119 * Fastest UDMA mode supported by the drive.
120 */
121#define ATA_UDMA_MODE_MAX 6
122
123/**
124 * Length of the configurable VPD data (without termination)
125 */
126#define AHCI_SERIAL_NUMBER_LENGTH 20
127#define AHCI_FIRMWARE_REVISION_LENGTH 8
128#define AHCI_MODEL_NUMBER_LENGTH 40
129#define AHCI_ATAPI_INQUIRY_VENDOR_ID_LENGTH 8
130#define AHCI_ATAPI_INQUIRY_PRODUCT_ID_LENGTH 16
131#define AHCI_ATAPI_INQUIRY_REVISION_LENGTH 4
132
133/* MediaEventStatus */
134#define ATA_EVENT_STATUS_UNCHANGED 0 /**< medium event status not changed */
135#define ATA_EVENT_STATUS_MEDIA_NEW 1 /**< new medium inserted */
136#define ATA_EVENT_STATUS_MEDIA_REMOVED 2 /**< medium removed */
137#define ATA_EVENT_STATUS_MEDIA_CHANGED 3 /**< medium was removed + new medium was inserted */
138#define ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED 4 /**< medium eject requested (eject button pressed) */
139
140/* Media track type */
141#define ATA_MEDIA_TYPE_UNKNOWN 0 /**< unknown CD type */
142
143/** ATAPI sense info size. */
144#define ATAPI_SENSE_SIZE 64
145
146/**
147 * Command Header.
148 */
149#pragma pack(1)
150typedef struct
151{
152 /** Description Information. */
153 uint32_t u32DescInf;
154 /** Command status. */
155 uint32_t u32PRDBC;
156 /** Command Table Base Address. */
157 uint32_t u32CmdTblAddr;
158 /** Command Table Base Address - upper 32-bits. */
159 uint32_t u32CmdTblAddrUp;
160 /** Reserved */
161 uint32_t u32Reserved[4];
162} CmdHdr;
163#pragma pack()
164AssertCompileSize(CmdHdr, 32);
165
166/* Defines for the command header. */
167#define AHCI_CMDHDR_PRDTL_MASK 0xffff0000
168#define AHCI_CMDHDR_PRDTL_ENTRIES(x) ((x & AHCI_CMDHDR_PRDTL_MASK) >> 16)
169#define AHCI_CMDHDR_C RT_BIT(10)
170#define AHCI_CMDHDR_B RT_BIT(9)
171#define AHCI_CMDHDR_R RT_BIT(8)
172#define AHCI_CMDHDR_P RT_BIT(7)
173#define AHCI_CMDHDR_W RT_BIT(6)
174#define AHCI_CMDHDR_A RT_BIT(5)
175#define AHCI_CMDHDR_CFL_MASK 0x1f
176
177#define AHCI_CMDHDR_PRDT_OFFSET 0x80
178#define AHCI_CMDHDR_ACMD_OFFSET 0x40
179
180/* Defines for the command FIS. */
181/* Defines that are used in the first double word. */
182#define AHCI_CMDFIS_TYPE 0 /* The first byte. */
183# define AHCI_CMDFIS_TYPE_H2D 0x27 /* Register - Host to Device FIS. */
184# define AHCI_CMDFIS_TYPE_H2D_SIZE 20 /* Five double words. */
185# define AHCI_CMDFIS_TYPE_D2H 0x34 /* Register - Device to Host FIS. */
186# define AHCI_CMDFIS_TYPE_D2H_SIZE 20 /* Five double words. */
187# define AHCI_CMDFIS_TYPE_SETDEVBITS 0xa1 /* Set Device Bits - Device to Host FIS. */
188# define AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE 8 /* Two double words. */
189# define AHCI_CMDFIS_TYPE_DMAACTD2H 0x39 /* DMA Activate - Device to Host FIS. */
190# define AHCI_CMDFIS_TYPE_DMAACTD2H_SIZE 4 /* One double word. */
191# define AHCI_CMDFIS_TYPE_DMASETUP 0x41 /* DMA Setup - Bidirectional FIS. */
192# define AHCI_CMDFIS_TYPE_DMASETUP_SIZE 28 /* Seven double words. */
193# define AHCI_CMDFIS_TYPE_PIOSETUP 0x5f /* PIO Setup - Device to Host FIS. */
194# define AHCI_CMDFIS_TYPE_PIOSETUP_SIZE 20 /* Five double words. */
195# define AHCI_CMDFIS_TYPE_DATA 0x46 /* Data - Bidirectional FIS. */
196
197#define AHCI_CMDFIS_BITS 1 /* Interrupt and Update bit. */
198#define AHCI_CMDFIS_C RT_BIT(7) /* Host to device. */
199#define AHCI_CMDFIS_I RT_BIT(6) /* Device to Host. */
200#define AHCI_CMDFIS_D RT_BIT(5)
201
202#define AHCI_CMDFIS_CMD 2
203#define AHCI_CMDFIS_FET 3
204
205#define AHCI_CMDFIS_SECTN 4
206#define AHCI_CMDFIS_CYLL 5
207#define AHCI_CMDFIS_CYLH 6
208#define AHCI_CMDFIS_HEAD 7
209
210#define AHCI_CMDFIS_SECTNEXP 8
211#define AHCI_CMDFIS_CYLLEXP 9
212#define AHCI_CMDFIS_CYLHEXP 10
213#define AHCI_CMDFIS_FETEXP 11
214
215#define AHCI_CMDFIS_SECTC 12
216#define AHCI_CMDFIS_SECTCEXP 13
217#define AHCI_CMDFIS_CTL 15
218# define AHCI_CMDFIS_CTL_SRST RT_BIT(2) /* Reset device. */
219# define AHCI_CMDFIS_CTL_NIEN RT_BIT(1) /* Assert or clear interrupt. */
220
221/* For D2H FIS */
222#define AHCI_CMDFIS_STS 2
223#define AHCI_CMDFIS_ERR 3
224
225/** Pointer to a task state. */
226typedef struct AHCIREQ *PAHCIREQ;
227
228/**
229 * Data processing callback
230 *
231 * @returns VBox status.
232 * @param pAhciReq The task state.
233 * @param ppvProc Where to store the pointer to the buffer holding the processed data on success.
234 * Must be freed with RTMemFree().
235 * @param pcbProc Where to store the size of the buffer on success.
236 */
237typedef DECLCALLBACK(int) FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc);
238/** Pointer to a FNAHCIPOSTPROCESS() function. */
239typedef FNAHCIPOSTPROCESS *PFNAHCIPOSTPROCESS;
240
241/**
242 * Transfer type.
243 */
244typedef enum AHCITXDIR
245{
246 /** Invalid */
247 AHCITXDIR_INVALID = 0,
248 /** None */
249 AHCITXDIR_NONE,
250 /** Read */
251 AHCITXDIR_READ,
252 /** Write */
253 AHCITXDIR_WRITE,
254 /** Flush */
255 AHCITXDIR_FLUSH,
256 /** Trim */
257 AHCITXDIR_TRIM
258} AHCITXDIR;
259
260/**
261 * Task state.
262 */
263typedef enum AHCITXSTATE
264{
265 /** Invalid. */
266 AHCITXSTATE_INVALID = 0,
267 /** Task is not active. */
268 AHCITXSTATE_FREE,
269 /** Task is active */
270 AHCITXSTATE_ACTIVE,
271 /** Task was canceled but the request didn't completed yet. */
272 AHCITXSTATE_CANCELED,
273 /** 32bit hack. */
274 AHCITXSTATE_32BIT_HACK = 0x7fffffff
275} AHCITXSTATE, *PAHCITXSTATE;
276
277/** Task encountered a buffer overflow. */
278#define AHCI_REQ_OVERFLOW RT_BIT_32(0)
279/** Request is a PIO data command, if this flag is not set it either is
280 * a command which does not transfer data or a DMA command based on the transfer size. */
281#define AHCI_REQ_PIO_DATA RT_BIT_32(1)
282/** The request has the SACT register set. */
283#define AHCI_REQ_CLEAR_SACT RT_BIT_32(2)
284/** FLag whether the request is queued. */
285#define AHCI_REQ_IS_QUEUED RT_BIT_32(3)
286
287/**
288 * A task state.
289 */
290typedef struct AHCIREQ
291{
292 /** Task state. */
293 volatile AHCITXSTATE enmTxState;
294 /** Start timestamp of the request. */
295 uint64_t tsStart;
296 /** Tag of the task. */
297 uint32_t uTag;
298 /** The command header for this task. */
299 CmdHdr cmdHdr;
300 /** The command Fis for this task. */
301 uint8_t cmdFis[AHCI_CMDFIS_TYPE_H2D_SIZE];
302 /** The ATAPI command data. */
303 uint8_t aATAPICmd[ATAPI_PACKET_SIZE];
304 /** Size of one sector for the ATAPI transfer. */
305 size_t cbATAPISector;
306 /** Physical address of the command header. - GC */
307 RTGCPHYS GCPhysCmdHdrAddr;
308 /** Physical address if the PRDT */
309 RTGCPHYS GCPhysPrdtl;
310 /** Number of entries in the PRDTL. */
311 unsigned cPrdtlEntries;
312 /** Data direction. */
313 AHCITXDIR enmTxDir;
314 /** Start offset. */
315 uint64_t uOffset;
316 /** Number of bytes to transfer. */
317 uint32_t cbTransfer;
318 /** ATA error register */
319 uint8_t uATARegError;
320 /** ATA status register */
321 uint8_t uATARegStatus;
322 /** Flags for this task. */
323 uint32_t fFlags;
324 /** Additional memory allocation for this task. */
325 void *pvAlloc;
326 /** Siize of the allocation. */
327 size_t cbAlloc;
328 /** Number of times we had too much memory allocated for the request. */
329 unsigned cAllocTooMuch;
330 /** Data dependent on the transfer direction. */
331 union
332 {
333 /** Data for an I/O request. */
334 struct
335 {
336 /** Data segment. */
337 RTSGSEG DataSeg;
338 /** Post processing callback.
339 * If this is set we will use a buffer for the data
340 * and the callback returns a buffer with the final data. */
341 PFNAHCIPOSTPROCESS pfnPostProcess;
342 } Io;
343 /** Data for a trim request. */
344 struct
345 {
346 /** Pointer to the array of ranges to trim. */
347 PRTRANGE paRanges;
348 /** Number of entries in the array. */
349 unsigned cRanges;
350 } Trim;
351 } u;
352} AHCIREQ;
353
354/**
355 * Notifier queue item.
356 */
357typedef struct DEVPORTNOTIFIERQUEUEITEM
358{
359 /** The core part owned by the queue manager. */
360 PDMQUEUEITEMCORE Core;
361 /** The port to process. */
362 uint8_t iPort;
363} DEVPORTNOTIFIERQUEUEITEM, *PDEVPORTNOTIFIERQUEUEITEM;
364
365
366/**
367 * @implements PDMIBASE
368 * @implements PDMIBLOCKPORT
369 * @implements PDMIBLOCKASYNCPORT
370 * @implements PDMIMOUNTNOTIFY
371 */
372typedef struct AHCIPort
373{
374 /** Pointer to the device instance - HC ptr */
375 PPDMDEVINSR3 pDevInsR3;
376 /** Pointer to the device instance - R0 ptr */
377 PPDMDEVINSR0 pDevInsR0;
378 /** Pointer to the device instance - RC ptr. */
379 PPDMDEVINSRC pDevInsRC;
380
381#if HC_ARCH_BITS == 64
382 uint32_t Alignment0;
383#endif
384
385 /** Pointer to the parent AHCI structure - R3 ptr. */
386 R3PTRTYPE(struct AHCI *) pAhciR3;
387 /** Pointer to the parent AHCI structure - R0 ptr. */
388 R0PTRTYPE(struct AHCI *) pAhciR0;
389 /** Pointer to the parent AHCI structure - RC ptr. */
390 RCPTRTYPE(struct AHCI *) pAhciRC;
391
392 /** Command List Base Address. */
393 uint32_t regCLB;
394 /** Command List Base Address upper bits. */
395 uint32_t regCLBU;
396 /** FIS Base Address. */
397 uint32_t regFB;
398 /** FIS Base Address upper bits. */
399 uint32_t regFBU;
400 /** Interrupt Status. */
401 volatile uint32_t regIS;
402 /** Interrupt Enable. */
403 uint32_t regIE;
404 /** Command. */
405 uint32_t regCMD;
406 /** Task File Data. */
407 uint32_t regTFD;
408 /** Signature */
409 uint32_t regSIG;
410 /** Serial ATA Status. */
411 uint32_t regSSTS;
412 /** Serial ATA Control. */
413 uint32_t regSCTL;
414 /** Serial ATA Error. */
415 uint32_t regSERR;
416 /** Serial ATA Active. */
417 volatile uint32_t regSACT;
418 /** Command Issue. */
419 uint32_t regCI;
420
421 /** Current number of active tasks. */
422 volatile uint32_t cTasksActive;
423 /** Command List Base Address */
424 volatile RTGCPHYS GCPhysAddrClb;
425 /** FIS Base Address */
426 volatile RTGCPHYS GCPhysAddrFb;
427
428 /** Device is powered on. */
429 bool fPoweredOn;
430 /** Device has spun up. */
431 bool fSpunUp;
432 /** First D2H FIS was send. */
433 bool fFirstD2HFisSend;
434 /** Mark the drive as having a non-rotational medium (i.e. as a SSD). */
435 bool fNonRotational;
436 /** Attached device is a CD/DVD drive. */
437 bool fATAPI;
438 /** Passthrough SCSI commands. */
439 bool fATAPIPassthrough;
440 /** Flag whether this port is in a reset state. */
441 volatile bool fPortReset;
442 /** If we use the new async interface. */
443 bool fAsyncInterface;
444 /** Flag if we are in a device reset. */
445 bool fResetDevice;
446 /** Flag whether this port is hot plug capable. */
447 bool fHotpluggable;
448 /** Flag whether the port is in redo task mode. */
449 volatile bool fRedo;
450 /** Flag whether the worker thread is sleeping. */
451 volatile bool fWrkThreadSleeping;
452
453 bool afAlignment[3];
454
455 /** Number of total sectors. */
456 uint64_t cTotalSectors;
457 /** Size of one sector. */
458 uint32_t cbSector;
459 /** Currently configured number of sectors in a multi-sector transfer. */
460 uint32_t cMultSectors;
461 /** Currently active transfer mode (MDMA/UDMA) and speed. */
462 uint8_t uATATransferMode;
463 /** ATAPI sense data. */
464 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
465 /** HACK: Countdown till we report a newly unmounted drive as mounted. */
466 uint8_t cNotifiedMediaChange;
467 /** Exponent of logical sectors in a physical sector, number of logical sectors is 2^exp. */
468 uint8_t cLogSectorsPerPhysicalExp;
469 /** The same for GET_EVENT_STATUS for mechanism */
470 volatile uint32_t MediaEventStatus;
471 /** Media type if known. */
472 volatile uint32_t MediaTrackType;
473 /** The LUN. */
474 RTUINT iLUN;
475
476 /** Bitmap for finished tasks (R3 -> Guest). */
477 volatile uint32_t u32TasksFinished;
478 /** Bitmap for finished queued tasks (R3 -> Guest). */
479 volatile uint32_t u32QueuedTasksFinished;
480 /** Bitmap for new queued tasks (Guest -> R3). */
481 volatile uint32_t u32TasksNew;
482 /** Bitmap of tasks which must be redone because of a non fatal error. */
483 volatile uint32_t u32TasksRedo;
484
485 /** Current command slot processed.
486 * Accessed by the guest by reading the CMD register.
487 * Holds the command slot of the command processed at the moment. */
488 volatile uint32_t u32CurrentCommandSlot;
489
490#if HC_ARCH_BITS == 64
491 uint32_t u32Alignment2;
492#endif
493
494 /** Device specific settings (R3 only stuff). */
495 /** Pointer to the attached driver's base interface. */
496 R3PTRTYPE(PPDMIBASE) pDrvBase;
497 /** Pointer to the attached driver's block interface. */
498 R3PTRTYPE(PPDMIBLOCK) pDrvBlock;
499 /** Pointer to the attached driver's async block interface. */
500 R3PTRTYPE(PPDMIBLOCKASYNC) pDrvBlockAsync;
501 /** Pointer to the attached driver's block bios interface. */
502 R3PTRTYPE(PPDMIBLOCKBIOS) pDrvBlockBios;
503 /** Pointer to the attached driver's mount interface. */
504 R3PTRTYPE(PPDMIMOUNT) pDrvMount;
505 /** The base interface. */
506 PDMIBASE IBase;
507 /** The block port interface. */
508 PDMIBLOCKPORT IPort;
509 /** The optional block async port interface. */
510 PDMIBLOCKASYNCPORT IPortAsync;
511 /** The mount notify interface. */
512 PDMIMOUNTNOTIFY IMountNotify;
513 /** Physical geometry of this image. */
514 PDMMEDIAGEOMETRY PCHSGeometry;
515 /** The status LED state for this drive. */
516 PDMLED Led;
517
518 uint32_t u32Alignment3;
519
520 /** Async IO Thread. */
521 R3PTRTYPE(PPDMTHREAD) pAsyncIOThread;
522 /**
523 * Array of cached tasks. The tag number is the index value.
524 * Only used with the async interface.
525 */
526 R3PTRTYPE(PAHCIREQ) aCachedTasks[AHCI_NR_COMMAND_SLOTS];
527 /** First task throwing an error. */
528 R3PTRTYPE(volatile PAHCIREQ) pTaskErr;
529 /** The current tracklist of the loaded medium if passthrough is used. */
530 R3PTRTYPE(PTRACKLIST) pTrackList;
531
532 /** The event semaphore the processing thread waits on. */
533 SUPSEMEVENT hEvtProcess;
534
535 /** Release statistics: number of DMA commands. */
536 STAMCOUNTER StatDMA;
537 /** Release statistics: number of bytes written. */
538 STAMCOUNTER StatBytesWritten;
539 /** Release statistics: number of bytes read. */
540 STAMCOUNTER StatBytesRead;
541 /** Release statistics: Number of I/O requests processed per second. */
542 STAMCOUNTER StatIORequestsPerSecond;
543#ifdef VBOX_WITH_STATISTICS
544 /** Statistics: Time to complete one request. */
545 STAMPROFILE StatProfileProcessTime;
546 /** Statistics: Amount of time to read/write data. */
547 STAMPROFILE StatProfileReadWrite;
548#endif /* VBOX_WITH_STATISTICS */
549
550 /** The serial numnber to use for IDENTIFY DEVICE commands. */
551 char szSerialNumber[AHCI_SERIAL_NUMBER_LENGTH+1]; /** < one extra byte for termination */
552 /** The firmware revision to use for IDENTIFY DEVICE commands. */
553 char szFirmwareRevision[AHCI_FIRMWARE_REVISION_LENGTH+1]; /** < one extra byte for termination */
554 /** The model number to use for IDENTIFY DEVICE commands. */
555 char szModelNumber[AHCI_MODEL_NUMBER_LENGTH+1]; /** < one extra byte for termination */
556 /** The vendor identification string for SCSI INQUIRY commands. */
557 char szInquiryVendorId[AHCI_ATAPI_INQUIRY_VENDOR_ID_LENGTH+1];
558 /** The product identification string for SCSI INQUIRY commands. */
559 char szInquiryProductId[AHCI_ATAPI_INQUIRY_PRODUCT_ID_LENGTH+1];
560 /** The revision string for SCSI INQUIRY commands. */
561 char szInquiryRevision[AHCI_ATAPI_INQUIRY_REVISION_LENGTH+1];
562 /** Error counter */
563 uint32_t cErrors;
564
565 uint32_t u32Alignment5;
566} AHCIPort;
567/** Pointer to the state of an AHCI port. */
568typedef AHCIPort *PAHCIPort;
569
570/**
571 * Main AHCI device state.
572 *
573 * @implements PDMILEDPORTS
574 */
575typedef struct AHCI
576{
577 /** The PCI device structure. */
578 PCIDEVICE dev;
579 /** Pointer to the device instance - R3 ptr */
580 PPDMDEVINSR3 pDevInsR3;
581 /** Pointer to the device instance - R0 ptr */
582 PPDMDEVINSR0 pDevInsR0;
583 /** Pointer to the device instance - RC ptr. */
584 PPDMDEVINSRC pDevInsRC;
585
586#if HC_ARCH_BITS == 64
587 uint32_t Alignment0;
588#endif
589
590 /** Status LUN: The base interface. */
591 PDMIBASE IBase;
592 /** Status LUN: Leds interface. */
593 PDMILEDPORTS ILeds;
594 /** Status LUN: Partner of ILeds. */
595 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
596 /** Status LUN: Media Notifys. */
597 R3PTRTYPE(PPDMIMEDIANOTIFY) pMediaNotify;
598
599#if HC_ARCH_BITS == 32
600 uint32_t Alignment1;
601#endif
602
603 /** Base address of the MMIO region. */
604 RTGCPHYS MMIOBase;
605 /** Base address of the I/O port region for Idx/Data. */
606 RTIOPORT IOPortBase;
607
608 /** Global Host Control register of the HBA */
609
610 /** HBA Capabilities - Readonly */
611 uint32_t regHbaCap;
612 /** HBA Control */
613 uint32_t regHbaCtrl;
614 /** Interrupt Status */
615 uint32_t regHbaIs;
616 /** Ports Implemented - Readonly */
617 uint32_t regHbaPi;
618 /** AHCI Version - Readonly */
619 uint32_t regHbaVs;
620 /** Command completion coalescing control */
621 uint32_t regHbaCccCtl;
622 /** Command completion coalescing ports */
623 uint32_t regHbaCccPorts;
624
625 /** Index register for BIOS access. */
626 uint32_t regIdx;
627
628#if HC_ARCH_BITS == 64
629 uint32_t Alignment3;
630#endif
631
632 /** Countdown timer for command completion coalescing - R3 ptr */
633 PTMTIMERR3 pHbaCccTimerR3;
634 /** Countdown timer for command completion coalescing - R0 ptr */
635 PTMTIMERR0 pHbaCccTimerR0;
636 /** Countdown timer for command completion coalescing - RC ptr */
637 PTMTIMERRC pHbaCccTimerRC;
638
639#if HC_ARCH_BITS == 64
640 uint32_t Alignment4;
641#endif
642
643 /** Queue to send tasks to R3. - HC ptr */
644 R3PTRTYPE(PPDMQUEUE) pNotifierQueueR3;
645 /** Queue to send tasks to R3. - HC ptr */
646 R0PTRTYPE(PPDMQUEUE) pNotifierQueueR0;
647 /** Queue to send tasks to R3. - RC ptr */
648 RCPTRTYPE(PPDMQUEUE) pNotifierQueueRC;
649
650#if HC_ARCH_BITS == 64
651 uint32_t Alignment5;
652#endif
653
654
655 /** Which port number is used to mark an CCC interrupt */
656 uint8_t uCccPortNr;
657
658#if HC_ARCH_BITS == 64
659 uint32_t Alignment6;
660#endif
661
662 /** Timeout value */
663 uint64_t uCccTimeout;
664 /** Number of completions used to assert an interrupt */
665 uint32_t uCccNr;
666 /** Current number of completed commands */
667 uint32_t uCccCurrentNr;
668
669 /** Register structure per port */
670 AHCIPort ahciPort[AHCI_MAX_NR_PORTS_IMPL];
671
672 /** The critical section. */
673 PDMCRITSECT lock;
674
675 /** Bitmask of ports which asserted an interrupt. */
676 volatile uint32_t u32PortsInterrupted;
677 /** Number of I/O threads currently active - used for async controller reset handling. */
678 volatile uint32_t cThreadsActive;
679 /** Device is in a reset state. */
680 bool fReset;
681 /** Supports 64bit addressing */
682 bool f64BitAddr;
683 /** GC enabled. */
684 bool fGCEnabled;
685 /** R0 enabled. */
686 bool fR0Enabled;
687 /** If the new async interface is used if available. */
688 bool fUseAsyncInterfaceIfAvailable;
689 /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
690 * a port is entering the idle state. */
691 bool volatile fSignalIdle;
692 /** Flag whether the controller has BIOS access enabled. */
693 bool fBootable;
694
695 /** Number of usable ports on this controller. */
696 uint32_t cPortsImpl;
697 /** Number of usable command slots for each port. */
698 uint32_t cCmdSlotsAvail;
699
700 /** Flag whether we have written the first 4bytes in an 8byte MMIO write successfully. */
701 volatile bool f8ByteMMIO4BytesWrittenSuccessfully;
702
703#if HC_ARCH_BITS == 64
704 uint32_t Alignment7;
705#endif
706
707 /** The support driver session handle. */
708 R3R0PTRTYPE(PSUPDRVSESSION) pSupDrvSession;
709} AHCI;
710/** Pointer to the state of an AHCI device. */
711typedef AHCI *PAHCI;
712
713/**
714 * Scatter gather list entry.
715 */
716typedef struct
717{
718 /** Data Base Address. */
719 uint32_t u32DBA;
720 /** Data Base Address - Upper 32-bits. */
721 uint32_t u32DBAUp;
722 /** Reserved */
723 uint32_t u32Reserved;
724 /** Description information. */
725 uint32_t u32DescInf;
726} SGLEntry;
727AssertCompileSize(SGLEntry, 16);
728
729/** Defines for a scatter gather list entry. */
730#define SGLENTRY_DBA_READONLY ~(RT_BIT(0))
731#define SGLENTRY_DESCINF_I RT_BIT(31)
732#define SGLENTRY_DESCINF_DBC 0x3fffff
733#define SGLENTRY_DESCINF_READONLY 0x803fffff
734
735/* Defines for the global host control registers for the HBA. */
736
737#define AHCI_HBA_GLOBAL_SIZE 0x100
738
739/* Defines for the HBA Capabilities - Readonly */
740#define AHCI_HBA_CAP_S64A RT_BIT(31)
741#define AHCI_HBA_CAP_SNCQ RT_BIT(30)
742#define AHCI_HBA_CAP_SIS RT_BIT(28)
743#define AHCI_HBA_CAP_SSS RT_BIT(27)
744#define AHCI_HBA_CAP_SALP RT_BIT(26)
745#define AHCI_HBA_CAP_SAL RT_BIT(25)
746#define AHCI_HBA_CAP_SCLO RT_BIT(24)
747#define AHCI_HBA_CAP_ISS (RT_BIT(23) | RT_BIT(22) | RT_BIT(21) | RT_BIT(20))
748# define AHCI_HBA_CAP_ISS_SHIFT(x) (((x) << 20) & AHCI_HBA_CAP_ISS)
749# define AHCI_HBA_CAP_ISS_GEN1 RT_BIT(0)
750# define AHCI_HBA_CAP_ISS_GEN2 RT_BIT(1)
751#define AHCI_HBA_CAP_SNZO RT_BIT(19)
752#define AHCI_HBA_CAP_SAM RT_BIT(18)
753#define AHCI_HBA_CAP_SPM RT_BIT(17)
754#define AHCI_HBA_CAP_PMD RT_BIT(15)
755#define AHCI_HBA_CAP_SSC RT_BIT(14)
756#define AHCI_HBA_CAP_PSC RT_BIT(13)
757#define AHCI_HBA_CAP_NCS (RT_BIT(12) | RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8))
758#define AHCI_HBA_CAP_NCS_SET(x) (((x-1) << 8) & AHCI_HBA_CAP_NCS) /* 0's based */
759#define AHCI_HBA_CAP_CCCS RT_BIT(7)
760#define AHCI_HBA_CAP_NP (RT_BIT(4) | RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0))
761#define AHCI_HBA_CAP_NP_SET(x) ((x-1) & AHCI_HBA_CAP_NP) /* 0's based */
762
763/* Defines for the HBA Control register - Read/Write */
764#define AHCI_HBA_CTRL_AE RT_BIT(31)
765#define AHCI_HBA_CTRL_IE RT_BIT(1)
766#define AHCI_HBA_CTRL_HR RT_BIT(0)
767#define AHCI_HBA_CTRL_RW_MASK (RT_BIT(0) | RT_BIT(1)) /* Mask for the used bits */
768
769/* Defines for the HBA Version register - Readonly (We support AHCI 1.0) */
770#define AHCI_HBA_VS_MJR (1 << 16)
771#define AHCI_HBA_VS_MNR 0x100
772
773/* Defines for the command completion coalescing control register */
774#define AHCI_HBA_CCC_CTL_TV 0xffff0000
775#define AHCI_HBA_CCC_CTL_TV_SET(x) (x << 16)
776#define AHCI_HBA_CCC_CTL_TV_GET(x) ((x & AHCI_HBA_CCC_CTL_TV) >> 16)
777
778#define AHCI_HBA_CCC_CTL_CC 0xff00
779#define AHCI_HBA_CCC_CTL_CC_SET(x) (x << 8)
780#define AHCI_HBA_CCC_CTL_CC_GET(x) ((x & AHCI_HBA_CCC_CTL_CC) >> 8)
781
782#define AHCI_HBA_CCC_CTL_INT 0xf8
783#define AHCI_HBA_CCC_CTL_INT_SET(x) (x << 3)
784#define AHCI_HBA_CCC_CTL_INT_GET(x) ((x & AHCI_HBA_CCC_CTL_INT) >> 3)
785
786#define AHCI_HBA_CCC_CTL_EN RT_BIT(0)
787
788/* Defines for the port registers. */
789
790#define AHCI_PORT_REGISTER_SIZE 0x80
791
792#define AHCI_PORT_CLB_RESERVED 0xfffffc00 /* For masking out the reserved bits. */
793
794#define AHCI_PORT_FB_RESERVED 0xffffff00 /* For masking out the reserved bits. */
795
796#define AHCI_PORT_IS_CPDS RT_BIT(31)
797#define AHCI_PORT_IS_TFES RT_BIT(30)
798#define AHCI_PORT_IS_HBFS RT_BIT(29)
799#define AHCI_PORT_IS_HBDS RT_BIT(28)
800#define AHCI_PORT_IS_IFS RT_BIT(27)
801#define AHCI_PORT_IS_INFS RT_BIT(26)
802#define AHCI_PORT_IS_OFS RT_BIT(24)
803#define AHCI_PORT_IS_IPMS RT_BIT(23)
804#define AHCI_PORT_IS_PRCS RT_BIT(22)
805#define AHCI_PORT_IS_DIS RT_BIT(7)
806#define AHCI_PORT_IS_PCS RT_BIT(6)
807#define AHCI_PORT_IS_DPS RT_BIT(5)
808#define AHCI_PORT_IS_UFS RT_BIT(4)
809#define AHCI_PORT_IS_SDBS RT_BIT(3)
810#define AHCI_PORT_IS_DSS RT_BIT(2)
811#define AHCI_PORT_IS_PSS RT_BIT(1)
812#define AHCI_PORT_IS_DHRS RT_BIT(0)
813#define AHCI_PORT_IS_READONLY 0xfd8000af /* Readonly mask including reserved bits. */
814
815#define AHCI_PORT_IE_CPDE RT_BIT(31)
816#define AHCI_PORT_IE_TFEE RT_BIT(30)
817#define AHCI_PORT_IE_HBFE RT_BIT(29)
818#define AHCI_PORT_IE_HBDE RT_BIT(28)
819#define AHCI_PORT_IE_IFE RT_BIT(27)
820#define AHCI_PORT_IE_INFE RT_BIT(26)
821#define AHCI_PORT_IE_OFE RT_BIT(24)
822#define AHCI_PORT_IE_IPME RT_BIT(23)
823#define AHCI_PORT_IE_PRCE RT_BIT(22)
824#define AHCI_PORT_IE_DIE RT_BIT(7) /* Not supported for now, readonly. */
825#define AHCI_PORT_IE_PCE RT_BIT(6)
826#define AHCI_PORT_IE_DPE RT_BIT(5)
827#define AHCI_PORT_IE_UFE RT_BIT(4)
828#define AHCI_PORT_IE_SDBE RT_BIT(3)
829#define AHCI_PORT_IE_DSE RT_BIT(2)
830#define AHCI_PORT_IE_PSE RT_BIT(1)
831#define AHCI_PORT_IE_DHRE RT_BIT(0)
832#define AHCI_PORT_IE_READONLY (0xfdc000ff) /* Readonly mask including reserved bits. */
833
834#define AHCI_PORT_CMD_ICC (RT_BIT(28) | RT_BIT(29) | RT_BIT(30) | RT_BIT(31))
835#define AHCI_PORT_CMD_ICC_SHIFT(x) ((x) << 28)
836# define AHCI_PORT_CMD_ICC_IDLE 0x0
837# define AHCI_PORT_CMD_ICC_ACTIVE 0x1
838# define AHCI_PORT_CMD_ICC_PARTIAL 0x2
839# define AHCI_PORT_CMD_ICC_SLUMBER 0x6
840#define AHCI_PORT_CMD_ASP RT_BIT(27) /* Not supported - Readonly */
841#define AHCI_PORT_CMD_ALPE RT_BIT(26) /* Not supported - Readonly */
842#define AHCI_PORT_CMD_DLAE RT_BIT(25)
843#define AHCI_PORT_CMD_ATAPI RT_BIT(24)
844#define AHCI_PORT_CMD_CPD RT_BIT(20)
845#define AHCI_PORT_CMD_ISP RT_BIT(19) /* Readonly */
846#define AHCI_PORT_CMD_HPCP RT_BIT(18)
847#define AHCI_PORT_CMD_PMA RT_BIT(17) /* Not supported - Readonly */
848#define AHCI_PORT_CMD_CPS RT_BIT(16)
849#define AHCI_PORT_CMD_CR RT_BIT(15) /* Readonly */
850#define AHCI_PORT_CMD_FR RT_BIT(14) /* Readonly */
851#define AHCI_PORT_CMD_ISS RT_BIT(13) /* Readonly */
852#define AHCI_PORT_CMD_CCS (RT_BIT(8) | RT_BIT(9) | RT_BIT(10) | RT_BIT(11) | RT_BIT(12))
853#define AHCI_PORT_CMD_CCS_SHIFT(x) (x << 8) /* Readonly */
854#define AHCI_PORT_CMD_FRE RT_BIT(4)
855#define AHCI_PORT_CMD_CLO RT_BIT(3)
856#define AHCI_PORT_CMD_POD RT_BIT(2)
857#define AHCI_PORT_CMD_SUD RT_BIT(1)
858#define AHCI_PORT_CMD_ST RT_BIT(0)
859#define AHCI_PORT_CMD_READONLY (0xff02001f & ~(AHCI_PORT_CMD_ASP | AHCI_PORT_CMD_ALPE | AHCI_PORT_CMD_PMA))
860
861#define AHCI_PORT_SCTL_IPM (RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8))
862#define AHCI_PORT_SCTL_IPM_GET(x) ((x & AHCI_PORT_SCTL_IPM) >> 8)
863#define AHCI_PORT_SCTL_SPD (RT_BIT(7) | RT_BIT(6) | RT_BIT(5) | RT_BIT(4))
864#define AHCI_PORT_SCTL_SPD_GET(x) ((x & AHCI_PORT_SCTL_SPD) >> 4)
865#define AHCI_PORT_SCTL_DET (RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0))
866#define AHCI_PORT_SCTL_DET_GET(x) (x & AHCI_PORT_SCTL_DET)
867#define AHCI_PORT_SCTL_DET_NINIT 0
868#define AHCI_PORT_SCTL_DET_INIT 1
869#define AHCI_PORT_SCTL_DET_OFFLINE 4
870#define AHCI_PORT_SCTL_READONLY 0xfff
871
872#define AHCI_PORT_SSTS_IPM (RT_BIT(11) | RT_BIT(10) | RT_BIT(9) | RT_BIT(8))
873#define AHCI_PORT_SSTS_IPM_GET(x) ((x & AHCI_PORT_SCTL_IPM) >> 8)
874#define AHCI_PORT_SSTS_SPD (RT_BIT(7) | RT_BIT(6) | RT_BIT(5) | RT_BIT(4))
875#define AHCI_PORT_SSTS_SPD_GET(x) ((x & AHCI_PORT_SCTL_SPD) >> 4)
876#define AHCI_PORT_SSTS_DET (RT_BIT(3) | RT_BIT(2) | RT_BIT(1) | RT_BIT(0))
877#define AHCI_PORT_SSTS_DET_GET(x) (x & AHCI_PORT_SCTL_DET)
878
879#define AHCI_PORT_TFD_BSY RT_BIT(7)
880#define AHCI_PORT_TFD_DRQ RT_BIT(3)
881#define AHCI_PORT_TFD_ERR RT_BIT(0)
882
883#define AHCI_PORT_SERR_X RT_BIT(26)
884#define AHCI_PORT_SERR_W RT_BIT(18)
885#define AHCI_PORT_SERR_N RT_BIT(16)
886
887/* Signatures for attached storage devices. */
888#define AHCI_PORT_SIG_DISK 0x00000101
889#define AHCI_PORT_SIG_ATAPI 0xeb140101
890
891/*
892 * The AHCI spec defines an area of memory where the HBA posts received FIS's from the device.
893 * regFB points to the base of this area.
894 * Every FIS type has an offset where it is posted in this area.
895 */
896#define AHCI_RECFIS_DSFIS_OFFSET 0x00 /* DMA Setup FIS */
897#define AHCI_RECFIS_PSFIS_OFFSET 0x20 /* PIO Setup FIS */
898#define AHCI_RECFIS_RFIS_OFFSET 0x40 /* D2H Register FIS */
899#define AHCI_RECFIS_SDBFIS_OFFSET 0x58 /* Set Device Bits FIS */
900#define AHCI_RECFIS_UFIS_OFFSET 0x60 /* Unknown FIS type */
901
902/** Mask to get the LBA value from a LBA range. */
903#define AHCI_RANGE_LBA_MASK UINT64_C(0xffffffffffff)
904/** Mas to get the length value from a LBA range. */
905#define AHCI_RANGE_LENGTH_MASK UINT64_C(0xffff000000000000)
906/** Returns the length of the range in sectors. */
907#define AHCI_RANGE_LENGTH_GET(val) (((val) & AHCI_RANGE_LENGTH_MASK) >> 48)
908
909/**
910 * AHCI register operator.
911 */
912typedef struct ahci_opreg
913{
914 const char *pszName;
915 int (*pfnRead )(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value);
916 int (*pfnWrite)(PAHCI ahci, uint32_t iReg, uint32_t u32Value);
917} AHCIOPREG;
918
919/**
920 * AHCI port register operator.
921 */
922typedef struct pAhciPort_opreg
923{
924 const char *pszName;
925 int (*pfnRead )(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value);
926 int (*pfnWrite)(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value);
927} AHCIPORTOPREG;
928
929#ifndef VBOX_DEVICE_STRUCT_TESTCASE
930RT_C_DECLS_BEGIN
931static void ahciHBAReset(PAHCI pThis);
932#ifdef IN_RING3
933static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *cmdFis);
934static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort);
935static size_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
936 void *pvBuf, size_t cbBuf);
937static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
938 void *pvBuf, size_t cbBuf);
939static bool ahciCancelActiveTasks(PAHCIPort pAhciPort);
940#endif
941RT_C_DECLS_END
942
943#define PCIDEV_2_PAHCI(pPciDev) ( (PAHCI)(pPciDev) )
944#define PDMIMOUNT_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCIPort, IMount)) )
945#define PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCIPort, IMountNotify)) )
946#define PDMIBASE_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCIPort, IBase)) )
947#define PDMIBLOCKPORT_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCIPort, IPort)) )
948#define PDMIBASE_2_PAHCI(pInterface) ( (PAHCI)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCI, IBase)) )
949#define PDMILEDPORTS_2_PAHCI(pInterface) ( (PAHCI)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCI, ILeds)) )
950
951#define AHCI_RTGCPHYS_FROM_U32(Hi, Lo) ( (RTGCPHYS)RT_MAKE_U64(Lo, Hi) )
952
953#ifdef IN_RING3
954
955# ifdef LOG_USE_C99
956# define ahciLog(a) \
957 Log(("R3 P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
958# else
959# define ahciLog(a) \
960 do { Log(("R3 P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
961# endif
962
963#elif IN_RING0
964
965# ifdef LOG_USE_C99
966# define ahciLog(a) \
967 Log(("R0 P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
968# else
969# define ahciLog(a) \
970 do { Log(("R0 P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
971# endif
972
973#elif IN_RC
974
975# ifdef LOG_USE_C99
976# define ahciLog(a) \
977 Log(("GC P%u: %M", pAhciPort->iLUN, _LogRelRemoveParentheseis a))
978# else
979# define ahciLog(a) \
980 do { Log(("GC P%u: ", pAhciPort->iLUN)); Log(a); } while(0)
981# endif
982
983#endif
984
985/**
986 * Update PCI IRQ levels
987 */
988static void ahciHbaClearInterrupt(PAHCI pAhci)
989{
990 Log(("%s: Clearing interrupt\n", __FUNCTION__));
991 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 0);
992}
993
994/**
995 * Updates the IRQ level and sets port bit in the global interrupt status register of the HBA.
996 */
997static int ahciHbaSetInterrupt(PAHCI pAhci, uint8_t iPort, int rcBusy)
998{
999 Log(("P%u: %s: Setting interrupt\n", iPort, __FUNCTION__));
1000
1001 int rc = PDMCritSectEnter(&pAhci->lock, rcBusy);
1002 if (rc != VINF_SUCCESS)
1003 return rc;
1004
1005 if (pAhci->regHbaCtrl & AHCI_HBA_CTRL_IE)
1006 {
1007 if ((pAhci->regHbaCccCtl & AHCI_HBA_CCC_CTL_EN) && (pAhci->regHbaCccPorts & (1 << iPort)))
1008 {
1009 pAhci->uCccCurrentNr++;
1010 if (pAhci->uCccCurrentNr >= pAhci->uCccNr)
1011 {
1012 /* Reset command completion coalescing state. */
1013 TMTimerSetMillies(pAhci->CTX_SUFF(pHbaCccTimer), pAhci->uCccTimeout);
1014 pAhci->uCccCurrentNr = 0;
1015
1016 pAhci->u32PortsInterrupted |= (1 << pAhci->uCccPortNr);
1017 if (!(pAhci->u32PortsInterrupted & ~(1 << pAhci->uCccPortNr)))
1018 {
1019 Log(("P%u: %s: Fire interrupt\n", iPort, __FUNCTION__));
1020 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 1);
1021 }
1022 }
1023 }
1024 else
1025 {
1026 /* If only the bit of the actual port is set assert an interrupt
1027 * because the interrupt status register was already read by the guest
1028 * and we need to send a new notification.
1029 * Otherwise an interrupt is still pending.
1030 */
1031 ASMAtomicOrU32((volatile uint32_t *)&pAhci->u32PortsInterrupted, (1 << iPort));
1032 if (!(pAhci->u32PortsInterrupted & ~(1 << iPort)))
1033 {
1034 Log(("P%u: %s: Fire interrupt\n", iPort, __FUNCTION__));
1035 PDMDevHlpPCISetIrq(pAhci->CTX_SUFF(pDevIns), 0, 1);
1036 }
1037 }
1038 }
1039
1040 PDMCritSectLeave(&pAhci->lock);
1041 return VINF_SUCCESS;
1042}
1043
1044#ifdef IN_RING3
1045/*
1046 * Assert irq when an CCC timeout occurs
1047 */
1048DECLCALLBACK(void) ahciCccTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
1049{
1050 PAHCI pAhci = (PAHCI)pvUser;
1051
1052 int rc = ahciHbaSetInterrupt(pAhci, pAhci->uCccPortNr, VERR_IGNORED);
1053 AssertRC(rc);
1054}
1055#endif
1056
1057static int PortCmdIssue_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1058{
1059 uint32_t uCIValue;
1060
1061 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1062
1063 /* Update the CI register first. */
1064 uCIValue = ASMAtomicXchgU32(&pAhciPort->u32TasksFinished, 0);
1065 pAhciPort->regCI &= ~uCIValue;
1066
1067 if ( (pAhciPort->regCMD & AHCI_PORT_CMD_CR)
1068 && u32Value > 0)
1069 {
1070 /*
1071 * Clear all tasks which are already marked as busy. The guest
1072 * shouldn't write already busy tasks actually.
1073 */
1074 u32Value &= ~pAhciPort->regCI;
1075
1076 ASMAtomicOrU32(&pAhciPort->u32TasksNew, u32Value);
1077
1078 /* Send a notification to R3 if u32TasksNew was before our write. */
1079 if (ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
1080 {
1081#ifdef IN_RC
1082 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue));
1083 AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
1084
1085 pItem->iPort = pAhciPort->iLUN;
1086 PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
1087#else
1088 LogFlowFunc(("Signal event semaphore\n"));
1089 int rc = SUPSemEventSignal(ahci->pSupDrvSession, pAhciPort->hEvtProcess);
1090 AssertRC(rc);
1091#endif
1092 }
1093 }
1094
1095 pAhciPort->regCI |= u32Value;
1096
1097 return VINF_SUCCESS;
1098}
1099
1100static int PortCmdIssue_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1101{
1102 uint32_t uCIValue = 0;
1103
1104 uCIValue = ASMAtomicXchgU32(&pAhciPort->u32TasksFinished, 0);
1105
1106 ahciLog(("%s: read regCI=%#010x uCIValue=%#010x\n", __FUNCTION__, pAhciPort->regCI, uCIValue));
1107
1108 pAhciPort->regCI &= ~uCIValue;
1109
1110 *pu32Value = pAhciPort->regCI;
1111
1112 return VINF_SUCCESS;
1113}
1114
1115static int PortSActive_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1116{
1117 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1118
1119 pAhciPort->regSACT |= u32Value;
1120
1121 return VINF_SUCCESS;
1122}
1123
1124static int PortSActive_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1125{
1126 uint32_t u32TasksFinished = ASMAtomicXchgU32(&pAhciPort->u32QueuedTasksFinished, 0);
1127
1128 pAhciPort->regSACT &= ~u32TasksFinished;
1129
1130 ahciLog(("%s: read regSACT=%#010x regCI=%#010x u32TasksFinished=%#010x\n",
1131 __FUNCTION__, pAhciPort->regSACT, pAhciPort->regCI, u32TasksFinished));
1132
1133 *pu32Value = pAhciPort->regSACT;
1134
1135 return VINF_SUCCESS;
1136}
1137
1138static int PortSError_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1139{
1140 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1141
1142 if ( (u32Value & AHCI_PORT_SERR_X)
1143 && (pAhciPort->regSERR & AHCI_PORT_SERR_X))
1144 {
1145 ASMAtomicAndU32(&pAhciPort->regIS, ~AHCI_PORT_IS_PCS);
1146 pAhciPort->regTFD |= ATA_STAT_ERR;
1147 pAhciPort->regTFD &= ~(ATA_STAT_DRQ | ATA_STAT_BUSY);
1148 }
1149
1150 if ( (u32Value & AHCI_PORT_SERR_N)
1151 && (pAhciPort->regSERR & AHCI_PORT_SERR_N))
1152 ASMAtomicAndU32(&pAhciPort->regIS, ~AHCI_PORT_IS_PRCS);
1153
1154 pAhciPort->regSERR &= ~u32Value;
1155
1156 return VINF_SUCCESS;
1157}
1158
1159static int PortSError_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1160{
1161 ahciLog(("%s: read regSERR=%#010x\n", __FUNCTION__, pAhciPort->regSERR));
1162 *pu32Value = pAhciPort->regSERR;
1163 return VINF_SUCCESS;
1164}
1165
1166static int PortSControl_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1167{
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 return VINF_IOM_R3_MMIO_WRITE;
1174#else
1175 if ((u32Value & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_INIT)
1176 {
1177 bool fAllTasksCanceled;
1178
1179 /* Cancel all tasks first. */
1180 fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
1181 Assert(fAllTasksCanceled);
1182
1183 if (!ASMAtomicXchgBool(&pAhciPort->fPortReset, true))
1184 LogRel(("AHCI#%u: Port %d reset\n", ahci->CTX_SUFF(pDevIns)->iInstance,
1185 pAhciPort->iLUN));
1186
1187 pAhciPort->regSSTS = 0;
1188 pAhciPort->regSIG = ~0;
1189 pAhciPort->regTFD = 0x7f;
1190 pAhciPort->fFirstD2HFisSend = false;
1191 }
1192 else if ((u32Value & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_NINIT && pAhciPort->pDrvBase &&
1193 (pAhciPort->regSCTL & AHCI_PORT_SCTL_DET) == AHCI_PORT_SCTL_DET_INIT)
1194 {
1195 if (pAhciPort->pDrvBase)
1196 {
1197 ASMAtomicXchgBool(&pAhciPort->fPortReset, false);
1198
1199 /* Signature for SATA device. */
1200 if (pAhciPort->fATAPI)
1201 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
1202 else
1203 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
1204
1205 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
1206 (0x03 << 0); /* Device detected and communication established. */
1207
1208 /*
1209 * Use the maximum allowed speed.
1210 * (Not that it changes anything really)
1211 */
1212 switch (AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL))
1213 {
1214 case 0x01:
1215 pAhciPort->regSSTS |= (0x01 << 4); /* Generation 1 (1.5GBps) speed. */
1216 break;
1217 case 0x02:
1218 case 0x00:
1219 default:
1220 pAhciPort->regSSTS |= (0x02 << 4); /* Generation 2 (3.0GBps) speed. */
1221 break;
1222 }
1223
1224 /* We received a COMINIT from the device. Tell the guest. */
1225 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PCS);
1226 pAhciPort->regSERR |= AHCI_PORT_SERR_X;
1227 pAhciPort->regTFD |= ATA_STAT_BUSY;
1228
1229 if ((pAhciPort->regCMD & AHCI_PORT_CMD_FRE) && (!pAhciPort->fFirstD2HFisSend))
1230 {
1231 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1232 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
1233
1234 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
1235 {
1236 int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
1237 AssertRC(rc);
1238 }
1239 }
1240 }
1241 }
1242
1243 pAhciPort->regSCTL = u32Value;
1244
1245 return VINF_SUCCESS;
1246#endif
1247}
1248
1249static int PortSControl_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1250{
1251 ahciLog(("%s: read regSCTL=%#010x\n", __FUNCTION__, pAhciPort->regSCTL));
1252 ahciLog(("%s: IPM=%d SPD=%d DET=%d\n", __FUNCTION__,
1253 AHCI_PORT_SCTL_IPM_GET(pAhciPort->regSCTL), AHCI_PORT_SCTL_SPD_GET(pAhciPort->regSCTL),
1254 AHCI_PORT_SCTL_DET_GET(pAhciPort->regSCTL)));
1255
1256 *pu32Value = pAhciPort->regSCTL;
1257 return VINF_SUCCESS;
1258}
1259
1260static int PortSStatus_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1261{
1262 ahciLog(("%s: read regSSTS=%#010x\n", __FUNCTION__, pAhciPort->regSSTS));
1263 ahciLog(("%s: IPM=%d SPD=%d DET=%d\n", __FUNCTION__,
1264 AHCI_PORT_SSTS_IPM_GET(pAhciPort->regSSTS), AHCI_PORT_SSTS_SPD_GET(pAhciPort->regSSTS),
1265 AHCI_PORT_SSTS_DET_GET(pAhciPort->regSSTS)));
1266
1267 *pu32Value = pAhciPort->regSSTS;
1268 return VINF_SUCCESS;
1269}
1270
1271static int PortSignature_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1272{
1273 ahciLog(("%s: read regSIG=%#010x\n", __FUNCTION__, pAhciPort->regSIG));
1274 *pu32Value = pAhciPort->regSIG;
1275 return VINF_SUCCESS;
1276}
1277
1278static int PortTaskFileData_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1279{
1280 ahciLog(("%s: read regTFD=%#010x\n", __FUNCTION__, pAhciPort->regTFD));
1281 ahciLog(("%s: ERR=%x BSY=%d DRQ=%d ERR=%d\n", __FUNCTION__,
1282 (pAhciPort->regTFD >> 8), (pAhciPort->regTFD & AHCI_PORT_TFD_BSY) >> 7,
1283 (pAhciPort->regTFD & AHCI_PORT_TFD_DRQ) >> 3, (pAhciPort->regTFD & AHCI_PORT_TFD_ERR)));
1284 *pu32Value = pAhciPort->regTFD;
1285 return VINF_SUCCESS;
1286}
1287
1288/**
1289 * Read from the port command register.
1290 */
1291static int PortCmd_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1292{
1293 ahciLog(("%s: read regCMD=%#010x\n", __FUNCTION__, pAhciPort->regCMD | AHCI_PORT_CMD_CCS_SHIFT(pAhciPort->u32CurrentCommandSlot)));
1294 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",
1295 __FUNCTION__, (pAhciPort->regCMD & AHCI_PORT_CMD_ICC) >> 28, (pAhciPort->regCMD & AHCI_PORT_CMD_ASP) >> 27,
1296 (pAhciPort->regCMD & AHCI_PORT_CMD_ALPE) >> 26, (pAhciPort->regCMD & AHCI_PORT_CMD_DLAE) >> 25,
1297 (pAhciPort->regCMD & AHCI_PORT_CMD_ATAPI) >> 24, (pAhciPort->regCMD & AHCI_PORT_CMD_CPD) >> 20,
1298 (pAhciPort->regCMD & AHCI_PORT_CMD_ISP) >> 19, (pAhciPort->regCMD & AHCI_PORT_CMD_HPCP) >> 18,
1299 (pAhciPort->regCMD & AHCI_PORT_CMD_PMA) >> 17, (pAhciPort->regCMD & AHCI_PORT_CMD_CPS) >> 16,
1300 (pAhciPort->regCMD & AHCI_PORT_CMD_CR) >> 15, (pAhciPort->regCMD & AHCI_PORT_CMD_FR) >> 14,
1301 (pAhciPort->regCMD & AHCI_PORT_CMD_ISS) >> 13, pAhciPort->u32CurrentCommandSlot,
1302 (pAhciPort->regCMD & AHCI_PORT_CMD_FRE) >> 4, (pAhciPort->regCMD & AHCI_PORT_CMD_CLO) >> 3,
1303 (pAhciPort->regCMD & AHCI_PORT_CMD_POD) >> 2, (pAhciPort->regCMD & AHCI_PORT_CMD_SUD) >> 1,
1304 (pAhciPort->regCMD & AHCI_PORT_CMD_ST)));
1305 *pu32Value = pAhciPort->regCMD | AHCI_PORT_CMD_CCS_SHIFT(pAhciPort->u32CurrentCommandSlot);
1306 return VINF_SUCCESS;
1307}
1308
1309/**
1310 * Write to the port command register.
1311 * This is the register where all the data transfer is started
1312 */
1313static int PortCmd_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1314{
1315 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1316 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",
1317 __FUNCTION__, (u32Value & AHCI_PORT_CMD_ICC) >> 28, (u32Value & AHCI_PORT_CMD_ASP) >> 27,
1318 (u32Value & AHCI_PORT_CMD_ALPE) >> 26, (u32Value & AHCI_PORT_CMD_DLAE) >> 25,
1319 (u32Value & AHCI_PORT_CMD_ATAPI) >> 24, (u32Value & AHCI_PORT_CMD_CPD) >> 20,
1320 (u32Value & AHCI_PORT_CMD_ISP) >> 19, (u32Value & AHCI_PORT_CMD_HPCP) >> 18,
1321 (u32Value & AHCI_PORT_CMD_PMA) >> 17, (u32Value & AHCI_PORT_CMD_CPS) >> 16,
1322 (u32Value & AHCI_PORT_CMD_CR) >> 15, (u32Value & AHCI_PORT_CMD_FR) >> 14,
1323 (u32Value & AHCI_PORT_CMD_ISS) >> 13, (u32Value & AHCI_PORT_CMD_CCS) >> 8,
1324 (u32Value & AHCI_PORT_CMD_FRE) >> 4, (u32Value & AHCI_PORT_CMD_CLO) >> 3,
1325 (u32Value & AHCI_PORT_CMD_POD) >> 2, (u32Value & AHCI_PORT_CMD_SUD) >> 1,
1326 (u32Value & AHCI_PORT_CMD_ST)));
1327
1328 /* The PxCMD.CCS bits are R/O and maintained separately. */
1329 u32Value &= ~AHCI_PORT_CMD_CCS;
1330
1331 if (pAhciPort->fPoweredOn && pAhciPort->fSpunUp)
1332 {
1333 if (u32Value & AHCI_PORT_CMD_CLO)
1334 {
1335 ahciLog(("%s: Command list override requested\n", __FUNCTION__));
1336 u32Value &= ~(AHCI_PORT_TFD_BSY | AHCI_PORT_TFD_DRQ);
1337 /* Clear the CLO bit. */
1338 u32Value &= ~(AHCI_PORT_CMD_CLO);
1339 }
1340
1341 if (u32Value & AHCI_PORT_CMD_ST)
1342 {
1343 /*
1344 * Set engine state to running if there is a device attached and
1345 * IS.PCS is clear.
1346 */
1347 if ( pAhciPort->pDrvBase
1348 && !(pAhciPort->regIS & AHCI_PORT_IS_PCS))
1349 {
1350 ahciLog(("%s: Engine starts\n", __FUNCTION__));
1351 u32Value |= AHCI_PORT_CMD_CR;
1352
1353 /* If there is something in CI, kick the I/O thread. */
1354 if ( pAhciPort->regCI > 0
1355 && ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping))
1356 {
1357 ASMAtomicOrU32(&pAhciPort->u32TasksNew, pAhciPort->regCI);
1358#ifdef IN_RC
1359 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(ahci->CTX_SUFF(pNotifierQueue));
1360 AssertMsg(VALID_PTR(pItem), ("Allocating item for queue failed\n"));
1361
1362 pItem->iPort = pAhciPort->iLUN;
1363 PDMQueueInsert(ahci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
1364#else
1365 LogFlowFunc(("Signal event semaphore\n"));
1366 int rc = SUPSemEventSignal(ahci->pSupDrvSession, pAhciPort->hEvtProcess);
1367 AssertRC(rc);
1368#endif
1369 }
1370 }
1371 else
1372 u32Value &= ~AHCI_PORT_CMD_CR;
1373 }
1374 else
1375 {
1376 ahciLog(("%s: Engine stops\n", __FUNCTION__));
1377 /* Clear command issue register. */
1378 pAhciPort->regCI = 0;
1379 pAhciPort->regSACT = 0;
1380 /* Clear current command slot. */
1381 pAhciPort->u32CurrentCommandSlot = 0;
1382 u32Value &= ~AHCI_PORT_CMD_CR;
1383 }
1384 }
1385 else if (pAhciPort->pDrvBase)
1386 {
1387 if ((u32Value & AHCI_PORT_CMD_POD) && (pAhciPort->regCMD & AHCI_PORT_CMD_CPS) && !pAhciPort->fPoweredOn)
1388 {
1389 ahciLog(("%s: Power on the device\n", __FUNCTION__));
1390 pAhciPort->fPoweredOn = true;
1391
1392 /*
1393 * Set states in the Port Signature and SStatus registers.
1394 */
1395 if (pAhciPort->fATAPI)
1396 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
1397 else
1398 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
1399 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
1400 (0x02 << 4) | /* Generation 2 (3.0GBps) speed. */
1401 (0x03 << 0); /* Device detected and communication established. */
1402
1403 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
1404 {
1405#ifndef IN_RING3
1406 return VINF_IOM_R3_MMIO_WRITE;
1407#else
1408 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1409 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
1410
1411 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
1412 {
1413 int rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
1414 AssertRC(rc);
1415 }
1416#endif
1417 }
1418 }
1419
1420 if ((u32Value & AHCI_PORT_CMD_SUD) && pAhciPort->fPoweredOn && !pAhciPort->fSpunUp)
1421 {
1422 ahciLog(("%s: Spin up the device\n", __FUNCTION__));
1423 pAhciPort->fSpunUp = true;
1424 }
1425 }
1426
1427 if (u32Value & AHCI_PORT_CMD_FRE)
1428 {
1429 ahciLog(("%s: FIS receive enabled\n", __FUNCTION__));
1430
1431 u32Value |= AHCI_PORT_CMD_FR;
1432
1433 /* Send the first D2H FIS only if it wasn't already send. */
1434 if ( !pAhciPort->fFirstD2HFisSend
1435 && pAhciPort->pDrvBase)
1436 {
1437#ifndef IN_RING3
1438 return VINF_IOM_R3_MMIO_WRITE;
1439#else
1440 ahciPostFirstD2HFisIntoMemory(pAhciPort);
1441 pAhciPort->fFirstD2HFisSend = true;
1442#endif
1443 }
1444 }
1445 else if (!(u32Value & AHCI_PORT_CMD_FRE))
1446 {
1447 ahciLog(("%s: FIS receive disabled\n", __FUNCTION__));
1448 u32Value &= ~AHCI_PORT_CMD_FR;
1449 }
1450
1451 pAhciPort->regCMD = u32Value;
1452
1453 return VINF_SUCCESS;
1454}
1455
1456/**
1457 * Read from the port interrupt enable register.
1458 */
1459static int PortIntrEnable_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1460{
1461 ahciLog(("%s: read regIE=%#010x\n", __FUNCTION__, pAhciPort->regIE));
1462 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",
1463 __FUNCTION__, (pAhciPort->regIE & AHCI_PORT_IE_CPDE) >> 31, (pAhciPort->regIE & AHCI_PORT_IE_TFEE) >> 30,
1464 (pAhciPort->regIE & AHCI_PORT_IE_HBFE) >> 29, (pAhciPort->regIE & AHCI_PORT_IE_HBDE) >> 28,
1465 (pAhciPort->regIE & AHCI_PORT_IE_IFE) >> 27, (pAhciPort->regIE & AHCI_PORT_IE_INFE) >> 26,
1466 (pAhciPort->regIE & AHCI_PORT_IE_OFE) >> 24, (pAhciPort->regIE & AHCI_PORT_IE_IPME) >> 23,
1467 (pAhciPort->regIE & AHCI_PORT_IE_PRCE) >> 22, (pAhciPort->regIE & AHCI_PORT_IE_DIE) >> 7,
1468 (pAhciPort->regIE & AHCI_PORT_IE_PCE) >> 6, (pAhciPort->regIE & AHCI_PORT_IE_DPE) >> 5,
1469 (pAhciPort->regIE & AHCI_PORT_IE_UFE) >> 4, (pAhciPort->regIE & AHCI_PORT_IE_SDBE) >> 3,
1470 (pAhciPort->regIE & AHCI_PORT_IE_DSE) >> 2, (pAhciPort->regIE & AHCI_PORT_IE_PSE) >> 1,
1471 (pAhciPort->regIE & AHCI_PORT_IE_DHRE)));
1472 *pu32Value = pAhciPort->regIE;
1473 return VINF_SUCCESS;
1474}
1475
1476/**
1477 * Write to the port interrupt enable register.
1478 */
1479static int PortIntrEnable_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1480{
1481 int rc = VINF_SUCCESS;
1482 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1483 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",
1484 __FUNCTION__, (u32Value & AHCI_PORT_IE_CPDE) >> 31, (u32Value & AHCI_PORT_IE_TFEE) >> 30,
1485 (u32Value & AHCI_PORT_IE_HBFE) >> 29, (u32Value & AHCI_PORT_IE_HBDE) >> 28,
1486 (u32Value & AHCI_PORT_IE_IFE) >> 27, (u32Value & AHCI_PORT_IE_INFE) >> 26,
1487 (u32Value & AHCI_PORT_IE_OFE) >> 24, (u32Value & AHCI_PORT_IE_IPME) >> 23,
1488 (u32Value & AHCI_PORT_IE_PRCE) >> 22, (u32Value & AHCI_PORT_IE_DIE) >> 7,
1489 (u32Value & AHCI_PORT_IE_PCE) >> 6, (u32Value & AHCI_PORT_IE_DPE) >> 5,
1490 (u32Value & AHCI_PORT_IE_UFE) >> 4, (u32Value & AHCI_PORT_IE_SDBE) >> 3,
1491 (u32Value & AHCI_PORT_IE_DSE) >> 2, (u32Value & AHCI_PORT_IE_PSE) >> 1,
1492 (u32Value & AHCI_PORT_IE_DHRE)));
1493
1494 u32Value &= AHCI_PORT_IE_READONLY;
1495
1496 /* Check if some a interrupt status bit changed*/
1497 uint32_t u32IntrStatus = ASMAtomicReadU32(&pAhciPort->regIS);
1498
1499 if (u32Value & u32IntrStatus)
1500 rc = ahciHbaSetInterrupt(ahci, pAhciPort->iLUN, VINF_IOM_R3_MMIO_WRITE);
1501
1502 if (rc == VINF_SUCCESS)
1503 pAhciPort->regIE = u32Value;
1504
1505 return rc;
1506}
1507
1508/**
1509 * Read from the port interrupt status register.
1510 */
1511static int PortIntrSts_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1512{
1513 ahciLog(("%s: read regIS=%#010x\n", __FUNCTION__, pAhciPort->regIS));
1514 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",
1515 __FUNCTION__, (pAhciPort->regIS & AHCI_PORT_IS_CPDS) >> 31, (pAhciPort->regIS & AHCI_PORT_IS_TFES) >> 30,
1516 (pAhciPort->regIS & AHCI_PORT_IS_HBFS) >> 29, (pAhciPort->regIS & AHCI_PORT_IS_HBDS) >> 28,
1517 (pAhciPort->regIS & AHCI_PORT_IS_IFS) >> 27, (pAhciPort->regIS & AHCI_PORT_IS_INFS) >> 26,
1518 (pAhciPort->regIS & AHCI_PORT_IS_OFS) >> 24, (pAhciPort->regIS & AHCI_PORT_IS_IPMS) >> 23,
1519 (pAhciPort->regIS & AHCI_PORT_IS_PRCS) >> 22, (pAhciPort->regIS & AHCI_PORT_IS_DIS) >> 7,
1520 (pAhciPort->regIS & AHCI_PORT_IS_PCS) >> 6, (pAhciPort->regIS & AHCI_PORT_IS_DPS) >> 5,
1521 (pAhciPort->regIS & AHCI_PORT_IS_UFS) >> 4, (pAhciPort->regIS & AHCI_PORT_IS_SDBS) >> 3,
1522 (pAhciPort->regIS & AHCI_PORT_IS_DSS) >> 2, (pAhciPort->regIS & AHCI_PORT_IS_PSS) >> 1,
1523 (pAhciPort->regIS & AHCI_PORT_IS_DHRS)));
1524 *pu32Value = pAhciPort->regIS;
1525 return VINF_SUCCESS;
1526}
1527
1528/**
1529 * Write to the port interrupt status register.
1530 */
1531static int PortIntrSts_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1532{
1533 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1534 ASMAtomicAndU32(&pAhciPort->regIS, ~(u32Value & AHCI_PORT_IS_READONLY));
1535
1536 return VINF_SUCCESS;
1537}
1538
1539/**
1540 * Read from the port FIS base address upper 32bit register.
1541 */
1542static int PortFisAddrUp_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1543{
1544 ahciLog(("%s: read regFBU=%#010x\n", __FUNCTION__, pAhciPort->regFBU));
1545 *pu32Value = pAhciPort->regFBU;
1546 return VINF_SUCCESS;
1547}
1548
1549/**
1550 * Write to the port FIS base address upper 32bit register.
1551 */
1552static int PortFisAddrUp_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1553{
1554 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1555
1556 pAhciPort->regFBU = u32Value;
1557 pAhciPort->GCPhysAddrFb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regFBU, pAhciPort->regFB);
1558
1559 return VINF_SUCCESS;
1560}
1561
1562/**
1563 * Read from the port FIS base address register.
1564 */
1565static int PortFisAddr_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1566{
1567 ahciLog(("%s: read regFB=%#010x\n", __FUNCTION__, pAhciPort->regFB));
1568 *pu32Value = pAhciPort->regFB;
1569 return VINF_SUCCESS;
1570}
1571
1572/**
1573 * Write to the port FIS base address register.
1574 */
1575static int PortFisAddr_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1576{
1577 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1578
1579 Assert(!(u32Value & ~AHCI_PORT_FB_RESERVED));
1580
1581 pAhciPort->regFB = (u32Value & AHCI_PORT_FB_RESERVED);
1582 pAhciPort->GCPhysAddrFb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regFBU, pAhciPort->regFB);
1583
1584 return VINF_SUCCESS;
1585}
1586
1587/**
1588 * Write to the port command list base address upper 32bit register.
1589 */
1590static int PortCmdLstAddrUp_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1591{
1592 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1593
1594 pAhciPort->regCLBU = u32Value;
1595 pAhciPort->GCPhysAddrClb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regCLBU, pAhciPort->regCLB);
1596
1597 return VINF_SUCCESS;
1598}
1599
1600/**
1601 * Read from the port command list base address upper 32bit register.
1602 */
1603static int PortCmdLstAddrUp_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1604{
1605 ahciLog(("%s: read regCLBU=%#010x\n", __FUNCTION__, pAhciPort->regCLBU));
1606 *pu32Value = pAhciPort->regCLBU;
1607 return VINF_SUCCESS;
1608}
1609
1610/**
1611 * Read from the port command list base address register.
1612 */
1613static int PortCmdLstAddr_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1614{
1615 ahciLog(("%s: read regCLB=%#010x\n", __FUNCTION__, pAhciPort->regCLB));
1616 *pu32Value = pAhciPort->regCLB;
1617 return VINF_SUCCESS;
1618}
1619
1620/**
1621 * Write to the port command list base address register.
1622 */
1623static int PortCmdLstAddr_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1624{
1625 ahciLog(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1626
1627 Assert(!(u32Value & ~AHCI_PORT_CLB_RESERVED));
1628
1629 pAhciPort->regCLB = (u32Value & AHCI_PORT_CLB_RESERVED);
1630 pAhciPort->GCPhysAddrClb = AHCI_RTGCPHYS_FROM_U32(pAhciPort->regCLBU, pAhciPort->regCLB);
1631
1632 return VINF_SUCCESS;
1633}
1634
1635/**
1636 * Read from the global Version register.
1637 */
1638static int HbaVersion_r(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value)
1639{
1640 Log(("%s: read regHbaVs=%#010x\n", __FUNCTION__, ahci->regHbaVs));
1641 *pu32Value = ahci->regHbaVs;
1642 return VINF_SUCCESS;
1643}
1644
1645/**
1646 * Read from the global Ports implemented register.
1647 */
1648static int HbaPortsImplemented_r(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value)
1649{
1650 Log(("%s: read regHbaPi=%#010x\n", __FUNCTION__, ahci->regHbaPi));
1651 *pu32Value = ahci->regHbaPi;
1652 return VINF_SUCCESS;
1653}
1654
1655/**
1656 * Write to the global interrupt status register.
1657 */
1658static int HbaInterruptStatus_w(PAHCI ahci, uint32_t iReg, uint32_t u32Value)
1659{
1660 int rc;
1661 Log(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1662
1663 rc = PDMCritSectEnter(&ahci->lock, VINF_IOM_R3_MMIO_WRITE);
1664 if (rc != VINF_SUCCESS)
1665 return rc;
1666
1667 if (u32Value > 0)
1668 {
1669 /*
1670 * Clear the interrupt only if no port has signalled
1671 * an interrupt and the guest has cleared all set interrupt
1672 * notification bits.
1673 */
1674 bool fClear = true;
1675
1676 ahci->regHbaIs &= ~(u32Value);
1677
1678 fClear = !ahci->u32PortsInterrupted && !ahci->regHbaIs;
1679 if (fClear)
1680 {
1681 unsigned i = 0;
1682
1683 /* Check if the cleared ports have a interrupt status bit set. */
1684 while ((u32Value > 0) && (i < AHCI_MAX_NR_PORTS_IMPL))
1685 {
1686 if (u32Value & 0x01)
1687 {
1688 PAHCIPort pAhciPort = &ahci->ahciPort[i];
1689
1690 if (pAhciPort->regIE & pAhciPort->regIS)
1691 {
1692 Log(("%s: Interrupt status of port %u set -> Set interrupt again\n", __FUNCTION__, i));
1693 ASMAtomicOrU32(&ahci->u32PortsInterrupted, 1 << i);
1694 fClear = false;
1695 break;
1696 }
1697 }
1698 u32Value = u32Value >> 1;
1699 i++;
1700 }
1701 }
1702
1703 if (fClear)
1704 ahciHbaClearInterrupt(ahci);
1705 else
1706 {
1707 Log(("%s: Not clearing interrupt: u32PortsInterrupted=%#010x\n", __FUNCTION__, ahci->u32PortsInterrupted));
1708 /*
1709 * We need to set the interrupt again because the I/O APIC does not set it again even if the
1710 * line is still high.
1711 * We need to clear it first because the PCI bus only calls the interrupt controller if the state changes.
1712 */
1713 PDMDevHlpPCISetIrq(ahci->CTX_SUFF(pDevIns), 0, 0);
1714 PDMDevHlpPCISetIrq(ahci->CTX_SUFF(pDevIns), 0, 1);
1715 }
1716 }
1717
1718 PDMCritSectLeave(&ahci->lock);
1719 return VINF_SUCCESS;
1720}
1721
1722/**
1723 * Read from the global interrupt status register.
1724 */
1725static int HbaInterruptStatus_r(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value)
1726{
1727 uint32_t u32PortsInterrupted;
1728 int rc;
1729
1730 rc = PDMCritSectEnter(&ahci->lock, VINF_IOM_R3_MMIO_READ);
1731 if (rc != VINF_SUCCESS)
1732 return rc;
1733
1734 u32PortsInterrupted = ASMAtomicXchgU32(&ahci->u32PortsInterrupted, 0);
1735
1736 PDMCritSectLeave(&ahci->lock);
1737 Log(("%s: read regHbaIs=%#010x u32PortsInterrupted=%#010x\n", __FUNCTION__, ahci->regHbaIs, u32PortsInterrupted));
1738
1739 ahci->regHbaIs |= u32PortsInterrupted;
1740
1741#ifdef LOG_ENABLED
1742 Log(("%s:", __FUNCTION__));
1743 unsigned i;
1744 for (i = 0; i < ahci->cPortsImpl; i++)
1745 {
1746 if ((ahci->regHbaIs >> i) & 0x01)
1747 Log((" P%d", i));
1748 }
1749 Log(("\n"));
1750#endif
1751
1752 *pu32Value = ahci->regHbaIs;
1753
1754 return VINF_SUCCESS;
1755}
1756
1757/**
1758 * Write to the global control register.
1759 */
1760static int HbaControl_w(PAHCI ahci, uint32_t iReg, uint32_t u32Value)
1761{
1762 Log(("%s: write u32Value=%#010x\n"
1763 "%s: AE=%d IE=%d HR=%d\n",
1764 __FUNCTION__, u32Value,
1765 __FUNCTION__, (u32Value & AHCI_HBA_CTRL_AE) >> 31, (u32Value & AHCI_HBA_CTRL_IE) >> 1,
1766 (u32Value & AHCI_HBA_CTRL_HR)));
1767
1768#ifndef IN_RING3
1769 return VINF_IOM_R3_MMIO_WRITE;
1770#else
1771 /*
1772 * Increase the active thread counter because we might set the host controller
1773 * reset bit.
1774 */
1775 ASMAtomicIncU32(&ahci->cThreadsActive);
1776 ASMAtomicWriteU32(&ahci->regHbaCtrl, (u32Value & AHCI_HBA_CTRL_RW_MASK) | AHCI_HBA_CTRL_AE);
1777
1778 /*
1779 * Do the HBA reset if requested and there is no other active thread at the moment,
1780 * the work is deferred to the last active thread otherwise.
1781 */
1782 uint32_t cThreadsActive = ASMAtomicDecU32(&ahci->cThreadsActive);
1783 if ( (u32Value & AHCI_HBA_CTRL_HR)
1784 && !cThreadsActive)
1785 ahciHBAReset(ahci);
1786
1787 return VINF_SUCCESS;
1788#endif
1789}
1790
1791/**
1792 * Read the global control register.
1793 */
1794static int HbaControl_r(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value)
1795{
1796 Log(("%s: read regHbaCtrl=%#010x\n"
1797 "%s: AE=%d IE=%d HR=%d\n",
1798 __FUNCTION__, ahci->regHbaCtrl,
1799 __FUNCTION__, (ahci->regHbaCtrl & AHCI_HBA_CTRL_AE) >> 31, (ahci->regHbaCtrl & AHCI_HBA_CTRL_IE) >> 1,
1800 (ahci->regHbaCtrl & AHCI_HBA_CTRL_HR)));
1801 *pu32Value = ahci->regHbaCtrl;
1802 return VINF_SUCCESS;
1803}
1804
1805/**
1806 * Read the global capabilities register.
1807 */
1808static int HbaCapabilities_r(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value)
1809{
1810 Log(("%s: read regHbaCap=%#010x\n"
1811 "%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",
1812 __FUNCTION__, ahci->regHbaCap,
1813 __FUNCTION__, (ahci->regHbaCap & AHCI_HBA_CAP_S64A) >> 31, (ahci->regHbaCap & AHCI_HBA_CAP_SNCQ) >> 30,
1814 (ahci->regHbaCap & AHCI_HBA_CAP_SIS) >> 28, (ahci->regHbaCap & AHCI_HBA_CAP_SSS) >> 27,
1815 (ahci->regHbaCap & AHCI_HBA_CAP_SALP) >> 26, (ahci->regHbaCap & AHCI_HBA_CAP_SAL) >> 25,
1816 (ahci->regHbaCap & AHCI_HBA_CAP_SCLO) >> 24, (ahci->regHbaCap & AHCI_HBA_CAP_ISS) >> 20,
1817 (ahci->regHbaCap & AHCI_HBA_CAP_SNZO) >> 19, (ahci->regHbaCap & AHCI_HBA_CAP_SAM) >> 18,
1818 (ahci->regHbaCap & AHCI_HBA_CAP_SPM) >> 17, (ahci->regHbaCap & AHCI_HBA_CAP_PMD) >> 15,
1819 (ahci->regHbaCap & AHCI_HBA_CAP_SSC) >> 14, (ahci->regHbaCap & AHCI_HBA_CAP_PSC) >> 13,
1820 (ahci->regHbaCap & AHCI_HBA_CAP_NCS) >> 8, (ahci->regHbaCap & AHCI_HBA_CAP_NP)));
1821 *pu32Value = ahci->regHbaCap;
1822 return VINF_SUCCESS;
1823}
1824
1825/**
1826 * Write to the global command completion coalescing control register.
1827 */
1828static int HbaCccCtl_w(PAHCI ahci, uint32_t iReg, uint32_t u32Value)
1829{
1830 Log(("%s: write u32Value=%#010x\n"
1831 "%s: TV=%d CC=%d INT=%d EN=%d\n",
1832 __FUNCTION__, u32Value,
1833 __FUNCTION__, AHCI_HBA_CCC_CTL_TV_GET(u32Value), AHCI_HBA_CCC_CTL_CC_GET(u32Value),
1834 AHCI_HBA_CCC_CTL_INT_GET(u32Value), (u32Value & AHCI_HBA_CCC_CTL_EN)));
1835
1836 ahci->regHbaCccCtl = u32Value;
1837 ahci->uCccTimeout = AHCI_HBA_CCC_CTL_TV_GET(u32Value);
1838 ahci->uCccPortNr = AHCI_HBA_CCC_CTL_INT_GET(u32Value);
1839 ahci->uCccNr = AHCI_HBA_CCC_CTL_CC_GET(u32Value);
1840
1841 if (u32Value & AHCI_HBA_CCC_CTL_EN)
1842 {
1843 /* Arm the timer */
1844 TMTimerSetMillies(ahci->CTX_SUFF(pHbaCccTimer), ahci->uCccTimeout);
1845 }
1846 else
1847 {
1848 TMTimerStop(ahci->CTX_SUFF(pHbaCccTimer));
1849 }
1850
1851 return VINF_SUCCESS;
1852}
1853
1854/**
1855 * Read the global command completion coalescing control register.
1856 */
1857static int HbaCccCtl_r(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value)
1858{
1859 Log(("%s: read regHbaCccCtl=%#010x\n"
1860 "%s: TV=%d CC=%d INT=%d EN=%d\n",
1861 __FUNCTION__, ahci->regHbaCccCtl,
1862 __FUNCTION__, AHCI_HBA_CCC_CTL_TV_GET(ahci->regHbaCccCtl), AHCI_HBA_CCC_CTL_CC_GET(ahci->regHbaCccCtl),
1863 AHCI_HBA_CCC_CTL_INT_GET(ahci->regHbaCccCtl), (ahci->regHbaCccCtl & AHCI_HBA_CCC_CTL_EN)));
1864 *pu32Value = ahci->regHbaCccCtl;
1865 return VINF_SUCCESS;
1866}
1867
1868/**
1869 * Write to the global command completion coalescing ports register.
1870 */
1871static int HbaCccPorts_w(PAHCI ahci, uint32_t iReg, uint32_t u32Value)
1872{
1873 Log(("%s: write u32Value=%#010x\n", __FUNCTION__, u32Value));
1874
1875 ahci->regHbaCccPorts = u32Value;
1876
1877 return VINF_SUCCESS;
1878}
1879
1880/**
1881 * Read the global command completion coalescing ports register.
1882 */
1883static int HbaCccPorts_r(PAHCI ahci, uint32_t iReg, uint32_t *pu32Value)
1884{
1885 Log(("%s: read regHbaCccPorts=%#010x\n", __FUNCTION__, ahci->regHbaCccPorts));
1886
1887#ifdef LOG_ENABLED
1888 Log(("%s:", __FUNCTION__));
1889 unsigned i;
1890 for (i = 0; i < ahci->cPortsImpl; i++)
1891 {
1892 if ((ahci->regHbaCccPorts >> i) & 0x01)
1893 Log((" P%d", i));
1894 }
1895 Log(("\n"));
1896#endif
1897
1898 *pu32Value = ahci->regHbaCccPorts;
1899 return VINF_SUCCESS;
1900}
1901
1902/**
1903 * Invalid write to global register
1904 */
1905static int HbaInvalid_w(PAHCI ahci, uint32_t iReg, uint32_t u32Value)
1906{
1907 Log(("%s: Write denied!!! iReg=%u u32Value=%#010x\n", __FUNCTION__, iReg, u32Value));
1908 return VINF_SUCCESS;
1909}
1910
1911/**
1912 * Invalid Port write.
1913 */
1914static int PortInvalid_w(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t u32Value)
1915{
1916 ahciLog(("%s: Write denied!!! iReg=%u u32Value=%#010x\n", __FUNCTION__, iReg, u32Value));
1917 return VINF_SUCCESS;
1918}
1919
1920/**
1921 * Invalid Port read.
1922 */
1923static int PortInvalid_r(PAHCI ahci, PAHCIPort pAhciPort, uint32_t iReg, uint32_t *pu32Value)
1924{
1925 ahciLog(("%s: Read denied!!! iReg=%u\n", __FUNCTION__, iReg));
1926 return VINF_SUCCESS;
1927}
1928
1929/**
1930 * Register descriptor table for global HBA registers
1931 */
1932static const AHCIOPREG g_aOpRegs[] =
1933{
1934 {"HbaCapabilites", HbaCapabilities_r, HbaInvalid_w}, /* Readonly */
1935 {"HbaControl" , HbaControl_r, HbaControl_w},
1936 {"HbaInterruptStatus", HbaInterruptStatus_r, HbaInterruptStatus_w},
1937 {"HbaPortsImplemented", HbaPortsImplemented_r, HbaInvalid_w}, /* Readonly */
1938 {"HbaVersion", HbaVersion_r, HbaInvalid_w}, /* ReadOnly */
1939 {"HbaCccCtl", HbaCccCtl_r, HbaCccCtl_w},
1940 {"HbaCccPorts", HbaCccPorts_r, HbaCccPorts_w},
1941};
1942
1943/**
1944 * Register descriptor table for port registers
1945 */
1946static const AHCIPORTOPREG g_aPortOpRegs[] =
1947{
1948 {"PortCmdLstAddr", PortCmdLstAddr_r, PortCmdLstAddr_w},
1949 {"PortCmdLstAddrUp", PortCmdLstAddrUp_r, PortCmdLstAddrUp_w},
1950 {"PortFisAddr", PortFisAddr_r, PortFisAddr_w},
1951 {"PortFisAddrUp", PortFisAddrUp_r, PortFisAddrUp_w},
1952 {"PortIntrSts", PortIntrSts_r, PortIntrSts_w},
1953 {"PortIntrEnable", PortIntrEnable_r, PortIntrEnable_w},
1954 {"PortCmd", PortCmd_r, PortCmd_w},
1955 {"PortReserved1", PortInvalid_r, PortInvalid_w}, /* Not used. */
1956 {"PortTaskFileData", PortTaskFileData_r, PortInvalid_w}, /* Readonly */
1957 {"PortSignature", PortSignature_r, PortInvalid_w}, /* Readonly */
1958 {"PortSStatus", PortSStatus_r, PortInvalid_w}, /* Readonly */
1959 {"PortSControl", PortSControl_r, PortSControl_w},
1960 {"PortSError", PortSError_r, PortSError_w},
1961 {"PortSActive", PortSActive_r, PortSActive_w},
1962 {"PortCmdIssue", PortCmdIssue_r, PortCmdIssue_w},
1963 {"PortReserved2", PortInvalid_r, PortInvalid_w}, /* Not used. */
1964};
1965
1966#ifdef IN_RING3
1967/**
1968 * Reset initiated by system software for one port.
1969 *
1970 * @param pAhciPort The port to reset.
1971 */
1972static void ahciPortSwReset(PAHCIPort pAhciPort)
1973{
1974 bool fAllTasksCanceled;
1975
1976 /* Cancel all tasks first. */
1977 fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort);
1978 Assert(fAllTasksCanceled);
1979
1980 pAhciPort->regIS = 0;
1981 pAhciPort->regIE = 0;
1982 pAhciPort->regCMD = AHCI_PORT_CMD_CPD | /* Cold presence detection */
1983 AHCI_PORT_CMD_SUD | /* Device has spun up. */
1984 AHCI_PORT_CMD_POD; /* Port is powered on. */
1985
1986 /* Hotplugging supported?. */
1987 if (pAhciPort->fHotpluggable)
1988 pAhciPort->regCMD |= AHCI_PORT_CMD_HPCP;
1989
1990 pAhciPort->regTFD = (1 << 8) | ATA_STAT_SEEK | ATA_STAT_WRERR;
1991 pAhciPort->regSIG = ~0;
1992 pAhciPort->regSSTS = 0;
1993 pAhciPort->regSCTL = 0;
1994 pAhciPort->regSERR = 0;
1995 pAhciPort->regSACT = 0;
1996 pAhciPort->regCI = 0;
1997
1998 pAhciPort->fResetDevice = false;
1999 pAhciPort->fPoweredOn = true;
2000 pAhciPort->fSpunUp = true;
2001 pAhciPort->cMultSectors = ATA_MAX_MULT_SECTORS;
2002 pAhciPort->uATATransferMode = ATA_MODE_UDMA | 6;
2003
2004 pAhciPort->u32TasksNew = 0;
2005 pAhciPort->u32TasksRedo = 0;
2006 pAhciPort->u32TasksFinished = 0;
2007 pAhciPort->u32QueuedTasksFinished = 0;
2008 pAhciPort->u32CurrentCommandSlot = 0;
2009
2010 pAhciPort->cTasksActive = 0;
2011
2012 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED);
2013 ASMAtomicWriteU32(&pAhciPort->MediaTrackType, ATA_MEDIA_TYPE_UNKNOWN);
2014
2015 if (pAhciPort->pDrvBase)
2016 {
2017 pAhciPort->regCMD |= AHCI_PORT_CMD_CPS; /* Indicate that there is a device on that port */
2018
2019 if (pAhciPort->fPoweredOn)
2020 {
2021 /*
2022 * Set states in the Port Signature and SStatus registers.
2023 */
2024 if (pAhciPort->fATAPI)
2025 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
2026 else
2027 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
2028 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
2029 (0x02 << 4) | /* Generation 2 (3.0GBps) speed. */
2030 (0x03 << 0); /* Device detected and communication established. */
2031 }
2032 }
2033}
2034
2035/**
2036 * Hardware reset used for machine power on and reset.
2037 *
2038 * @param pAhciport The port to reset.
2039 */
2040static void ahciPortHwReset(PAHCIPort pAhciPort)
2041{
2042 /* Reset the address registers. */
2043 pAhciPort->regCLB = 0;
2044 pAhciPort->regCLBU = 0;
2045 pAhciPort->regFB = 0;
2046 pAhciPort->regFBU = 0;
2047
2048 /* Reset calculated addresses. */
2049 pAhciPort->GCPhysAddrClb = 0;
2050 pAhciPort->GCPhysAddrFb = 0;
2051}
2052
2053/**
2054 * Create implemented ports bitmap.
2055 *
2056 * @returns 32bit bitmask with a bit set for every implemented port.
2057 * @param cPorts Number of ports.
2058 */
2059static uint32_t ahciGetPortsImplemented(unsigned cPorts)
2060{
2061 uint32_t uPortsImplemented = 0;
2062
2063 for (unsigned i = 0; i < cPorts; i++)
2064 uPortsImplemented |= (1 << i);
2065
2066 return uPortsImplemented;
2067}
2068
2069/**
2070 * Reset the entire HBA.
2071 *
2072 * @param pThis The HBA state.
2073 */
2074static void ahciHBAReset(PAHCI pThis)
2075{
2076 unsigned i;
2077 int rc = VINF_SUCCESS;
2078
2079 LogRel(("AHCI#%u: Reset the HBA\n", pThis->CTX_SUFF(pDevIns)->iInstance));
2080
2081 /* Stop the CCC timer. */
2082 if (pThis->regHbaCccCtl & AHCI_HBA_CCC_CTL_EN)
2083 {
2084 rc = TMTimerStop(pThis->CTX_SUFF(pHbaCccTimer));
2085 if (RT_FAILURE(rc))
2086 AssertMsgFailed(("%s: Failed to stop timer!\n", __FUNCTION__));
2087 }
2088
2089 /* Reset every port */
2090 for (i = 0; i < pThis->cPortsImpl; i++)
2091 {
2092 PAHCIPort pAhciPort = &pThis->ahciPort[i];
2093
2094 pAhciPort->iLUN = i;
2095 ahciPortSwReset(pAhciPort);
2096 }
2097
2098 /* Init Global registers */
2099 pThis->regHbaCap = AHCI_HBA_CAP_ISS_SHIFT(AHCI_HBA_CAP_ISS_GEN2) |
2100 AHCI_HBA_CAP_S64A | /* 64bit addressing supported */
2101 AHCI_HBA_CAP_SAM | /* AHCI mode only */
2102 AHCI_HBA_CAP_SNCQ | /* Support native command queuing */
2103 AHCI_HBA_CAP_SSS | /* Staggered spin up */
2104 AHCI_HBA_CAP_CCCS | /* Support command completion coalescing */
2105 AHCI_HBA_CAP_NCS_SET(pThis->cCmdSlotsAvail) | /* Number of command slots we support */
2106 AHCI_HBA_CAP_NP_SET(pThis->cPortsImpl); /* Number of supported ports */
2107 pThis->regHbaCtrl = AHCI_HBA_CTRL_AE;
2108 pThis->regHbaPi = ahciGetPortsImplemented(pThis->cPortsImpl);
2109 pThis->regHbaVs = AHCI_HBA_VS_MJR | AHCI_HBA_VS_MNR;
2110 pThis->regHbaCccCtl = 0;
2111 pThis->regHbaCccPorts = 0;
2112 pThis->uCccTimeout = 0;
2113 pThis->uCccPortNr = 0;
2114 pThis->uCccNr = 0;
2115
2116 /* Clear pending interrupts. */
2117 pThis->regHbaIs = 0;
2118 pThis->u32PortsInterrupted = 0;
2119 ahciHbaClearInterrupt(pThis);
2120
2121 pThis->f64BitAddr = false;
2122 pThis->u32PortsInterrupted = 0;
2123 pThis->f8ByteMMIO4BytesWrittenSuccessfully = false;
2124 /* Clear the HBA Reset bit */
2125 pThis->regHbaCtrl &= ~AHCI_HBA_CTRL_HR;
2126}
2127#endif
2128
2129/**
2130 * Reads from a AHCI controller register.
2131 *
2132 * @returns VBox status code.
2133 *
2134 * @param pAhci The AHCI instance.
2135 * @param uReg The register to write.
2136 * @param pv Where to store the result.
2137 * @param cb Number of bytes read.
2138 */
2139static int ahciRegisterRead(PAHCI pAhci, uint32_t uReg, void *pv, unsigned cb)
2140{
2141 int rc = VINF_SUCCESS;
2142 uint32_t iReg;
2143
2144 /*
2145 * If the access offset is smaller than AHCI_HBA_GLOBAL_SIZE the guest accesses the global registers.
2146 * Otherwise it accesses the registers of a port.
2147 */
2148 if (uReg < AHCI_HBA_GLOBAL_SIZE)
2149 {
2150 iReg = uReg >> 2;
2151 Log3(("%s: Trying to read from global register %u\n", __FUNCTION__, iReg));
2152 if (iReg < RT_ELEMENTS(g_aOpRegs))
2153 {
2154 const AHCIOPREG *pReg = &g_aOpRegs[iReg];
2155 rc = pReg->pfnRead(pAhci, iReg, (uint32_t *)pv);
2156 }
2157 else
2158 {
2159 Log3(("%s: Trying to read global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs)));
2160 *(uint32_t *)pv = 0;
2161 }
2162 }
2163 else
2164 {
2165 uint32_t iRegOffset;
2166 uint32_t iPort;
2167
2168 /* Calculate accessed port. */
2169 uReg -= AHCI_HBA_GLOBAL_SIZE;
2170 iPort = uReg / AHCI_PORT_REGISTER_SIZE;
2171 iRegOffset = (uReg % AHCI_PORT_REGISTER_SIZE);
2172 iReg = iRegOffset >> 2;
2173
2174 Log3(("%s: Trying to read from port %u and register %u\n", __FUNCTION__, iPort, iReg));
2175
2176 if (RT_LIKELY( iPort < pAhci->cPortsImpl
2177 && iReg < RT_ELEMENTS(g_aPortOpRegs)))
2178 {
2179 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg];
2180 rc = pPortReg->pfnRead(pAhci, &pAhci->ahciPort[iPort], iReg, (uint32_t *)pv);
2181 }
2182 else
2183 {
2184 Log3(("%s: Trying to read port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs)));
2185 rc = VINF_IOM_MMIO_UNUSED_00;
2186 }
2187
2188 /*
2189 * Windows Vista tries to read one byte from some registers instead of four.
2190 * Correct the value according to the read size.
2191 */
2192 if (RT_SUCCESS(rc) && cb != sizeof(uint32_t))
2193 {
2194 switch (cb)
2195 {
2196 case 1:
2197 {
2198 uint8_t uNewValue;
2199 uint8_t *p = (uint8_t *)pv;
2200
2201 iRegOffset &= 3;
2202 Log3(("%s: iRegOffset=%u\n", __FUNCTION__, iRegOffset));
2203 uNewValue = p[iRegOffset];
2204 /* Clear old value */
2205 *(uint32_t *)pv = 0;
2206 *(uint8_t *)pv = uNewValue;
2207 break;
2208 }
2209 default:
2210 AssertMsgFailed(("%s: unsupported access width cb=%d iPort=%x iRegOffset=%x iReg=%x!!!\n",
2211 __FUNCTION__, cb, iPort, iRegOffset, iReg));
2212 }
2213 }
2214 }
2215
2216 return rc;
2217}
2218
2219/**
2220 * Writes a value to one of the AHCI controller registers.
2221 *
2222 * @returns VBox status code.
2223 *
2224 * @param pAhci The AHCI instance.
2225 * @param offReg The offset of the register to write to.
2226 * @param u32Value The value to write.
2227 */
2228static int ahciRegisterWrite(PAHCI pAhci, uint32_t offReg, uint32_t u32Value)
2229{
2230 int rc;
2231 uint32_t iReg;
2232
2233 /*
2234 * If the access offset is smaller than 100h the guest accesses the global registers.
2235 * Otherwise it accesses the registers of a port.
2236 */
2237 if (offReg < AHCI_HBA_GLOBAL_SIZE)
2238 {
2239 Log3(("Write global HBA register\n"));
2240 iReg = offReg >> 2;
2241 if (iReg < RT_ELEMENTS(g_aOpRegs))
2242 {
2243 const AHCIOPREG *pReg = &g_aOpRegs[iReg];
2244 rc = pReg->pfnWrite(pAhci, iReg, u32Value);
2245 }
2246 else
2247 {
2248 Log3(("%s: Trying to write global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs)));
2249 rc = VINF_SUCCESS;
2250 }
2251 }
2252 else
2253 {
2254 uint32_t iPort;
2255 Log3(("Write Port register\n"));
2256 /* Calculate accessed port. */
2257 offReg -= AHCI_HBA_GLOBAL_SIZE;
2258 iPort = offReg / AHCI_PORT_REGISTER_SIZE;
2259 iReg = (offReg % AHCI_PORT_REGISTER_SIZE) >> 2;
2260 Log3(("%s: Trying to write to port %u and register %u\n", __FUNCTION__, iPort, iReg));
2261 if (RT_LIKELY( iPort < pAhci->cPortsImpl
2262 && iReg < RT_ELEMENTS(g_aPortOpRegs)))
2263 {
2264 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg];
2265 rc = pPortReg->pfnWrite(pAhci, &pAhci->ahciPort[iPort], iReg, u32Value);
2266 }
2267 else
2268 {
2269 Log3(("%s: Trying to write port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs)));
2270 rc = VINF_SUCCESS;
2271 }
2272 }
2273
2274 return rc;
2275}
2276
2277/**
2278 * Memory mapped I/O Handler for read operations.
2279 *
2280 * @returns VBox status code.
2281 *
2282 * @param pDevIns The device instance.
2283 * @param pvUser User argument.
2284 * @param GCPhysAddr Physical address (in GC) where the read starts.
2285 * @param pv Where to store the result.
2286 * @param cb Number of bytes read.
2287 */
2288PDMBOTHCBDECL(int) ahciMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
2289{
2290 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2291 Log2(("#%d ahciMMIORead: pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp\n",
2292 pDevIns->iInstance, pv, cb, pv, cb, GCPhysAddr));
2293
2294 int rc = ahciRegisterRead(pAhci, GCPhysAddr - pAhci->MMIOBase, pv, cb);
2295
2296 Log2(("#%d ahciMMIORead: return pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp rc=%Rrc\n",
2297 pDevIns->iInstance, pv, cb, pv, cb, GCPhysAddr, rc));
2298 return rc;
2299}
2300
2301
2302/**
2303 * Memory mapped I/O Handler for write operations.
2304 *
2305 * @returns VBox status code.
2306 *
2307 * @param pDevIns The device instance.
2308 * @param pvUser User argument.
2309 * @param GCPhysAddr Physical address (in GC) where the read starts.
2310 * @param pv Where to fetch the result.
2311 * @param cb Number of bytes to write.
2312 */
2313PDMBOTHCBDECL(int) ahciMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
2314{
2315 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2316 Assert(cb == 4 || cb == 8);
2317 Assert(!(GCPhysAddr & (cb - 1)));
2318
2319 /* Break up 64 bits writes into two dword writes. */
2320 /** @todo Eliminate this code once the IOM/EM starts taking care of these
2321 * situations. */
2322 if (cb == 8)
2323 {
2324 /*
2325 * Only write the first 4 bytes if they weren't already.
2326 * It is possible that the last write to the register caused a world
2327 * switch and we entered this function again.
2328 * Writing the first 4 bytes again could cause indeterminate behavior
2329 * which can cause errors in the guest.
2330 */
2331 int rc = VINF_SUCCESS;
2332 if (!pAhci->f8ByteMMIO4BytesWrittenSuccessfully)
2333 {
2334 rc = ahciMMIOWrite(pDevIns, pvUser, GCPhysAddr, pv, 4);
2335 if (rc != VINF_SUCCESS)
2336 return rc;
2337
2338 pAhci->f8ByteMMIO4BytesWrittenSuccessfully = true;
2339 }
2340
2341 rc = ahciMMIOWrite(pDevIns, pvUser, GCPhysAddr + 4, (uint8_t *)pv + 4, 4);
2342 /*
2343 * Reset flag again so that the first 4 bytes are written again on the next
2344 * 8byte MMIO access.
2345 */
2346 if (rc == VINF_SUCCESS)
2347 pAhci->f8ByteMMIO4BytesWrittenSuccessfully = false;
2348
2349 return rc;
2350 }
2351
2352 /* Do the access. */
2353 Log2(("#%d ahciMMIOWrite: pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp\n", pDevIns->iInstance, pv, cb, pv, cb, GCPhysAddr));
2354 return ahciRegisterWrite(pAhci, GCPhysAddr - pAhci->MMIOBase, *(uint32_t const *)pv);
2355}
2356
2357PDMBOTHCBDECL(int) ahciLegacyFakeWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
2358{
2359 AssertMsgFailed(("Should not happen\n"));
2360 return VINF_SUCCESS;
2361}
2362
2363PDMBOTHCBDECL(int) ahciLegacyFakeRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
2364{
2365 AssertMsgFailed(("Should not happen\n"));
2366 return VINF_SUCCESS;
2367}
2368
2369/**
2370 * I/O port handler for writes to the index/data register pair.
2371 *
2372 * @returns VBox status code.
2373 *
2374 * @param pDevIns The device instance.
2375 * @param pvUser User argument.
2376 * @param Port Port address where the write starts.
2377 * @param pv Where to fetch the result.
2378 * @param cb Number of bytes to write.
2379 */
2380PDMBOTHCBDECL(int) ahciIdxDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
2381{
2382 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2383 int rc = VINF_SUCCESS;
2384
2385 if (Port - pAhci->IOPortBase >= 8)
2386 {
2387 unsigned iReg = (Port - pAhci->IOPortBase - 8) / 4;
2388
2389 Assert(cb == 4);
2390
2391 if (iReg == 0)
2392 {
2393 /* Write the index register. */
2394 pAhci->regIdx = u32;
2395 }
2396 else
2397 {
2398 /** @todo range check? */
2399 Assert(iReg == 1);
2400 rc = ahciRegisterWrite(pAhci, pAhci->regIdx, u32);
2401 if (rc == VINF_IOM_R3_MMIO_WRITE)
2402 rc = VINF_IOM_R3_IOPORT_WRITE;
2403 }
2404 }
2405 /* else: ignore */
2406
2407 Log2(("#%d ahciIdxDataWrite: pu32=%p:{%.*Rhxs} cb=%d Port=%#x rc=%Rrc\n",
2408 pDevIns->iInstance, &u32, cb, &u32, cb, Port, rc));
2409 return rc;
2410}
2411
2412/**
2413 * I/O port handler for reads from the index/data register pair.
2414 *
2415 * @returns VBox status code.
2416 *
2417 * @param pDevIns The device instance.
2418 * @param pvUser User argument.
2419 * @param Port Port address where the read starts.
2420 * @param pv Where to fetch the result.
2421 * @param cb Number of bytes to write.
2422 */
2423PDMBOTHCBDECL(int) ahciIdxDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
2424{
2425 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
2426 int rc = VINF_SUCCESS;
2427
2428 if (Port - pAhci->IOPortBase >= 8)
2429 {
2430 unsigned iReg = (Port - pAhci->IOPortBase - 8) / 4;
2431
2432 Assert(cb == 4);
2433
2434 if (iReg == 0)
2435 {
2436 /* Read the index register. */
2437 *pu32 = pAhci->regIdx;
2438 }
2439 else
2440 {
2441 Assert(iReg == 1);
2442 /** @todo range check? */
2443 rc = ahciRegisterRead(pAhci, pAhci->regIdx, pu32, cb);
2444 if (rc == VINF_IOM_R3_MMIO_READ)
2445 rc = VINF_IOM_R3_IOPORT_READ;
2446 else if (rc == VINF_IOM_MMIO_UNUSED_00)
2447 rc = VERR_IOM_IOPORT_UNUSED;
2448 }
2449 }
2450 else
2451 *pu32 = UINT32_C(0xffffffff);
2452
2453 Log2(("#%d ahciIdxDataRead: pu32=%p:{%.*Rhxs} cb=%d Port=%#x rc=%Rrc\n",
2454 pDevIns->iInstance, pu32, cb, pu32, cb, Port, rc));
2455 return rc;
2456}
2457
2458#ifdef IN_RING3
2459
2460static DECLCALLBACK(int) ahciR3MMIOMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
2461{
2462 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev);
2463 PPDMDEVINS pDevIns = pPciDev->pDevIns;
2464 int rc = VINF_SUCCESS;
2465
2466 Log2(("%s: registering MMIO area at GCPhysAddr=%RGp cb=%u\n", __FUNCTION__, GCPhysAddress, cb));
2467
2468 Assert(enmType == PCI_ADDRESS_SPACE_MEM);
2469 Assert(cb >= 4352);
2470
2471 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
2472 /** @todo change this to IOMMMIO_FLAGS_WRITE_ONLY_DWORD once EM/IOM starts
2473 * handling 2nd DWORD failures on split accesses correctly. */
2474 rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
2475 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD,
2476 ahciMMIOWrite, ahciMMIORead, "AHCI");
2477 if (RT_FAILURE(rc))
2478 return rc;
2479
2480 if (pThis->fR0Enabled)
2481 {
2482 rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/, "ahciMMIOWrite", "ahciMMIORead");
2483 if (RT_FAILURE(rc))
2484 return rc;
2485 }
2486
2487 if (pThis->fGCEnabled)
2488 {
2489 rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/, "ahciMMIOWrite", "ahciMMIORead");
2490 if (RT_FAILURE(rc))
2491 return rc;
2492 }
2493
2494 pThis->MMIOBase = GCPhysAddress;
2495 return rc;
2496}
2497
2498/**
2499 * Map the legacy I/O port ranges to make Solaris work with the controller.
2500 */
2501static DECLCALLBACK(int) ahciR3LegacyFakeIORangeMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
2502{
2503 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev);
2504 PPDMDEVINS pDevIns = pPciDev->pDevIns;
2505 int rc = VINF_SUCCESS;
2506
2507 Log2(("%s: registering fake I/O area at GCPhysAddr=%RGp cb=%u\n", __FUNCTION__, GCPhysAddress, cb));
2508
2509 Assert(enmType == PCI_ADDRESS_SPACE_IO);
2510
2511 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
2512 rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, cb, NULL,
2513 ahciLegacyFakeWrite, ahciLegacyFakeRead, NULL, NULL, "AHCI Fake");
2514 if (RT_FAILURE(rc))
2515 return rc;
2516
2517 if (pThis->fR0Enabled)
2518 {
2519 rc = PDMDevHlpIOPortRegisterR0(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
2520 "ahciLegacyFakeWrite", "ahciLegacyFakeRead", NULL, NULL, "AHCI Fake");
2521 if (RT_FAILURE(rc))
2522 return rc;
2523 }
2524
2525 if (pThis->fGCEnabled)
2526 {
2527 rc = PDMDevHlpIOPortRegisterRC(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
2528 "ahciLegacyFakeWrite", "ahciLegacyFakeRead", NULL, NULL, "AHCI Fake");
2529 if (RT_FAILURE(rc))
2530 return rc;
2531 }
2532
2533 return rc;
2534}
2535
2536/**
2537 * Map the BMDMA I/O port range (used for the Index/Data pair register access)
2538 */
2539static DECLCALLBACK(int) ahciR3IdxDataIORangeMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
2540{
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=%u\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, PDMIBLOCKPORT, &pAhciPort->IPort);
2616 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBLOCKASYNCPORT, &pAhciPort->IPortAsync);
2617 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pAhciPort->IMountNotify);
2618 return NULL;
2619}
2620
2621/**
2622 * @interface_method_impl{PDMIBLOCKPORT,pfnQueryDeviceLocation}
2623 */
2624static DECLCALLBACK(int) ahciR3PortQueryDeviceLocation(PPDMIBLOCKPORT pInterface, const char **ppcszController,
2625 uint32_t *piInstance, uint32_t *piLUN)
2626{
2627 PAHCIPort pAhciPort = PDMIBLOCKPORT_2_PAHCIPORT(pInterface);
2628 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
2629
2630 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
2631 AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
2632 AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
2633
2634 *ppcszController = pDevIns->pReg->szName;
2635 *piInstance = pDevIns->iInstance;
2636 *piLUN = pAhciPort->iLUN;
2637
2638 return VINF_SUCCESS;
2639}
2640
2641#ifdef LOG_ENABLED
2642
2643/**
2644 * Dump info about the FIS
2645 *
2646 * @returns nothing
2647 * @param pAhciPort The port the command FIS was read from.
2648 * @param cmdFis The FIS to print info from.
2649 */
2650static void ahciDumpFisInfo(PAHCIPort pAhciPort, uint8_t *cmdFis)
2651{
2652 ahciLog(("%s: *** Begin FIS info dump. ***\n", __FUNCTION__));
2653 /* Print FIS type. */
2654 switch (cmdFis[AHCI_CMDFIS_TYPE])
2655 {
2656 case AHCI_CMDFIS_TYPE_H2D:
2657 {
2658 ahciLog(("%s: Command Fis type: H2D\n", __FUNCTION__));
2659 ahciLog(("%s: Command Fis size: %d bytes\n", __FUNCTION__, AHCI_CMDFIS_TYPE_H2D_SIZE));
2660 if (cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)
2661 ahciLog(("%s: Command register update\n", __FUNCTION__));
2662 else
2663 ahciLog(("%s: Control register update\n", __FUNCTION__));
2664 ahciLog(("%s: CMD=%#04x \"%s\"\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CMD], ATACmdText(cmdFis[AHCI_CMDFIS_CMD])));
2665 ahciLog(("%s: FEAT=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FET]));
2666 ahciLog(("%s: SECTN=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTN]));
2667 ahciLog(("%s: CYLL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLL]));
2668 ahciLog(("%s: CYLH=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLH]));
2669 ahciLog(("%s: HEAD=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_HEAD]));
2670
2671 ahciLog(("%s: SECTNEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTNEXP]));
2672 ahciLog(("%s: CYLLEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLLEXP]));
2673 ahciLog(("%s: CYLHEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLHEXP]));
2674 ahciLog(("%s: FETEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FETEXP]));
2675
2676 ahciLog(("%s: SECTC=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTC]));
2677 ahciLog(("%s: SECTCEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTCEXP]));
2678 ahciLog(("%s: CTL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CTL]));
2679 if (cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
2680 ahciLog(("%s: Reset bit is set\n", __FUNCTION__));
2681 break;
2682 }
2683 case AHCI_CMDFIS_TYPE_D2H:
2684 {
2685 ahciLog(("%s: Command Fis type D2H\n", __FUNCTION__));
2686 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_D2H_SIZE));
2687 break;
2688 }
2689 case AHCI_CMDFIS_TYPE_SETDEVBITS:
2690 {
2691 ahciLog(("%s: Command Fis type Set Device Bits\n", __FUNCTION__));
2692 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE));
2693 break;
2694 }
2695 case AHCI_CMDFIS_TYPE_DMAACTD2H:
2696 {
2697 ahciLog(("%s: Command Fis type DMA Activate H2D\n", __FUNCTION__));
2698 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMAACTD2H_SIZE));
2699 break;
2700 }
2701 case AHCI_CMDFIS_TYPE_DMASETUP:
2702 {
2703 ahciLog(("%s: Command Fis type DMA Setup\n", __FUNCTION__));
2704 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMASETUP_SIZE));
2705 break;
2706 }
2707 case AHCI_CMDFIS_TYPE_PIOSETUP:
2708 {
2709 ahciLog(("%s: Command Fis type PIO Setup\n", __FUNCTION__));
2710 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_PIOSETUP_SIZE));
2711 break;
2712 }
2713 case AHCI_CMDFIS_TYPE_DATA:
2714 {
2715 ahciLog(("%s: Command Fis type Data\n", __FUNCTION__));
2716 break;
2717 }
2718 default:
2719 ahciLog(("%s: ERROR Unknown command FIS type\n", __FUNCTION__));
2720 break;
2721 }
2722 ahciLog(("%s: *** End FIS info dump. ***\n", __FUNCTION__));
2723}
2724
2725/**
2726 * Dump info about the command header
2727 *
2728 * @returns nothing
2729 * @param pAhciPort Pointer to the port the command header was read from.
2730 * @param pCmdHdr The command header to print info from.
2731 */
2732static void ahciDumpCmdHdrInfo(PAHCIPort pAhciPort, CmdHdr *pCmdHdr)
2733{
2734 ahciLog(("%s: *** Begin command header info dump. ***\n", __FUNCTION__));
2735 ahciLog(("%s: Number of Scatter/Gatther List entries: %u\n", __FUNCTION__, AHCI_CMDHDR_PRDTL_ENTRIES(pCmdHdr->u32DescInf)));
2736 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_C)
2737 ahciLog(("%s: Clear busy upon R_OK\n", __FUNCTION__));
2738 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_B)
2739 ahciLog(("%s: BIST Fis\n", __FUNCTION__));
2740 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_R)
2741 ahciLog(("%s: Device Reset Fis\n", __FUNCTION__));
2742 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_P)
2743 ahciLog(("%s: Command prefetchable\n", __FUNCTION__));
2744 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_W)
2745 ahciLog(("%s: Device write\n", __FUNCTION__));
2746 else
2747 ahciLog(("%s: Device read\n", __FUNCTION__));
2748 if (pCmdHdr->u32DescInf & AHCI_CMDHDR_A)
2749 ahciLog(("%s: ATAPI command\n", __FUNCTION__));
2750 else
2751 ahciLog(("%s: ATA command\n", __FUNCTION__));
2752
2753 ahciLog(("%s: Command FIS length %u DW\n", __FUNCTION__, (pCmdHdr->u32DescInf & AHCI_CMDHDR_CFL_MASK)));
2754 ahciLog(("%s: *** End command header info dump. ***\n", __FUNCTION__));
2755}
2756
2757#endif /* LOG_ENABLED */
2758
2759/**
2760 * Post the first D2H FIS from the device into guest memory.
2761 *
2762 * @returns nothing
2763 * @param pAhciPort Pointer to the port which "receives" the FIS.
2764 */
2765static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort)
2766{
2767 uint8_t d2hFis[AHCI_CMDFIS_TYPE_D2H_SIZE];
2768
2769 pAhciPort->fFirstD2HFisSend = true;
2770
2771 ahciLog(("%s: Sending First D2H FIS from FIFO\n", __FUNCTION__));
2772 memset(&d2hFis[0], 0, sizeof(d2hFis));
2773 d2hFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_D2H;
2774 d2hFis[AHCI_CMDFIS_ERR] = 0x01;
2775
2776 d2hFis[AHCI_CMDFIS_STS] = 0x00;
2777
2778 /* Set the signature based on the device type. */
2779 if (pAhciPort->fATAPI)
2780 {
2781 d2hFis[AHCI_CMDFIS_CYLL] = 0x14;
2782 d2hFis[AHCI_CMDFIS_CYLH] = 0xeb;
2783 }
2784 else
2785 {
2786 d2hFis[AHCI_CMDFIS_CYLL] = 0x00;
2787 d2hFis[AHCI_CMDFIS_CYLH] = 0x00;
2788 }
2789
2790 d2hFis[AHCI_CMDFIS_HEAD] = 0x00;
2791 d2hFis[AHCI_CMDFIS_SECTN] = 0x01;
2792 d2hFis[AHCI_CMDFIS_SECTC] = 0x01;
2793
2794 pAhciPort->regTFD = (1 << 8) | ATA_STAT_SEEK | ATA_STAT_WRERR;
2795 if (!pAhciPort->fATAPI)
2796 pAhciPort->regTFD |= ATA_STAT_READY;
2797
2798 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis);
2799}
2800
2801/**
2802 * Post the FIS in the memory area allocated by the guest and set interrupt if necessary.
2803 *
2804 * @returns VBox status code
2805 * @param pAhciPort The port which "receives" the FIS.
2806 * @param uFisType The type of the FIS.
2807 * @param pCmdFis Pointer to the FIS which is to be posted into memory.
2808 */
2809static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *pCmdFis)
2810{
2811 int rc = VINF_SUCCESS;
2812 RTGCPHYS GCPhysAddrRecFis = pAhciPort->GCPhysAddrFb;
2813 unsigned cbFis = 0;
2814
2815 ahciLog(("%s: pAhciPort=%p uFisType=%u pCmdFis=%p\n", __FUNCTION__, pAhciPort, uFisType, pCmdFis));
2816
2817 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
2818 {
2819 AssertMsg(GCPhysAddrRecFis, ("%s: GCPhysAddrRecFis is 0\n", __FUNCTION__));
2820
2821 /* Determine the offset and size of the FIS based on uFisType. */
2822 switch (uFisType)
2823 {
2824 case AHCI_CMDFIS_TYPE_D2H:
2825 {
2826 GCPhysAddrRecFis += AHCI_RECFIS_RFIS_OFFSET;
2827 cbFis = AHCI_CMDFIS_TYPE_D2H_SIZE;
2828 break;
2829 }
2830 case AHCI_CMDFIS_TYPE_SETDEVBITS:
2831 {
2832 GCPhysAddrRecFis += AHCI_RECFIS_SDBFIS_OFFSET;
2833 cbFis = AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE;
2834 break;
2835 }
2836 case AHCI_CMDFIS_TYPE_DMASETUP:
2837 {
2838 GCPhysAddrRecFis += AHCI_RECFIS_DSFIS_OFFSET;
2839 cbFis = AHCI_CMDFIS_TYPE_DMASETUP_SIZE;
2840 break;
2841 }
2842 case AHCI_CMDFIS_TYPE_PIOSETUP:
2843 {
2844 GCPhysAddrRecFis += AHCI_RECFIS_PSFIS_OFFSET;
2845 cbFis = AHCI_CMDFIS_TYPE_PIOSETUP_SIZE;
2846 break;
2847 }
2848 default:
2849 /*
2850 * We should post the unknown FIS into memory too but this never happens because
2851 * we know which FIS types we generate. ;)
2852 */
2853 AssertMsgFailed(("%s: Unknown FIS type!\n", __FUNCTION__));
2854 }
2855
2856 /* Post the FIS into memory. */
2857 ahciLog(("%s: PDMDevHlpPCIPhysWrite GCPhysAddrRecFis=%RGp cbFis=%u\n", __FUNCTION__, GCPhysAddrRecFis, cbFis));
2858 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrRecFis, pCmdFis, cbFis);
2859 }
2860
2861 return rc;
2862}
2863
2864DECLINLINE(void) ataH2BE_U16(uint8_t *pbBuf, uint16_t val)
2865{
2866 pbBuf[0] = val >> 8;
2867 pbBuf[1] = val;
2868}
2869
2870
2871DECLINLINE(void) ataH2BE_U24(uint8_t *pbBuf, uint32_t val)
2872{
2873 pbBuf[0] = val >> 16;
2874 pbBuf[1] = val >> 8;
2875 pbBuf[2] = val;
2876}
2877
2878
2879DECLINLINE(void) ataH2BE_U32(uint8_t *pbBuf, uint32_t val)
2880{
2881 pbBuf[0] = val >> 24;
2882 pbBuf[1] = val >> 16;
2883 pbBuf[2] = val >> 8;
2884 pbBuf[3] = val;
2885}
2886
2887
2888DECLINLINE(uint16_t) ataBE2H_U16(const uint8_t *pbBuf)
2889{
2890 return (pbBuf[0] << 8) | pbBuf[1];
2891}
2892
2893
2894DECLINLINE(uint32_t) ataBE2H_U24(const uint8_t *pbBuf)
2895{
2896 return (pbBuf[0] << 16) | (pbBuf[1] << 8) | pbBuf[2];
2897}
2898
2899
2900DECLINLINE(uint32_t) ataBE2H_U32(const uint8_t *pbBuf)
2901{
2902 return (pbBuf[0] << 24) | (pbBuf[1] << 16) | (pbBuf[2] << 8) | pbBuf[3];
2903}
2904
2905
2906DECLINLINE(void) ataLBA2MSF(uint8_t *pbBuf, uint32_t iATAPILBA)
2907{
2908 iATAPILBA += 150;
2909 pbBuf[0] = (iATAPILBA / 75) / 60;
2910 pbBuf[1] = (iATAPILBA / 75) % 60;
2911 pbBuf[2] = iATAPILBA % 75;
2912}
2913
2914
2915DECLINLINE(uint32_t) ataMSF2LBA(const uint8_t *pbBuf)
2916{
2917 return (pbBuf[0] * 60 + pbBuf[1]) * 75 + pbBuf[2];
2918}
2919
2920static void atapiCmdOK(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
2921{
2922 pAhciReq->uATARegError = 0;
2923 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
2924 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7)
2925 | ((pAhciReq->enmTxDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0)
2926 | (!pAhciReq->cbTransfer ? ATAPI_INT_REASON_CD : 0);
2927 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense));
2928 pAhciPort->abATAPISense[0] = 0x70;
2929 pAhciPort->abATAPISense[7] = 10;
2930}
2931
2932static void atapiCmdError(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, const uint8_t *pabATAPISense, size_t cbATAPISense)
2933{
2934 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, pabATAPISense[2] & 0x0f, SCSISenseText(pabATAPISense[2] & 0x0f),
2935 pabATAPISense[12], pabATAPISense[13], SCSISenseExtText(pabATAPISense[12], pabATAPISense[13])));
2936 pAhciReq->uATARegError = pabATAPISense[2] << 4;
2937 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
2938 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7) |
2939 ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
2940 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense));
2941 memcpy(pAhciPort->abATAPISense, pabATAPISense, RT_MIN(cbATAPISense, sizeof(pAhciPort->abATAPISense)));
2942}
2943
2944/** @todo deprecated function - doesn't provide enough info. Replace by direct
2945 * calls to atapiCmdError() with full data. */
2946static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t uATAPISenseKey, uint8_t uATAPIASC)
2947{
2948 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
2949 memset(abATAPISense, '\0', sizeof(abATAPISense));
2950 abATAPISense[0] = 0x70 | (1 << 7);
2951 abATAPISense[2] = uATAPISenseKey & 0x0f;
2952 abATAPISense[7] = 10;
2953 abATAPISense[12] = uATAPIASC;
2954 atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
2955}
2956
2957static void ataSCSIPadStr(uint8_t *pbDst, const char *pbSrc, uint32_t cbSize)
2958{
2959 for (uint32_t i = 0; i < cbSize; i++)
2960 {
2961 if (*pbSrc)
2962 pbDst[i] = *pbSrc++;
2963 else
2964 pbDst[i] = ' ';
2965 }
2966}
2967
2968static void ataPadString(uint8_t *pbDst, const char *pbSrc, uint32_t cbSize)
2969{
2970 for (uint32_t i = 0; i < cbSize; i++)
2971 {
2972 if (*pbSrc)
2973 pbDst[i ^ 1] = *pbSrc++;
2974 else
2975 pbDst[i ^ 1] = ' ';
2976 }
2977}
2978
2979static uint32_t ataChecksum(void* ptr, size_t count)
2980{
2981 uint8_t u8Sum = 0xa5, *p = (uint8_t*)ptr;
2982 size_t i;
2983
2984 for (i = 0; i < count; i++)
2985 {
2986 u8Sum += *p++;
2987 }
2988
2989 return (uint8_t)-(int32_t)u8Sum;
2990}
2991
2992static int ahciIdentifySS(PAHCIPort pAhciPort, void *pvBuf)
2993{
2994 uint16_t *p;
2995 int rc = VINF_SUCCESS;
2996
2997 p = (uint16_t *)pvBuf;
2998 memset(p, 0, 512);
2999 p[0] = RT_H2LE_U16(0x0040);
3000 p[1] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383));
3001 p[3] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cHeads);
3002 /* Block size; obsolete, but required for the BIOS. */
3003 p[5] = RT_H2LE_U16(512);
3004 p[6] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cSectors);
3005 ataPadString((uint8_t *)(p + 10), pAhciPort->szSerialNumber, AHCI_SERIAL_NUMBER_LENGTH); /* serial number */
3006 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
3007 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
3008 p[22] = RT_H2LE_U16(0); /* ECC bytes per sector */
3009 ataPadString((uint8_t *)(p + 23), pAhciPort->szFirmwareRevision, AHCI_FIRMWARE_REVISION_LENGTH); /* firmware version */
3010 ataPadString((uint8_t *)(p + 27), pAhciPort->szModelNumber, AHCI_MODEL_NUMBER_LENGTH); /* model */
3011#if ATA_MAX_MULT_SECTORS > 1
3012 p[47] = RT_H2LE_U16(0x8000 | ATA_MAX_MULT_SECTORS);
3013#endif
3014 p[48] = RT_H2LE_U16(1); /* dword I/O, used by the BIOS */
3015 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
3016 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
3017 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
3018 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
3019 p[53] = RT_H2LE_U16(1 | 1 << 1 | 1 << 2); /* words 54-58,64-70,88 valid */
3020 p[54] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383));
3021 p[55] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cHeads);
3022 p[56] = RT_H2LE_U16(pAhciPort->PCHSGeometry.cSectors);
3023 p[57] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors);
3024 p[58] = RT_H2LE_U16(RT_MIN(pAhciPort->PCHSGeometry.cCylinders, 16383) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors >> 16);
3025 if (pAhciPort->cMultSectors)
3026 p[59] = RT_H2LE_U16(0x100 | pAhciPort->cMultSectors);
3027 if (pAhciPort->cTotalSectors <= (1 << 28) - 1)
3028 {
3029 p[60] = RT_H2LE_U16(pAhciPort->cTotalSectors);
3030 p[61] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 16);
3031 }
3032 else
3033 {
3034 /* Report maximum number of sectors possible with LBA28 */
3035 p[60] = RT_H2LE_U16(((1 << 28) - 1) & 0xffff);
3036 p[61] = RT_H2LE_U16(((1 << 28) - 1) >> 16);
3037 }
3038 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* MDMA modes supported / mode enabled */
3039 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
3040 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
3041 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
3042 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
3043 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
3044 if ( pAhciPort->pDrvBlock->pfnDiscard
3045 || ( pAhciPort->fAsyncInterface
3046 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)
3047 || pAhciPort->cbSector != 512
3048 || pAhciPort->fNonRotational)
3049 {
3050 p[80] = RT_H2LE_U16(0x1f0); /* support everything up to ATA/ATAPI-8 ACS */
3051 p[81] = RT_H2LE_U16(0x28); /* conforms to ATA/ATAPI-8 ACS */
3052 }
3053 else
3054 {
3055 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
3056 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
3057 }
3058 p[82] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* supports power management, write cache and look-ahead */
3059 p[83] = RT_H2LE_U16(1 << 14 | 1 << 10 | 1 << 12 | 1 << 13); /* supports LBA48, FLUSH CACHE and FLUSH CACHE EXT */
3060 p[84] = RT_H2LE_U16(1 << 14);
3061 p[85] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* enabled power management, write cache and look-ahead */
3062 p[86] = RT_H2LE_U16(1 << 10 | 1 << 12 | 1 << 13); /* enabled LBA48, FLUSH CACHE and FLUSH CACHE EXT */
3063 p[87] = RT_H2LE_U16(1 << 14);
3064 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* UDMA modes supported / mode enabled */
3065 p[93] = RT_H2LE_U16(0x00);
3066 p[100] = RT_H2LE_U16(pAhciPort->cTotalSectors);
3067 p[101] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 16);
3068 p[102] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 32);
3069 p[103] = RT_H2LE_U16(pAhciPort->cTotalSectors >> 48);
3070
3071 /* valid information, more than one logical sector per physical sector, 2^cLogSectorsPerPhysicalExp logical sectors per physical sector */
3072 if (pAhciPort->cLogSectorsPerPhysicalExp)
3073 p[106] = RT_H2LE_U16(RT_BIT(14) | RT_BIT(13) | pAhciPort->cLogSectorsPerPhysicalExp);
3074
3075 if (pAhciPort->cbSector != 512)
3076 {
3077 uint32_t cSectorSizeInWords = pAhciPort->cbSector / sizeof(uint16_t);
3078 /* Enable reporting of logical sector size. */
3079 p[106] |= RT_H2LE_U16(RT_BIT(12) | RT_BIT(14));
3080 p[117] = RT_H2LE_U16(cSectorSizeInWords);
3081 p[118] = RT_H2LE_U16(cSectorSizeInWords >> 16);
3082 }
3083
3084 if (pAhciPort->fNonRotational)
3085 p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
3086
3087 if ( pAhciPort->pDrvBlock->pfnDiscard
3088 || ( pAhciPort->fAsyncInterface
3089 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */
3090 p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */
3091
3092 /* The following are SATA specific */
3093 p[75] = RT_H2LE_U16(pAhciPort->CTX_SUFF(pAhci)->cCmdSlotsAvail-1); /* Number of commands we support, 0's based */
3094 p[76] = RT_H2LE_U16((1 << 8) | (1 << 2)); /* Native command queuing and Serial ATA Gen2 (3.0 Gbps) speed supported */
3095
3096 uint32_t uCsum = ataChecksum(p, 510);
3097 p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
3098
3099 return VINF_SUCCESS;
3100}
3101
3102typedef int (*PAtapiFunc)(PAHCIREQ, PAHCIPort, size_t, size_t *);
3103
3104static int atapiGetConfigurationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3105static int atapiGetEventStatusNotificationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3106static int atapiIdentifySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3107static int atapiInquirySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3108static int atapiMechanismStatusSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3109static int atapiModeSenseErrorRecoverySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3110static int atapiModeSenseCDStatusSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3111static int atapiReadCapacitySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3112static int atapiReadDiscInformationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3113static int atapiReadTOCNormalSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3114static int atapiReadTOCMultiSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3115static int atapiReadTOCRawSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3116static int atapiReadTrackInformationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3117static int atapiRequestSenseSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3118static int atapiPassthroughSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3119static int atapiReadDVDStructureSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
3120
3121/**
3122 * Source/sink function indexes for g_apfnAtapiFuncs.
3123 */
3124typedef enum ATAPIFN
3125{
3126 ATAFN_SS_NULL = 0,
3127 ATAFN_SS_ATAPI_GET_CONFIGURATION,
3128 ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION,
3129 ATAFN_SS_ATAPI_IDENTIFY,
3130 ATAFN_SS_ATAPI_INQUIRY,
3131 ATAFN_SS_ATAPI_MECHANISM_STATUS,
3132 ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY,
3133 ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS,
3134 ATAFN_SS_ATAPI_READ_CAPACITY,
3135 ATAFN_SS_ATAPI_READ_DISC_INFORMATION,
3136 ATAFN_SS_ATAPI_READ_TOC_NORMAL,
3137 ATAFN_SS_ATAPI_READ_TOC_MULTI,
3138 ATAFN_SS_ATAPI_READ_TOC_RAW,
3139 ATAFN_SS_ATAPI_READ_TRACK_INFORMATION,
3140 ATAFN_SS_ATAPI_REQUEST_SENSE,
3141 ATAFN_SS_ATAPI_PASSTHROUGH,
3142 ATAFN_SS_ATAPI_READ_DVD_STRUCTURE,
3143 ATAFN_SS_MAX
3144} ATAPIFN;
3145
3146/**
3147 * Array of source/sink functions, the index is ATAFNSS.
3148 * Make sure ATAFNSS and this array match!
3149 */
3150static const PAtapiFunc g_apfnAtapiFuncs[ATAFN_SS_MAX] =
3151{
3152 NULL,
3153 atapiGetConfigurationSS,
3154 atapiGetEventStatusNotificationSS,
3155 atapiIdentifySS,
3156 atapiInquirySS,
3157 atapiMechanismStatusSS,
3158 atapiModeSenseErrorRecoverySS,
3159 atapiModeSenseCDStatusSS,
3160 atapiReadCapacitySS,
3161 atapiReadDiscInformationSS,
3162 atapiReadTOCNormalSS,
3163 atapiReadTOCMultiSS,
3164 atapiReadTOCRawSS,
3165 atapiReadTrackInformationSS,
3166 atapiRequestSenseSS,
3167 atapiPassthroughSS,
3168 atapiReadDVDStructureSS
3169};
3170
3171static int atapiIdentifySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3172{
3173 uint16_t p[256];
3174
3175 memset(p, 0, 512);
3176 /* Removable CDROM, 50us response, 12 byte packets */
3177 p[0] = RT_H2LE_U16(2 << 14 | 5 << 8 | 1 << 7 | 2 << 5 | 0 << 0);
3178 ataPadString((uint8_t *)(p + 10), pAhciPort->szSerialNumber, AHCI_SERIAL_NUMBER_LENGTH); /* serial number */
3179 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
3180 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
3181 ataPadString((uint8_t *)(p + 23), pAhciPort->szFirmwareRevision, AHCI_FIRMWARE_REVISION_LENGTH); /* firmware version */
3182 ataPadString((uint8_t *)(p + 27), pAhciPort->szModelNumber, AHCI_MODEL_NUMBER_LENGTH); /* model */
3183 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
3184 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
3185 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
3186 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
3187 p[53] = RT_H2LE_U16(1 << 1 | 1 << 2); /* words 64-70,88 are valid */
3188 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* MDMA modes supported / mode enabled */
3189 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
3190 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
3191 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
3192 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
3193 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
3194 p[73] = RT_H2LE_U16(0x003e); /* ATAPI CDROM major */
3195 p[74] = RT_H2LE_U16(9); /* ATAPI CDROM minor */
3196 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
3197 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
3198 p[82] = RT_H2LE_U16(1 << 4 | 1 << 9); /* supports packet command set and DEVICE RESET */
3199 p[83] = RT_H2LE_U16(1 << 14);
3200 p[84] = RT_H2LE_U16(1 << 14);
3201 p[85] = RT_H2LE_U16(1 << 4 | 1 << 9); /* enabled packet command set and DEVICE RESET */
3202 p[86] = RT_H2LE_U16(0);
3203 p[87] = RT_H2LE_U16(1 << 14);
3204 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, pAhciPort->uATATransferMode)); /* UDMA modes supported / mode enabled */
3205 p[93] = RT_H2LE_U16((1 | 1 << 1) << ((pAhciPort->iLUN & 1) == 0 ? 0 : 8) | 1 << 13 | 1 << 14);
3206
3207 /* The following are SATA specific */
3208 p[75] = RT_H2LE_U16(31); /* We support 32 commands */
3209 p[76] = RT_H2LE_U16((1 << 8) | (1 << 2)); /* Native command queuing and Serial ATA Gen2 (3.0 Gbps) speed supported */
3210
3211 /* Copy the buffer in to the scatter gather list. */
3212 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&p[0],
3213 RT_MIN(cbData, sizeof(p)));
3214
3215 atapiCmdOK(pAhciPort, pAhciReq);
3216 return VINF_SUCCESS;
3217}
3218
3219static int atapiReadCapacitySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3220{
3221 uint8_t aBuf[8];
3222
3223 ataH2BE_U32(aBuf, pAhciPort->cTotalSectors - 1);
3224 ataH2BE_U32(aBuf + 4, 2048);
3225
3226 /* Copy the buffer in to the scatter gather list. */
3227 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3228 RT_MIN(cbData, sizeof(aBuf)));
3229
3230 atapiCmdOK(pAhciPort, pAhciReq);
3231 return VINF_SUCCESS;
3232}
3233
3234
3235static int atapiReadDiscInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3236{
3237 uint8_t aBuf[34];
3238
3239 memset(aBuf, '\0', 34);
3240 ataH2BE_U16(aBuf, 32);
3241 aBuf[2] = (0 << 4) | (3 << 2) | (2 << 0); /* not erasable, complete session, complete disc */
3242 aBuf[3] = 1; /* number of first track */
3243 aBuf[4] = 1; /* number of sessions (LSB) */
3244 aBuf[5] = 1; /* first track number in last session (LSB) */
3245 aBuf[6] = 1; /* last track number in last session (LSB) */
3246 aBuf[7] = (0 << 7) | (0 << 6) | (1 << 5) | (0 << 2) | (0 << 0); /* disc id not valid, disc bar code not valid, unrestricted use, not dirty, not RW medium */
3247 aBuf[8] = 0; /* disc type = CD-ROM */
3248 aBuf[9] = 0; /* number of sessions (MSB) */
3249 aBuf[10] = 0; /* number of sessions (MSB) */
3250 aBuf[11] = 0; /* number of sessions (MSB) */
3251 ataH2BE_U32(aBuf + 16, 0x00ffffff); /* last session lead-in start time is not available */
3252 ataH2BE_U32(aBuf + 20, 0x00ffffff); /* last possible start time for lead-out is not available */
3253
3254 /* Copy the buffer in to the scatter gather list. */
3255 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3256 RT_MIN(cbData, sizeof(aBuf)));
3257
3258 atapiCmdOK(pAhciPort, pAhciReq);
3259 return VINF_SUCCESS;
3260}
3261
3262
3263static int atapiReadTrackInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3264{
3265 uint8_t aBuf[36];
3266
3267 /* Accept address/number type of 1 only, and only track 1 exists. */
3268 if ((pAhciReq->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&pAhciReq->aATAPICmd[2]) != 1)
3269 {
3270 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3271 return VINF_SUCCESS;
3272 }
3273 memset(aBuf, '\0', 36);
3274 ataH2BE_U16(aBuf, 34);
3275 aBuf[2] = 1; /* track number (LSB) */
3276 aBuf[3] = 1; /* session number (LSB) */
3277 aBuf[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */
3278 aBuf[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */
3279 aBuf[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */
3280 ataH2BE_U32(aBuf + 8, 0); /* track start address is 0 */
3281 ataH2BE_U32(aBuf + 24, pAhciPort->cTotalSectors); /* track size */
3282 aBuf[32] = 0; /* track number (MSB) */
3283 aBuf[33] = 0; /* session number (MSB) */
3284
3285 /* Copy the buffer in to the scatter gather list. */
3286 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3287 RT_MIN(cbData, sizeof(aBuf)));
3288
3289 atapiCmdOK(pAhciPort, pAhciReq);
3290 return VINF_SUCCESS;
3291}
3292
3293static size_t atapiGetConfigurationFillFeatureListProfiles(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3294{
3295 if (cbBuf < 3*4)
3296 return 0;
3297
3298 ataH2BE_U16(pbBuf, 0x0); /* feature 0: list of profiles supported */
3299 pbBuf[2] = (0 << 2) | (1 << 1) | (1 || 0); /* version 0, persistent, current */
3300 pbBuf[3] = 8; /* additional bytes for profiles */
3301 /* The MMC-3 spec says that DVD-ROM read capability should be reported
3302 * before CD-ROM read capability. */
3303 ataH2BE_U16(pbBuf + 4, 0x10); /* profile: read-only DVD */
3304 pbBuf[6] = (0 << 0); /* NOT current profile */
3305 ataH2BE_U16(pbBuf + 8, 0x08); /* profile: read only CD */
3306 pbBuf[10] = (1 << 0); /* current profile */
3307
3308 return 3*4; /* Header + 2 profiles entries */
3309}
3310
3311static size_t atapiGetConfigurationFillFeatureCore(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3312{
3313 if (cbBuf < 12)
3314 return 0;
3315
3316 ataH2BE_U16(pbBuf, 0x1); /* feature 0001h: Core Feature */
3317 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
3318 pbBuf[3] = 8; /* Additional length */
3319 ataH2BE_U16(pbBuf + 4, 0x00000002); /* Physical interface ATAPI. */
3320 pbBuf[8] = RT_BIT(0); /* DBE */
3321 /* Rest is reserved. */
3322
3323 return 12;
3324}
3325
3326static size_t atapiGetConfigurationFillFeatureMorphing(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3327{
3328 if (cbBuf < 8)
3329 return 0;
3330
3331 ataH2BE_U16(pbBuf, 0x2); /* feature 0002h: Morphing Feature */
3332 pbBuf[2] = (0x1 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
3333 pbBuf[3] = 4; /* Additional length */
3334 pbBuf[4] = RT_BIT(1) | 0x0; /* OCEvent | !ASYNC */
3335 /* Rest is reserved. */
3336
3337 return 8;
3338}
3339
3340static size_t atapiGetConfigurationFillFeatureRemovableMedium(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3341{
3342 if (cbBuf < 8)
3343 return 0;
3344
3345 ataH2BE_U16(pbBuf, 0x3); /* feature 0003h: Removable Medium Feature */
3346 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
3347 pbBuf[3] = 4; /* Additional length */
3348 /* Tray type loading | Load | Eject | !Pvnt Jmpr | !DBML | Lock */
3349 pbBuf[4] = (0x2 << 5) | RT_BIT(4) | RT_BIT(3) | (0x0 << 2) | (0x0 << 1) | RT_BIT(0);
3350 /* Rest is reserved. */
3351
3352 return 8;
3353}
3354
3355static size_t atapiGetConfigurationFillFeatureRandomReadable(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3356{
3357 if (cbBuf < 12)
3358 return 0;
3359
3360 ataH2BE_U16(pbBuf, 0x10); /* feature 0010h: Random Readable Feature */
3361 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
3362 pbBuf[3] = 8; /* Additional length */
3363 ataH2BE_U32(pbBuf + 4, 2048); /* Logical block size. */
3364 ataH2BE_U16(pbBuf + 8, 0x10); /* Blocking (0x10 for DVD, CD is not defined). */
3365 pbBuf[10] = 0; /* PP not present */
3366 /* Rest is reserved. */
3367
3368 return 12;
3369}
3370
3371static size_t atapiGetConfigurationFillFeatureCDRead(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3372{
3373 if (cbBuf < 8)
3374 return 0;
3375
3376 ataH2BE_U16(pbBuf, 0x1e); /* feature 001Eh: CD Read Feature */
3377 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
3378 pbBuf[3] = 0; /* Additional length */
3379 pbBuf[4] = (0x0 << 7) | (0x0 << 1) | 0x0; /* !DAP | !C2-Flags | !CD-Text. */
3380 /* Rest is reserved. */
3381
3382 return 8;
3383}
3384
3385static size_t atapiGetConfigurationFillFeaturePowerManagement(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3386{
3387 if (cbBuf < 4)
3388 return 0;
3389
3390 ataH2BE_U16(pbBuf, 0x100); /* feature 0100h: Power Management Feature */
3391 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
3392 pbBuf[3] = 0; /* Additional length */
3393
3394 return 4;
3395}
3396
3397static size_t atapiGetConfigurationFillFeatureTimeout(PAHCIPort pAhciPort, uint8_t *pbBuf, size_t cbBuf)
3398{
3399 if (cbBuf < 8)
3400 return 0;
3401
3402 ataH2BE_U16(pbBuf, 0x105); /* feature 0105h: Timeout Feature */
3403 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
3404 pbBuf[3] = 4; /* Additional length */
3405 pbBuf[4] = 0x0; /* !Group3 */
3406
3407 return 8;
3408}
3409
3410static int atapiGetConfigurationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3411{
3412 uint8_t aBuf[80];
3413 uint8_t *pbBuf = &aBuf[0];
3414 size_t cbBuf = sizeof(aBuf);
3415 size_t cbCopied = 0;
3416
3417 /* Accept valid request types only, and only starting feature 0. */
3418 if ((pAhciReq->aATAPICmd[1] & 0x03) == 3 || ataBE2H_U16(&pAhciReq->aATAPICmd[2]) != 0)
3419 {
3420 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3421 return VINF_SUCCESS;
3422 }
3423 /** @todo implement switching between CD-ROM and DVD-ROM profile (the only
3424 * way to differentiate them right now is based on the image size). */
3425 if (pAhciPort->cTotalSectors)
3426 ataH2BE_U16(pbBuf + 6, 0x08); /* current profile: read-only CD */
3427 else
3428 ataH2BE_U16(pbBuf + 6, 0x00); /* current profile: none -> no media */
3429 cbBuf -= 8;
3430 pbBuf += 8;
3431
3432 cbCopied = atapiGetConfigurationFillFeatureListProfiles(pAhciPort, pbBuf, cbBuf);
3433 cbBuf -= cbCopied;
3434 pbBuf += cbCopied;
3435
3436 cbCopied = atapiGetConfigurationFillFeatureCore(pAhciPort, pbBuf, cbBuf);
3437 cbBuf -= cbCopied;
3438 pbBuf += cbCopied;
3439
3440 cbCopied = atapiGetConfigurationFillFeatureMorphing(pAhciPort, pbBuf, cbBuf);
3441 cbBuf -= cbCopied;
3442 pbBuf += cbCopied;
3443
3444 cbCopied = atapiGetConfigurationFillFeatureRemovableMedium(pAhciPort, pbBuf, cbBuf);
3445 cbBuf -= cbCopied;
3446 pbBuf += cbCopied;
3447
3448 cbCopied = atapiGetConfigurationFillFeatureRandomReadable(pAhciPort, pbBuf, cbBuf);
3449 cbBuf -= cbCopied;
3450 pbBuf += cbCopied;
3451
3452 cbCopied = atapiGetConfigurationFillFeatureCDRead(pAhciPort, pbBuf, cbBuf);
3453 cbBuf -= cbCopied;
3454 pbBuf += cbCopied;
3455
3456 cbCopied = atapiGetConfigurationFillFeaturePowerManagement(pAhciPort, pbBuf, cbBuf);
3457 cbBuf -= cbCopied;
3458 pbBuf += cbCopied;
3459
3460 cbCopied = atapiGetConfigurationFillFeatureTimeout(pAhciPort, pbBuf, cbBuf);
3461 cbBuf -= cbCopied;
3462 pbBuf += cbCopied;
3463
3464 /* Set data length now. */
3465 ataH2BE_U32(&aBuf[0], sizeof(aBuf) - cbBuf);
3466
3467 /* Copy the buffer in to the scatter gather list. */
3468 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3469 RT_MIN(cbData, sizeof(aBuf)));
3470
3471 atapiCmdOK(pAhciPort, pAhciReq);
3472 return VINF_SUCCESS;
3473}
3474
3475
3476static int atapiGetEventStatusNotificationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3477{
3478 uint8_t abBuf[8];
3479
3480 Assert(pAhciReq->enmTxDir == AHCITXDIR_READ);
3481 Assert(pAhciReq->cbTransfer <= 8);
3482
3483 if (!(pAhciReq->aATAPICmd[1] & 1))
3484 {
3485 /* no asynchronous operation supported */
3486 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3487 return VINF_SUCCESS;
3488 }
3489
3490 uint32_t OldStatus, NewStatus;
3491 do
3492 {
3493 OldStatus = ASMAtomicReadU32(&pAhciPort->MediaEventStatus);
3494 NewStatus = ATA_EVENT_STATUS_UNCHANGED;
3495 switch (OldStatus)
3496 {
3497 case ATA_EVENT_STATUS_MEDIA_NEW:
3498 /* mount */
3499 ataH2BE_U16(abBuf + 0, 6);
3500 abBuf[2] = 0x04; /* media */
3501 abBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3502 abBuf[4] = 0x02; /* new medium */
3503 abBuf[5] = 0x02; /* medium present / door closed */
3504 abBuf[6] = 0x00;
3505 abBuf[7] = 0x00;
3506 break;
3507
3508 case ATA_EVENT_STATUS_MEDIA_CHANGED:
3509 case ATA_EVENT_STATUS_MEDIA_REMOVED:
3510 /* umount */
3511 ataH2BE_U16(abBuf + 0, 6);
3512 abBuf[2] = 0x04; /* media */
3513 abBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3514 abBuf[4] = 0x03; /* media removal */
3515 abBuf[5] = 0x00; /* medium absent / door closed */
3516 abBuf[6] = 0x00;
3517 abBuf[7] = 0x00;
3518 if (OldStatus == ATA_EVENT_STATUS_MEDIA_CHANGED)
3519 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW;
3520 break;
3521
3522 case ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED: /* currently unused */
3523 ataH2BE_U16(abBuf + 0, 6);
3524 abBuf[2] = 0x04; /* media */
3525 abBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3526 abBuf[4] = 0x01; /* eject requested (eject button pressed) */
3527 abBuf[5] = 0x02; /* medium present / door closed */
3528 abBuf[6] = 0x00;
3529 abBuf[7] = 0x00;
3530 break;
3531
3532 case ATA_EVENT_STATUS_UNCHANGED:
3533 default:
3534 ataH2BE_U16(abBuf + 0, 6);
3535 abBuf[2] = 0x01; /* operational change request / notification */
3536 abBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3537 abBuf[4] = 0x00;
3538 abBuf[5] = 0x00;
3539 abBuf[6] = 0x00;
3540 abBuf[7] = 0x00;
3541 break;
3542 }
3543 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus));
3544
3545 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&abBuf[0],
3546 RT_MIN(cbData, sizeof(abBuf)));
3547
3548 atapiCmdOK(pAhciPort, pAhciReq);
3549 return VINF_SUCCESS;
3550}
3551
3552
3553static int atapiInquirySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3554{
3555 uint8_t aBuf[36];
3556
3557 aBuf[0] = 0x05; /* CD-ROM */
3558 aBuf[1] = 0x80; /* removable */
3559 aBuf[2] = 0x00; /* ISO */
3560 aBuf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
3561 aBuf[4] = 31; /* additional length */
3562 aBuf[5] = 0; /* reserved */
3563 aBuf[6] = 0; /* reserved */
3564 aBuf[7] = 0; /* reserved */
3565 ataSCSIPadStr(aBuf + 8, pAhciPort->szInquiryVendorId, 8);
3566 ataSCSIPadStr(aBuf + 16, pAhciPort->szInquiryProductId, 16);
3567 ataSCSIPadStr(aBuf + 32, pAhciPort->szInquiryRevision, 4);
3568
3569 /* Copy the buffer in to the scatter gather list. */
3570 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3571 RT_MIN(cbData, sizeof(aBuf)));
3572
3573 atapiCmdOK(pAhciPort, pAhciReq);
3574 return VINF_SUCCESS;
3575}
3576
3577
3578static int atapiModeSenseErrorRecoverySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3579{
3580 uint8_t aBuf[16];
3581
3582 ataH2BE_U16(&aBuf[0], 16 + 6);
3583 aBuf[2] = 0x70;
3584 aBuf[3] = 0;
3585 aBuf[4] = 0;
3586 aBuf[5] = 0;
3587 aBuf[6] = 0;
3588 aBuf[7] = 0;
3589
3590 aBuf[8] = 0x01;
3591 aBuf[9] = 0x06;
3592 aBuf[10] = 0x00;
3593 aBuf[11] = 0x05;
3594 aBuf[12] = 0x00;
3595 aBuf[13] = 0x00;
3596 aBuf[14] = 0x00;
3597 aBuf[15] = 0x00;
3598
3599 /* Copy the buffer in to the scatter gather list. */
3600 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3601 RT_MIN(cbData, sizeof(aBuf)));
3602
3603 atapiCmdOK(pAhciPort, pAhciReq);
3604 return VINF_SUCCESS;
3605}
3606
3607
3608static int atapiModeSenseCDStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3609{
3610 uint8_t aBuf[40];
3611
3612 ataH2BE_U16(&aBuf[0], 38);
3613 aBuf[2] = 0x70;
3614 aBuf[3] = 0;
3615 aBuf[4] = 0;
3616 aBuf[5] = 0;
3617 aBuf[6] = 0;
3618 aBuf[7] = 0;
3619
3620 aBuf[8] = 0x2a;
3621 aBuf[9] = 30; /* page length */
3622 aBuf[10] = 0x08; /* DVD-ROM read support */
3623 aBuf[11] = 0x00; /* no write support */
3624 /* The following claims we support audio play. This is obviously false,
3625 * but the Linux generic CDROM support makes many features depend on this
3626 * capability. If it's not set, this causes many things to be disabled. */
3627 aBuf[12] = 0x71; /* multisession support, mode 2 form 1/2 support, audio play */
3628 aBuf[13] = 0x00; /* no subchannel reads supported */
3629 aBuf[14] = (1 << 0) | (1 << 3) | (1 << 5); /* lock supported, eject supported, tray type loading mechanism */
3630 if (pAhciPort->pDrvMount->pfnIsLocked(pAhciPort->pDrvMount))
3631 aBuf[14] |= 1 << 1; /* report lock state */
3632 aBuf[15] = 0; /* no subchannel reads supported, no separate audio volume control, no changer etc. */
3633 ataH2BE_U16(&aBuf[16], 5632); /* (obsolete) claim 32x speed support */
3634 ataH2BE_U16(&aBuf[18], 2); /* number of audio volume levels */
3635 ataH2BE_U16(&aBuf[20], 128); /* buffer size supported in Kbyte - We don't have a buffer because we write directly into guest memory.
3636 Just write the value DevATA is using. */
3637 ataH2BE_U16(&aBuf[22], 5632); /* (obsolete) current read speed 32x */
3638 aBuf[24] = 0; /* reserved */
3639 aBuf[25] = 0; /* reserved for digital audio (see idx 15) */
3640 ataH2BE_U16(&aBuf[26], 0); /* (obsolete) maximum write speed */
3641 ataH2BE_U16(&aBuf[28], 0); /* (obsolete) current write speed */
3642 ataH2BE_U16(&aBuf[30], 0); /* copy management revision supported 0=no CSS */
3643 aBuf[32] = 0; /* reserved */
3644 aBuf[33] = 0; /* reserved */
3645 aBuf[34] = 0; /* reserved */
3646 aBuf[35] = 1; /* rotation control CAV */
3647 ataH2BE_U16(&aBuf[36], 0); /* current write speed */
3648 ataH2BE_U16(&aBuf[38], 0); /* number of write speed performance descriptors */
3649
3650 /* Copy the buffer in to the scatter gather list. */
3651 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3652 RT_MIN(cbData, sizeof(aBuf)));
3653
3654 atapiCmdOK(pAhciPort, pAhciReq);
3655 return VINF_SUCCESS;
3656}
3657
3658
3659static int atapiRequestSenseSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3660{
3661 /* Copy the buffer in to the scatter gather list. */
3662 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
3663 pAhciPort->abATAPISense, RT_MIN(cbData, sizeof(pAhciPort->abATAPISense)));
3664
3665 atapiCmdOK(pAhciPort, pAhciReq);
3666 return VINF_SUCCESS;
3667}
3668
3669
3670static int atapiMechanismStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3671{
3672 uint8_t aBuf[8];
3673
3674 ataH2BE_U16(&aBuf[0], 0);
3675 /* no current LBA */
3676 aBuf[2] = 0;
3677 aBuf[3] = 0;
3678 aBuf[4] = 0;
3679 aBuf[5] = 1;
3680 ataH2BE_U16(aBuf + 6, 0);
3681
3682 /* Copy the buffer in to the scatter gather list. */
3683 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3684 RT_MIN(cbData, sizeof(aBuf)));
3685
3686 atapiCmdOK(pAhciPort, pAhciReq);
3687 return VINF_SUCCESS;
3688}
3689
3690
3691static int atapiReadTOCNormalSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3692{
3693 uint8_t aBuf[20], *q, iStartTrack;
3694 bool fMSF;
3695 uint32_t cbSize;
3696
3697 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
3698 iStartTrack = pAhciReq->aATAPICmd[6];
3699 if (iStartTrack > 1 && iStartTrack != 0xaa)
3700 {
3701 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3702 return VINF_SUCCESS;
3703 }
3704 q = aBuf + 2;
3705 *q++ = 1; /* first session */
3706 *q++ = 1; /* last session */
3707 if (iStartTrack <= 1)
3708 {
3709 *q++ = 0; /* reserved */
3710 *q++ = 0x14; /* ADR, control */
3711 *q++ = 1; /* track number */
3712 *q++ = 0; /* reserved */
3713 if (fMSF)
3714 {
3715 *q++ = 0; /* reserved */
3716 ataLBA2MSF(q, 0);
3717 q += 3;
3718 }
3719 else
3720 {
3721 /* sector 0 */
3722 ataH2BE_U32(q, 0);
3723 q += 4;
3724 }
3725 }
3726 /* lead out track */
3727 *q++ = 0; /* reserved */
3728 *q++ = 0x14; /* ADR, control */
3729 *q++ = 0xaa; /* track number */
3730 *q++ = 0; /* reserved */
3731 if (fMSF)
3732 {
3733 *q++ = 0; /* reserved */
3734 ataLBA2MSF(q, pAhciPort->cTotalSectors);
3735 q += 3;
3736 }
3737 else
3738 {
3739 ataH2BE_U32(q, pAhciPort->cTotalSectors);
3740 q += 4;
3741 }
3742 cbSize = q - aBuf;
3743 ataH2BE_U16(aBuf, cbSize - 2);
3744
3745 /* Copy the buffer in to the scatter gather list. */
3746 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3747 RT_MIN(cbData, cbSize));
3748
3749 atapiCmdOK(pAhciPort, pAhciReq);
3750 return VINF_SUCCESS;
3751}
3752
3753
3754static int atapiReadTOCMultiSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3755{
3756 uint8_t aBuf[12];
3757 bool fMSF;
3758
3759 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
3760 /* multi session: only a single session defined */
3761/** @todo double-check this stuff against what a real drive says for a CD-ROM (not a CD-R) with only a single data session. Maybe solve the problem with "cdrdao read-toc" not being able to figure out whether numbers are in BCD or hex. */
3762 memset(aBuf, 0, 12);
3763 aBuf[1] = 0x0a;
3764 aBuf[2] = 0x01;
3765 aBuf[3] = 0x01;
3766 aBuf[5] = 0x14; /* ADR, control */
3767 aBuf[6] = 1; /* first track in last complete session */
3768 if (fMSF)
3769 {
3770 aBuf[8] = 0; /* reserved */
3771 ataLBA2MSF(&aBuf[9], 0);
3772 }
3773 else
3774 {
3775 /* sector 0 */
3776 ataH2BE_U32(aBuf + 8, 0);
3777 }
3778
3779 /* Copy the buffer in to the scatter gather list. */
3780 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3781 RT_MIN(cbData, sizeof(aBuf)));
3782
3783 atapiCmdOK(pAhciPort, pAhciReq);
3784 return VINF_SUCCESS;
3785}
3786
3787
3788static int atapiReadTOCRawSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3789{
3790 uint8_t aBuf[50]; /* Counted a maximum of 45 bytes but better be on the safe side. */
3791 uint8_t *q, iStartTrack;
3792 bool fMSF;
3793 uint32_t cbSize;
3794
3795 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
3796 iStartTrack = pAhciReq->aATAPICmd[6];
3797
3798 q = aBuf + 2;
3799 *q++ = 1; /* first session */
3800 *q++ = 1; /* last session */
3801
3802 *q++ = 1; /* session number */
3803 *q++ = 0x14; /* data track */
3804 *q++ = 0; /* track number */
3805 *q++ = 0xa0; /* first track in program area */
3806 *q++ = 0; /* min */
3807 *q++ = 0; /* sec */
3808 *q++ = 0; /* frame */
3809 *q++ = 0;
3810 *q++ = 1; /* first track */
3811 *q++ = 0x00; /* disk type CD-DA or CD data */
3812 *q++ = 0;
3813
3814 *q++ = 1; /* session number */
3815 *q++ = 0x14; /* data track */
3816 *q++ = 0; /* track number */
3817 *q++ = 0xa1; /* last track in program area */
3818 *q++ = 0; /* min */
3819 *q++ = 0; /* sec */
3820 *q++ = 0; /* frame */
3821 *q++ = 0;
3822 *q++ = 1; /* last track */
3823 *q++ = 0;
3824 *q++ = 0;
3825
3826 *q++ = 1; /* session number */
3827 *q++ = 0x14; /* data track */
3828 *q++ = 0; /* track number */
3829 *q++ = 0xa2; /* lead-out */
3830 *q++ = 0; /* min */
3831 *q++ = 0; /* sec */
3832 *q++ = 0; /* frame */
3833 if (fMSF)
3834 {
3835 *q++ = 0; /* reserved */
3836 ataLBA2MSF(q, pAhciPort->cTotalSectors);
3837 q += 3;
3838 }
3839 else
3840 {
3841 ataH2BE_U32(q, pAhciPort->cTotalSectors);
3842 q += 4;
3843 }
3844
3845 *q++ = 1; /* session number */
3846 *q++ = 0x14; /* ADR, control */
3847 *q++ = 0; /* track number */
3848 *q++ = 1; /* point */
3849 *q++ = 0; /* min */
3850 *q++ = 0; /* sec */
3851 *q++ = 0; /* frame */
3852 if (fMSF)
3853 {
3854 *q++ = 0; /* reserved */
3855 ataLBA2MSF(q, 0);
3856 q += 3;
3857 }
3858 else
3859 {
3860 /* sector 0 */
3861 ataH2BE_U32(q, 0);
3862 q += 4;
3863 }
3864
3865 cbSize = q - aBuf;
3866 ataH2BE_U16(aBuf, cbSize - 2);
3867
3868 /* Copy the buffer in to the scatter gather list. */
3869 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
3870 RT_MIN(cbData, cbSize));
3871
3872 atapiCmdOK(pAhciPort, pAhciReq);
3873 return VINF_SUCCESS;
3874}
3875
3876/**
3877 * Sets the given media track type.
3878 */
3879static uint32_t ahciMediumTypeSet(PAHCIPort pAhciPort, uint32_t MediaTrackType)
3880{
3881 return ASMAtomicXchgU32(&pAhciPort->MediaTrackType, MediaTrackType);
3882}
3883
3884static int atapiPassthroughSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
3885{
3886 int rc = VINF_SUCCESS;
3887 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
3888 uint32_t cbTransfer;
3889 void *pvBuf = NULL;
3890
3891 cbTransfer = pAhciReq->cbTransfer;
3892
3893 if (cbTransfer)
3894 {
3895 pvBuf = (uint8_t *)RTMemAlloc(cbTransfer);
3896 if (!pvBuf)
3897 return VERR_NO_MEMORY;
3898
3899 if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
3900 {
3901 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);
3902 if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
3903 return VINF_SUCCESS;
3904 }
3905 }
3906
3907 /* Simple heuristics: if there is at least one sector of data
3908 * to transfer, it's worth updating the LEDs. */
3909 if (cbTransfer >= 2048)
3910 {
3911 if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
3912 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
3913 else
3914 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
3915 }
3916
3917 if (cbTransfer > SCSI_MAX_BUFFER_SIZE)
3918 {
3919 /* Linux accepts commands with up to 100KB of data, but expects
3920 * us to handle commands with up to 128KB of data. The usual
3921 * imbalance of powers. */
3922 uint8_t aATAPICmd[ATAPI_PACKET_SIZE];
3923 uint32_t iATAPILBA, cSectors, cReqSectors, cbCurrTX;
3924 uint8_t *pbBuf = (uint8_t *)pvBuf;
3925
3926 switch (pAhciReq->aATAPICmd[0])
3927 {
3928 case SCSI_READ_10:
3929 case SCSI_WRITE_10:
3930 case SCSI_WRITE_AND_VERIFY_10:
3931 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
3932 cSectors = ataBE2H_U16(pAhciReq->aATAPICmd + 7);
3933 break;
3934 case SCSI_READ_12:
3935 case SCSI_WRITE_12:
3936 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
3937 cSectors = ataBE2H_U32(pAhciReq->aATAPICmd + 6);
3938 break;
3939 case SCSI_READ_CD:
3940 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
3941 cSectors = ataBE2H_U24(pAhciReq->aATAPICmd + 6);
3942 break;
3943 case SCSI_READ_CD_MSF:
3944 iATAPILBA = ataMSF2LBA(pAhciReq->aATAPICmd + 3);
3945 cSectors = ataMSF2LBA(pAhciReq->aATAPICmd + 6) - iATAPILBA;
3946 break;
3947 default:
3948 AssertMsgFailed(("Don't know how to split command %#04x\n", pAhciReq->aATAPICmd[0]));
3949 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
3950 LogRel(("AHCI: LUN#%d: CD-ROM passthrough split error\n", pAhciPort->iLUN));
3951 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
3952 RTMemFree(pvBuf);
3953 return VINF_SUCCESS;
3954 }
3955 memcpy(aATAPICmd, pAhciReq->aATAPICmd, ATAPI_PACKET_SIZE);
3956 cReqSectors = 0;
3957 for (uint32_t i = cSectors; i > 0; i -= cReqSectors)
3958 {
3959 if (i * pAhciReq->cbATAPISector > SCSI_MAX_BUFFER_SIZE)
3960 cReqSectors = SCSI_MAX_BUFFER_SIZE / pAhciReq->cbATAPISector;
3961 else
3962 cReqSectors = i;
3963 cbCurrTX = pAhciReq->cbATAPISector * cReqSectors;
3964 switch (pAhciReq->aATAPICmd[0])
3965 {
3966 case SCSI_READ_10:
3967 case SCSI_WRITE_10:
3968 case SCSI_WRITE_AND_VERIFY_10:
3969 ataH2BE_U32(aATAPICmd + 2, iATAPILBA);
3970 ataH2BE_U16(aATAPICmd + 7, cReqSectors);
3971 break;
3972 case SCSI_READ_12:
3973 case SCSI_WRITE_12:
3974 ataH2BE_U32(aATAPICmd + 2, iATAPILBA);
3975 ataH2BE_U32(aATAPICmd + 6, cReqSectors);
3976 break;
3977 case SCSI_READ_CD:
3978 ataH2BE_U32(aATAPICmd + 2, iATAPILBA);
3979 ataH2BE_U24(aATAPICmd + 6, cReqSectors);
3980 break;
3981 case SCSI_READ_CD_MSF:
3982 ataLBA2MSF(aATAPICmd + 3, iATAPILBA);
3983 ataLBA2MSF(aATAPICmd + 6, iATAPILBA + cReqSectors);
3984 break;
3985 }
3986 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock,
3987 aATAPICmd,
3988 pAhciReq->enmTxDir == AHCITXDIR_READ
3989 ? PDMBLOCKTXDIR_FROM_DEVICE
3990 : PDMBLOCKTXDIR_TO_DEVICE,
3991 pbBuf,
3992 &cbCurrTX,
3993 abATAPISense,
3994 sizeof(abATAPISense),
3995 30000 /**< @todo timeout */);
3996 if (rc != VINF_SUCCESS)
3997 break;
3998 iATAPILBA += cReqSectors;
3999 pbBuf += pAhciReq->cbATAPISector * cReqSectors;
4000 }
4001 }
4002 else
4003 {
4004 PDMBLOCKTXDIR enmBlockTxDir = PDMBLOCKTXDIR_NONE;
4005
4006 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
4007 enmBlockTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
4008 else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
4009 enmBlockTxDir = PDMBLOCKTXDIR_TO_DEVICE;
4010 else if (pAhciReq->enmTxDir == AHCITXDIR_NONE)
4011 enmBlockTxDir = PDMBLOCKTXDIR_NONE;
4012 else
4013 AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmTxDir));
4014
4015 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock,
4016 pAhciReq->aATAPICmd,
4017 enmBlockTxDir,
4018 pvBuf,
4019 &cbTransfer,
4020 abATAPISense,
4021 sizeof(abATAPISense),
4022 30000 /**< @todo timeout */);
4023 }
4024
4025 /* Update the LEDs and the read/write statistics. */
4026 if (cbTransfer >= 2048)
4027 {
4028 if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
4029 {
4030 pAhciPort->Led.Actual.s.fReading = 0;
4031 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbTransfer);
4032 }
4033 else
4034 {
4035 pAhciPort->Led.Actual.s.fWriting = 0;
4036 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbTransfer);
4037 }
4038 }
4039
4040 if (RT_SUCCESS(rc))
4041 {
4042 /* Do post processing for certain commands. */
4043 switch (pAhciReq->aATAPICmd[0])
4044 {
4045 case SCSI_SEND_CUE_SHEET:
4046 case SCSI_READ_TOC_PMA_ATIP:
4047 {
4048 if (!pAhciPort->pTrackList)
4049 rc = ATAPIPassthroughTrackListCreateEmpty(&pAhciPort->pTrackList);
4050
4051 if (RT_SUCCESS(rc))
4052 rc = ATAPIPassthroughTrackListUpdate(pAhciPort->pTrackList, pAhciReq->aATAPICmd, pvBuf);
4053
4054 if ( RT_FAILURE(rc)
4055 && pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
4056 LogRel(("AHCI: Error (%Rrc) while updating the tracklist during %s, burning the disc might fail\n",
4057 rc, pAhciReq->aATAPICmd[0] == SCSI_SEND_CUE_SHEET ? "SEND CUE SHEET" : "READ TOC/PMA/ATIP"));
4058 break;
4059 }
4060 case SCSI_SYNCHRONIZE_CACHE:
4061 {
4062 ATAPIPassthroughTrackListClear(pAhciPort->pTrackList);
4063 break;
4064 }
4065 }
4066
4067 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
4068 {
4069 Assert(cbTransfer <= pAhciReq->cbTransfer);
4070
4071 if (pAhciReq->aATAPICmd[0] == SCSI_INQUIRY)
4072 {
4073 /* Make sure that the real drive cannot be identified.
4074 * Motivation: changing the VM configuration should be as
4075 * invisible as possible to the guest. */
4076 if (cbTransfer >= 8 + 8)
4077 ataSCSIPadStr((uint8_t *)pvBuf + 8, "VBOX", 8);
4078 if (cbTransfer >= 16 + 16)
4079 ataSCSIPadStr((uint8_t *)pvBuf + 16, "CD-ROM", 16);
4080 if (cbTransfer >= 32 + 4)
4081 ataSCSIPadStr((uint8_t *)pvBuf + 32, "1.0", 4);
4082 }
4083
4084 if (cbTransfer)
4085 {
4086 Log3(("ATAPI PT data read (%d): %.*Rhxs\n", cbTransfer, cbTransfer, (uint8_t *)pvBuf));
4087
4088 /* Reply with the same amount of data as the real drive. */
4089 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf,
4090 cbTransfer);
4091 }
4092 else
4093 *pcbData = 0;
4094 }
4095 else
4096 *pcbData = cbTransfer;
4097 atapiCmdOK(pAhciPort, pAhciReq);
4098 }
4099 else
4100 {
4101 if (pAhciPort->cErrors < MAX_LOG_REL_ERRORS)
4102 {
4103 uint8_t u8Cmd = pAhciReq->aATAPICmd[0];
4104 do
4105 {
4106 /* don't log superfluous errors */
4107 if ( rc == VERR_DEV_IO_ERROR
4108 && ( u8Cmd == SCSI_TEST_UNIT_READY
4109 || u8Cmd == SCSI_READ_CAPACITY
4110 || u8Cmd == SCSI_READ_DVD_STRUCTURE
4111 || u8Cmd == SCSI_READ_TOC_PMA_ATIP))
4112 break;
4113 pAhciPort->cErrors++;
4114 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough cmd=%#04x sense=%d ASC=%#02x ASCQ=%#02x %Rrc\n",
4115 pAhciPort->iLUN, u8Cmd, abATAPISense[2] & 0x0f, abATAPISense[12], abATAPISense[13], rc));
4116 } while (0);
4117 }
4118 atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
4119 }
4120
4121 if (pvBuf)
4122 RTMemFree(pvBuf);
4123
4124 return VINF_SUCCESS;
4125}
4126
4127/** @todo: Revise ASAP. */
4128/* Keep in sync with DevATA.cpp! */
4129static int atapiReadDVDStructureSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
4130{
4131 uint8_t aBuf[25]; /* Counted a maximum of 20 bytes but better be on the safe side. */
4132 uint8_t *buf = aBuf;
4133 int media = pAhciReq->aATAPICmd[1];
4134 int format = pAhciReq->aATAPICmd[7];
4135
4136 uint16_t max_len = ataBE2H_U16(&pAhciReq->aATAPICmd[8]);
4137
4138 memset(buf, 0, max_len);
4139
4140 switch (format) {
4141 case 0x00:
4142 case 0x01:
4143 case 0x02:
4144 case 0x03:
4145 case 0x04:
4146 case 0x05:
4147 case 0x06:
4148 case 0x07:
4149 case 0x08:
4150 case 0x09:
4151 case 0x0a:
4152 case 0x0b:
4153 case 0x0c:
4154 case 0x0d:
4155 case 0x0e:
4156 case 0x0f:
4157 case 0x10:
4158 case 0x11:
4159 case 0x30:
4160 case 0x31:
4161 case 0xff:
4162 if (media == 0)
4163 {
4164 int uASC = SCSI_ASC_NONE;
4165
4166 switch (format)
4167 {
4168 case 0x0: /* Physical format information */
4169 {
4170 int layer = pAhciReq->aATAPICmd[6];
4171 uint64_t total_sectors;
4172
4173 if (layer != 0)
4174 {
4175 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
4176 break;
4177 }
4178
4179 total_sectors = pAhciPort->cTotalSectors;
4180 total_sectors >>= 2;
4181 if (total_sectors == 0)
4182 {
4183 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
4184 break;
4185 }
4186
4187 buf[4] = 1; /* DVD-ROM, part version 1 */
4188 buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
4189 buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */
4190 buf[7] = 0; /* default densities */
4191
4192 /* FIXME: 0x30000 per spec? */
4193 ataH2BE_U32(buf + 8, 0); /* start sector */
4194 ataH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
4195 ataH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
4196
4197 /* Size of buffer, not including 2 byte size field */
4198 ataH2BE_U32(&buf[0], 2048 + 2);
4199
4200 /* 2k data + 4 byte header */
4201 uASC = (2048 + 4);
4202 break;
4203 }
4204 case 0x01: /* DVD copyright information */
4205 buf[4] = 0; /* no copyright data */
4206 buf[5] = 0; /* no region restrictions */
4207
4208 /* Size of buffer, not including 2 byte size field */
4209 ataH2BE_U16(buf, 4 + 2);
4210
4211 /* 4 byte header + 4 byte data */
4212 uASC = (4 + 4);
4213
4214 case 0x03: /* BCA information - invalid field for no BCA info */
4215 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
4216 break;
4217
4218 case 0x04: /* DVD disc manufacturing information */
4219 /* Size of buffer, not including 2 byte size field */
4220 ataH2BE_U16(buf, 2048 + 2);
4221
4222 /* 2k data + 4 byte header */
4223 uASC = (2048 + 4);
4224 break;
4225 case 0xff:
4226 /*
4227 * This lists all the command capabilities above. Add new ones
4228 * in order and update the length and buffer return values.
4229 */
4230
4231 buf[4] = 0x00; /* Physical format */
4232 buf[5] = 0x40; /* Not writable, is readable */
4233 ataH2BE_U16((buf + 6), 2048 + 4);
4234
4235 buf[8] = 0x01; /* Copyright info */
4236 buf[9] = 0x40; /* Not writable, is readable */
4237 ataH2BE_U16((buf + 10), 4 + 4);
4238
4239 buf[12] = 0x03; /* BCA info */
4240 buf[13] = 0x40; /* Not writable, is readable */
4241 ataH2BE_U16((buf + 14), 188 + 4);
4242
4243 buf[16] = 0x04; /* Manufacturing info */
4244 buf[17] = 0x40; /* Not writable, is readable */
4245 ataH2BE_U16((buf + 18), 2048 + 4);
4246
4247 /* Size of buffer, not including 2 byte size field */
4248 ataH2BE_U16(buf, 16 + 2);
4249
4250 /* data written + 4 byte header */
4251 uASC = (16 + 4);
4252 break;
4253 default: /* TODO: formats beyond DVD-ROM requires */
4254 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
4255 }
4256
4257 if (uASC < 0)
4258 {
4259 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, -uASC);
4260 return false;
4261 }
4262 break;
4263 }
4264 /* TODO: BD support, fall through for now */
4265
4266 /* Generic disk structures */
4267 case 0x80: /* TODO: AACS volume identifier */
4268 case 0x81: /* TODO: AACS media serial number */
4269 case 0x82: /* TODO: AACS media identifier */
4270 case 0x83: /* TODO: AACS media key block */
4271 case 0x90: /* TODO: List of recognized format layers */
4272 case 0xc0: /* TODO: Write protection status */
4273 default:
4274 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST,
4275 SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
4276 return false;
4277 }
4278
4279 /* Copy the buffer into the scatter gather list. */
4280 *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
4281 RT_MIN(cbData, max_len));
4282
4283 atapiCmdOK(pAhciPort, pAhciReq);
4284 return false;
4285}
4286
4287static int atapiDoTransfer(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbMax, ATAPIFN iSourceSink)
4288{
4289 size_t cbTransfered = 0;
4290 int rcSourceSink;
4291
4292 rcSourceSink = g_apfnAtapiFuncs[iSourceSink](pAhciReq, pAhciPort, cbMax,
4293 &cbTransfered);
4294
4295 pAhciReq->cmdHdr.u32PRDBC = cbTransfered;
4296 pAhciReq->cbTransfer = cbTransfered;
4297
4298 LogFlow(("cbTransfered=%d\n", cbTransfered));
4299
4300 /* Write updated command header into memory of the guest. */
4301 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
4302
4303 return rcSourceSink;
4304}
4305
4306static int atapiReadSectors2352PostProcess(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc)
4307{
4308 uint8_t *pbBuf = NULL;
4309 uint32_t cSectors = pAhciReq->cbTransfer / 2048;
4310 uint32_t iATAPILBA = pAhciReq->uOffset / 2048;
4311 uint8_t *pbBufDst;
4312 uint8_t *pbBufSrc = (uint8_t *)pAhciReq->u.Io.DataSeg.pvSeg;
4313 size_t cbAlloc = pAhciReq->cbTransfer + cSectors * (1 + 11 + 3 + 1 + 288); /* Per sector data like ECC. */
4314
4315 pbBuf = (uint8_t *)RTMemAlloc(cbAlloc);
4316 if (RT_UNLIKELY(!pbBuf))
4317 return VERR_NO_MEMORY;
4318
4319 pbBufDst = pbBuf;
4320
4321 for (uint32_t i = iATAPILBA; i < iATAPILBA + cSectors; i++)
4322 {
4323 /* sync bytes */
4324 *pbBufDst++ = 0x00;
4325 memset(pbBufDst, 0xff, 11);
4326 pbBufDst += 11;
4327 /* MSF */
4328 ataLBA2MSF(pbBufDst, i);
4329 pbBufDst += 3;
4330 *pbBufDst++ = 0x01; /* mode 1 data */
4331 /* data */
4332 memcpy(pbBufDst, pbBufSrc, 2048);
4333 pbBufDst += 2048;
4334 pbBufSrc += 2048;
4335 /* ECC */
4336 memset(pbBufDst, 0, 288);
4337 pbBufDst += 288;
4338 }
4339
4340 *ppvProc = pbBuf;
4341 *pcbProc = cbAlloc;
4342
4343 return VINF_SUCCESS;
4344}
4345
4346static int atapiReadSectors(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
4347{
4348 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iATAPILBA));
4349
4350 switch (cbSector)
4351 {
4352 case 2048:
4353 pAhciReq->uOffset = (uint64_t)iATAPILBA * cbSector;
4354 pAhciReq->cbTransfer = cSectors * cbSector;
4355 break;
4356 case 2352:
4357 {
4358 pAhciReq->u.Io.pfnPostProcess = atapiReadSectors2352PostProcess;
4359 pAhciReq->uOffset = (uint64_t)iATAPILBA * 2048;
4360 pAhciReq->cbTransfer = cSectors * 2048;
4361 break;
4362 }
4363 default:
4364 AssertMsgFailed(("Unsupported sectors size\n"));
4365 break;
4366 }
4367
4368 return VINF_SUCCESS;
4369}
4370
4371static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
4372{
4373 AHCITXDIR enmTxDir = AHCITXDIR_NONE;
4374 const uint8_t *pbPacket;
4375 uint32_t cbMax;
4376
4377 pbPacket = pAhciReq->aATAPICmd;
4378
4379 ahciLog(("%s: ATAPI CMD=%#04x \"%s\"\n", __FUNCTION__, pbPacket[0], SCSICmdText(pbPacket[0])));
4380
4381 switch (pbPacket[0])
4382 {
4383 case SCSI_TEST_UNIT_READY:
4384 if (pAhciPort->cNotifiedMediaChange > 0)
4385 {
4386 if (pAhciPort->cNotifiedMediaChange-- > 2)
4387 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4388 else
4389 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4390 }
4391 else if (pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4392 atapiCmdOK(pAhciPort, pAhciReq);
4393 else
4394 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4395 break;
4396 case SCSI_GET_EVENT_STATUS_NOTIFICATION:
4397 cbMax = ataBE2H_U16(pbPacket + 7);
4398 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
4399 break;
4400 case SCSI_MODE_SENSE_10:
4401 {
4402 uint8_t uPageControl, uPageCode;
4403 cbMax = ataBE2H_U16(pbPacket + 7);
4404 uPageControl = pbPacket[2] >> 6;
4405 uPageCode = pbPacket[2] & 0x3f;
4406 switch (uPageControl)
4407 {
4408 case SCSI_PAGECONTROL_CURRENT:
4409 switch (uPageCode)
4410 {
4411 case SCSI_MODEPAGE_ERROR_RECOVERY:
4412 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
4413 break;
4414 case SCSI_MODEPAGE_CD_STATUS:
4415 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
4416 break;
4417 default:
4418 goto error_cmd;
4419 }
4420 break;
4421 case SCSI_PAGECONTROL_CHANGEABLE:
4422 goto error_cmd;
4423 case SCSI_PAGECONTROL_DEFAULT:
4424 goto error_cmd;
4425 default:
4426 case SCSI_PAGECONTROL_SAVED:
4427 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
4428 break;
4429 }
4430 break;
4431 }
4432 case SCSI_REQUEST_SENSE:
4433 cbMax = pbPacket[4];
4434 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_REQUEST_SENSE);
4435 break;
4436 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
4437 if (pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4438 {
4439 if (pbPacket[4] & 1)
4440 pAhciPort->pDrvMount->pfnLock(pAhciPort->pDrvMount);
4441 else
4442 pAhciPort->pDrvMount->pfnUnlock(pAhciPort->pDrvMount);
4443 atapiCmdOK(pAhciPort, pAhciReq);
4444 }
4445 else
4446 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4447 break;
4448 case SCSI_READ_10:
4449 case SCSI_READ_12:
4450 {
4451 uint32_t cSectors, iATAPILBA;
4452
4453 if (pAhciPort->cNotifiedMediaChange > 0)
4454 {
4455 pAhciPort->cNotifiedMediaChange-- ;
4456 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4457 break;
4458 }
4459 if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4460 {
4461 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4462 break;
4463 }
4464 if (pbPacket[0] == SCSI_READ_10)
4465 cSectors = ataBE2H_U16(pbPacket + 7);
4466 else
4467 cSectors = ataBE2H_U32(pbPacket + 6);
4468 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4469 if (cSectors == 0)
4470 {
4471 atapiCmdOK(pAhciPort, pAhciReq);
4472 break;
4473 }
4474 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
4475 {
4476 /* Rate limited logging, one log line per second. For
4477 * guests that insist on reading from places outside the
4478 * valid area this often generates too many release log
4479 * entries otherwise. */
4480 static uint64_t s_uLastLogTS = 0;
4481 if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
4482 {
4483 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
4484 s_uLastLogTS = RTTimeMilliTS();
4485 }
4486 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4487 break;
4488 }
4489 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
4490 enmTxDir = AHCITXDIR_READ;
4491 break;
4492 }
4493 case SCSI_READ_CD:
4494 {
4495 uint32_t cSectors, iATAPILBA;
4496
4497 if (pAhciPort->cNotifiedMediaChange > 0)
4498 {
4499 pAhciPort->cNotifiedMediaChange-- ;
4500 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4501 break;
4502 }
4503 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4504 {
4505 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4506 break;
4507 }
4508 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
4509 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4510 if (cSectors == 0)
4511 {
4512 atapiCmdOK(pAhciPort, pAhciReq);
4513 break;
4514 }
4515 if ((uint64_t)iATAPILBA + cSectors > pAhciPort->cTotalSectors)
4516 {
4517 /* Rate limited logging, one log line per second. For
4518 * guests that insist on reading from places outside the
4519 * valid area this often generates too many release log
4520 * entries otherwise. */
4521 static uint64_t s_uLastLogTS = 0;
4522 if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
4523 {
4524 LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA + cSectors));
4525 s_uLastLogTS = RTTimeMilliTS();
4526 }
4527 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4528 break;
4529 }
4530 switch (pbPacket[9] & 0xf8)
4531 {
4532 case 0x00:
4533 /* nothing */
4534 atapiCmdOK(pAhciPort, pAhciReq);
4535 break;
4536 case 0x10:
4537 /* normal read */
4538 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
4539 enmTxDir = AHCITXDIR_READ;
4540 break;
4541 case 0xf8:
4542 /* read all data */
4543 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
4544 enmTxDir = AHCITXDIR_READ;
4545 break;
4546 default:
4547 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN));
4548 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
4549 break;
4550 }
4551 break;
4552 }
4553 case SCSI_SEEK_10:
4554 {
4555 uint32_t iATAPILBA;
4556 if (pAhciPort->cNotifiedMediaChange > 0)
4557 {
4558 pAhciPort->cNotifiedMediaChange-- ;
4559 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4560 break;
4561 }
4562 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4563 {
4564 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4565 break;
4566 }
4567 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4568 if (iATAPILBA > pAhciPort->cTotalSectors)
4569 {
4570 /* Rate limited logging, one log line per second. For
4571 * guests that insist on seeking to places outside the
4572 * valid area this often generates too many release log
4573 * entries otherwise. */
4574 static uint64_t s_uLastLogTS = 0;
4575 if (RTTimeMilliTS() >= s_uLastLogTS + 1000)
4576 {
4577 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", pAhciPort->iLUN, (uint64_t)iATAPILBA));
4578 s_uLastLogTS = RTTimeMilliTS();
4579 }
4580 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
4581 break;
4582 }
4583 atapiCmdOK(pAhciPort, pAhciReq);
4584 pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
4585 break;
4586 }
4587 case SCSI_START_STOP_UNIT:
4588 {
4589 int rc = VINF_SUCCESS;
4590 switch (pbPacket[4] & 3)
4591 {
4592 case 0: /* 00 - Stop motor */
4593 case 1: /* 01 - Start motor */
4594 break;
4595 case 2: /* 10 - Eject media */
4596 {
4597 /* This must be done from EMT. */
4598 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
4599 PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns);
4600
4601 rc = VMR3ReqPriorityCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
4602 (PFNRT)pAhciPort->pDrvMount->pfnUnmount, 3,
4603 pAhciPort->pDrvMount, false/*=fForce*/, true/*=fEject*/);
4604 Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc == VERR_PDM_MEDIA_NOT_MOUNTED);
4605 if (RT_SUCCESS(rc) && pAhci->pMediaNotify)
4606 {
4607 rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
4608 (PFNRT)pAhci->pMediaNotify->pfnEjected, 2,
4609 pAhci->pMediaNotify, pAhciPort->iLUN);
4610 AssertRC(rc);
4611 }
4612 break;
4613 }
4614 case 3: /* 11 - Load media */
4615 /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
4616 break;
4617 }
4618 if (RT_SUCCESS(rc))
4619 atapiCmdOK(pAhciPort, pAhciReq);
4620 else
4621 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
4622 break;
4623 }
4624 case SCSI_MECHANISM_STATUS:
4625 {
4626 cbMax = ataBE2H_U16(pbPacket + 8);
4627 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS);
4628 break;
4629 }
4630 case SCSI_READ_TOC_PMA_ATIP:
4631 {
4632 uint8_t format;
4633
4634 if (pAhciPort->cNotifiedMediaChange > 0)
4635 {
4636 pAhciPort->cNotifiedMediaChange-- ;
4637 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4638 break;
4639 }
4640 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4641 {
4642 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4643 break;
4644 }
4645 cbMax = ataBE2H_U16(pbPacket + 7);
4646 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
4647 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
4648 * the other field is clear... */
4649 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
4650 switch (format)
4651 {
4652 case 0:
4653 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
4654 break;
4655 case 1:
4656 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI);
4657 break;
4658 case 2:
4659 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW);
4660 break;
4661 default:
4662 error_cmd:
4663 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
4664 break;
4665 }
4666 break;
4667 }
4668 case SCSI_READ_CAPACITY:
4669 if (pAhciPort->cNotifiedMediaChange > 0)
4670 {
4671 pAhciPort->cNotifiedMediaChange-- ;
4672 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4673 break;
4674 }
4675 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4676 {
4677 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4678 break;
4679 }
4680 atapiDoTransfer(pAhciPort, pAhciReq, 8 /* cbMax */, ATAFN_SS_ATAPI_READ_CAPACITY);
4681 break;
4682 case SCSI_READ_DISC_INFORMATION:
4683 if (pAhciPort->cNotifiedMediaChange > 0)
4684 {
4685 pAhciPort->cNotifiedMediaChange-- ;
4686 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4687 break;
4688 }
4689 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4690 {
4691 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4692 break;
4693 }
4694 cbMax = ataBE2H_U16(pbPacket + 7);
4695 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_DISC_INFORMATION);
4696 break;
4697 case SCSI_READ_TRACK_INFORMATION:
4698 if (pAhciPort->cNotifiedMediaChange > 0)
4699 {
4700 pAhciPort->cNotifiedMediaChange-- ;
4701 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
4702 break;
4703 }
4704 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
4705 {
4706 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
4707 break;
4708 }
4709 cbMax = ataBE2H_U16(pbPacket + 7);
4710 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION);
4711 break;
4712 case SCSI_GET_CONFIGURATION:
4713 /* No media change stuff here, it can confuse Linux guests. */
4714 cbMax = ataBE2H_U16(pbPacket + 7);
4715 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_CONFIGURATION);
4716 break;
4717 case SCSI_INQUIRY:
4718 cbMax = pbPacket[4];
4719 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_INQUIRY);
4720 break;
4721 case SCSI_READ_DVD_STRUCTURE:
4722 cbMax = ataBE2H_U16(pbPacket + 8);
4723 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_DVD_STRUCTURE);
4724 break;
4725 default:
4726 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
4727 break;
4728 }
4729
4730 return enmTxDir;
4731}
4732
4733/*
4734 * Parse ATAPI commands, passing them directly to the CD/DVD drive.
4735 */
4736static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
4737{
4738 const uint8_t *pbPacket;
4739 uint32_t cSectors, iATAPILBA;
4740 uint32_t cbTransfer = 0;
4741 AHCITXDIR enmTxDir = AHCITXDIR_NONE;
4742
4743 pbPacket = pAhciReq->aATAPICmd;
4744 switch (pbPacket[0])
4745 {
4746 case SCSI_BLANK:
4747 goto sendcmd;
4748 case SCSI_CLOSE_TRACK_SESSION:
4749 goto sendcmd;
4750 case SCSI_ERASE_10:
4751 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4752 cbTransfer = ataBE2H_U16(pbPacket + 7);
4753 Log2(("ATAPI PT: lba %d\n", iATAPILBA));
4754 enmTxDir = AHCITXDIR_WRITE;
4755 goto sendcmd;
4756 case SCSI_FORMAT_UNIT:
4757 cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
4758 enmTxDir = AHCITXDIR_WRITE;
4759 goto sendcmd;
4760 case SCSI_GET_CONFIGURATION:
4761 cbTransfer = ataBE2H_U16(pbPacket + 7);
4762 enmTxDir = AHCITXDIR_READ;
4763 goto sendcmd;
4764 case SCSI_GET_EVENT_STATUS_NOTIFICATION:
4765 cbTransfer = ataBE2H_U16(pbPacket + 7);
4766 if (ASMAtomicReadU32(&pAhciPort->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
4767 {
4768 pAhciReq->cbTransfer = RT_MIN(cbTransfer, 8);
4769 atapiDoTransfer(pAhciPort, pAhciReq, pAhciReq->cbTransfer, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
4770 break;
4771 }
4772 enmTxDir = AHCITXDIR_READ;
4773 goto sendcmd;
4774 case SCSI_GET_PERFORMANCE:
4775 cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
4776 enmTxDir = AHCITXDIR_READ;
4777 goto sendcmd;
4778 case SCSI_INQUIRY:
4779 cbTransfer = ataBE2H_U16(pbPacket + 3);
4780 enmTxDir = AHCITXDIR_READ;
4781 goto sendcmd;
4782 case SCSI_LOAD_UNLOAD_MEDIUM:
4783 goto sendcmd;
4784 case SCSI_MECHANISM_STATUS:
4785 cbTransfer = ataBE2H_U16(pbPacket + 8);
4786 enmTxDir = AHCITXDIR_READ;
4787 goto sendcmd;
4788 case SCSI_MODE_SELECT_10:
4789 cbTransfer = ataBE2H_U16(pbPacket + 7);
4790 enmTxDir = AHCITXDIR_WRITE;
4791 goto sendcmd;
4792 case SCSI_MODE_SENSE_10:
4793 cbTransfer = ataBE2H_U16(pbPacket + 7);
4794 enmTxDir = AHCITXDIR_READ;
4795 goto sendcmd;
4796 case SCSI_PAUSE_RESUME:
4797 goto sendcmd;
4798 case SCSI_PLAY_AUDIO_10:
4799 goto sendcmd;
4800 case SCSI_PLAY_AUDIO_12:
4801 goto sendcmd;
4802 case SCSI_PLAY_AUDIO_MSF:
4803 goto sendcmd;
4804 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
4805 /** @todo do not forget to unlock when a VM is shut down */
4806 goto sendcmd;
4807 case SCSI_READ_10:
4808 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4809 cSectors = ataBE2H_U16(pbPacket + 7);
4810 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
4811 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
4812 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4813 enmTxDir = AHCITXDIR_READ;
4814 goto sendcmd;
4815 case SCSI_READ_12:
4816 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4817 cSectors = ataBE2H_U32(pbPacket + 6);
4818 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
4819 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
4820 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4821 enmTxDir = AHCITXDIR_READ;
4822 goto sendcmd;
4823 case SCSI_READ_BUFFER:
4824 cbTransfer = ataBE2H_U24(pbPacket + 6);
4825 enmTxDir = AHCITXDIR_READ;
4826 goto sendcmd;
4827 case SCSI_READ_BUFFER_CAPACITY:
4828 cbTransfer = ataBE2H_U16(pbPacket + 7);
4829 enmTxDir = AHCITXDIR_READ;
4830 goto sendcmd;
4831 case SCSI_READ_CAPACITY:
4832 cbTransfer = 8;
4833 enmTxDir = AHCITXDIR_READ;
4834 goto sendcmd;
4835 case SCSI_READ_CD:
4836 case SCSI_READ_CD_MSF:
4837 {
4838 /* Get sector size based on the expected sector type field. */
4839 switch ((pbPacket[1] >> 2) & 0x7)
4840 {
4841 case 0x0: /* All types. */
4842 {
4843 uint32_t iLbaStart;
4844
4845 if (pbPacket[0] == SCSI_READ_CD)
4846 iLbaStart = ataBE2H_U32(&pbPacket[2]);
4847 else
4848 iLbaStart = ataMSF2LBA(&pbPacket[3]);
4849
4850 if (pAhciPort->pTrackList)
4851 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iLbaStart);
4852 else
4853 pAhciReq->cbATAPISector = 2048; /* Might be incorrect if we couldn't determine the type. */
4854 break;
4855 }
4856 case 0x1: /* CD-DA */
4857 pAhciReq->cbATAPISector = 2352;
4858 break;
4859 case 0x2: /* Mode 1 */
4860 pAhciReq->cbATAPISector = 2048;
4861 break;
4862 case 0x3: /* Mode 2 formless */
4863 pAhciReq->cbATAPISector = 2336;
4864 break;
4865 case 0x4: /* Mode 2 form 1 */
4866 pAhciReq->cbATAPISector = 2048;
4867 break;
4868 case 0x5: /* Mode 2 form 2 */
4869 pAhciReq->cbATAPISector = 2324;
4870 break;
4871 default: /* Reserved */
4872 AssertMsgFailed(("Unknown sector type\n"));
4873 pAhciReq->cbATAPISector = 0; /** @todo we should probably fail the command here already. */
4874 }
4875
4876 if (pbPacket[0] == SCSI_READ_CD)
4877 cbTransfer = ataBE2H_U24(pbPacket + 6) * pAhciReq->cbATAPISector;
4878 else /* SCSI_READ_MSF */
4879 {
4880 cSectors = ataMSF2LBA(pbPacket + 6) - ataMSF2LBA(pbPacket + 3);
4881 if (cSectors > 32)
4882 cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */
4883 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4884 }
4885 enmTxDir = AHCITXDIR_READ;
4886 goto sendcmd;
4887 }
4888 case SCSI_READ_DISC_INFORMATION:
4889 cbTransfer = ataBE2H_U16(pbPacket + 7);
4890 enmTxDir = AHCITXDIR_READ;
4891 goto sendcmd;
4892 case SCSI_READ_DVD_STRUCTURE:
4893 cbTransfer = ataBE2H_U16(pbPacket + 8);
4894 enmTxDir = AHCITXDIR_READ;
4895 goto sendcmd;
4896 case SCSI_READ_FORMAT_CAPACITIES:
4897 cbTransfer = ataBE2H_U16(pbPacket + 7);
4898 enmTxDir = AHCITXDIR_READ;
4899 goto sendcmd;
4900 case SCSI_READ_SUBCHANNEL:
4901 cbTransfer = ataBE2H_U16(pbPacket + 7);
4902 enmTxDir = AHCITXDIR_READ;
4903 goto sendcmd;
4904 case SCSI_READ_TOC_PMA_ATIP:
4905 cbTransfer = ataBE2H_U16(pbPacket + 7);
4906 enmTxDir = AHCITXDIR_READ;
4907 goto sendcmd;
4908 case SCSI_READ_TRACK_INFORMATION:
4909 cbTransfer = ataBE2H_U16(pbPacket + 7);
4910 enmTxDir = AHCITXDIR_READ;
4911 goto sendcmd;
4912 case SCSI_REPAIR_TRACK:
4913 goto sendcmd;
4914 case SCSI_REPORT_KEY:
4915 cbTransfer = ataBE2H_U16(pbPacket + 8);
4916 enmTxDir = AHCITXDIR_READ;
4917 goto sendcmd;
4918 case SCSI_REQUEST_SENSE:
4919 cbTransfer = pbPacket[4];
4920 if ((pAhciPort->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
4921 {
4922 pAhciReq->cbTransfer = cbTransfer;
4923 pAhciReq->enmTxDir = AHCITXDIR_READ;
4924 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_REQUEST_SENSE);
4925 break;
4926 }
4927 enmTxDir = AHCITXDIR_READ;
4928 goto sendcmd;
4929 case SCSI_RESERVE_TRACK:
4930 goto sendcmd;
4931 case SCSI_SCAN:
4932 goto sendcmd;
4933 case SCSI_SEEK_10:
4934 goto sendcmd;
4935 case SCSI_SEND_CUE_SHEET:
4936 cbTransfer = ataBE2H_U24(pbPacket + 6);
4937 enmTxDir = AHCITXDIR_WRITE;
4938 goto sendcmd;
4939 case SCSI_SEND_DVD_STRUCTURE:
4940 cbTransfer = ataBE2H_U16(pbPacket + 8);
4941 enmTxDir = AHCITXDIR_WRITE;
4942 goto sendcmd;
4943 case SCSI_SEND_EVENT:
4944 cbTransfer = ataBE2H_U16(pbPacket + 8);
4945 enmTxDir = AHCITXDIR_WRITE;
4946 goto sendcmd;
4947 case SCSI_SEND_KEY:
4948 cbTransfer = ataBE2H_U16(pbPacket + 8);
4949 enmTxDir = AHCITXDIR_WRITE;
4950 goto sendcmd;
4951 case SCSI_SEND_OPC_INFORMATION:
4952 cbTransfer = ataBE2H_U16(pbPacket + 7);
4953 enmTxDir = AHCITXDIR_WRITE;
4954 goto sendcmd;
4955 case SCSI_SET_CD_SPEED:
4956 goto sendcmd;
4957 case SCSI_SET_READ_AHEAD:
4958 goto sendcmd;
4959 case SCSI_SET_STREAMING:
4960 cbTransfer = ataBE2H_U16(pbPacket + 9);
4961 enmTxDir = AHCITXDIR_WRITE;
4962 goto sendcmd;
4963 case SCSI_START_STOP_UNIT:
4964 goto sendcmd;
4965 case SCSI_STOP_PLAY_SCAN:
4966 goto sendcmd;
4967 case SCSI_SYNCHRONIZE_CACHE:
4968 goto sendcmd;
4969 case SCSI_TEST_UNIT_READY:
4970 goto sendcmd;
4971 case SCSI_VERIFY_10:
4972 goto sendcmd;
4973 case SCSI_WRITE_10:
4974 case SCSI_WRITE_AND_VERIFY_10:
4975 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4976 cSectors = ataBE2H_U16(pbPacket + 7);
4977 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
4978 if (pAhciPort->pTrackList)
4979 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iATAPILBA);
4980 else
4981 pAhciReq->cbATAPISector = 2048;
4982 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4983 enmTxDir = AHCITXDIR_WRITE;
4984 goto sendcmd;
4985 case SCSI_WRITE_12:
4986 iATAPILBA = ataBE2H_U32(pbPacket + 2);
4987 cSectors = ataBE2H_U32(pbPacket + 6);
4988 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
4989 if (pAhciPort->pTrackList)
4990 pAhciReq->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(pAhciPort->pTrackList, iATAPILBA);
4991 else
4992 pAhciReq->cbATAPISector = 2048;
4993 cbTransfer = cSectors * pAhciReq->cbATAPISector;
4994 enmTxDir = AHCITXDIR_WRITE;
4995 goto sendcmd;
4996 case SCSI_WRITE_BUFFER:
4997 switch (pbPacket[1] & 0x1f)
4998 {
4999 case 0x04: /* download microcode */
5000 case 0x05: /* download microcode and save */
5001 case 0x06: /* download microcode with offsets */
5002 case 0x07: /* download microcode with offsets and save */
5003 case 0x0e: /* download microcode with offsets and defer activation */
5004 case 0x0f: /* activate deferred microcode */
5005 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", pAhciPort->iLUN));
5006 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
5007 break;
5008 default:
5009 cbTransfer = ataBE2H_U16(pbPacket + 6);
5010 enmTxDir = AHCITXDIR_WRITE;
5011 goto sendcmd;
5012 }
5013 break;
5014 case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */
5015 cbTransfer = ataBE2H_U32(pbPacket + 6);
5016 enmTxDir = AHCITXDIR_READ;
5017 goto sendcmd;
5018 case SCSI_REZERO_UNIT:
5019 /* Obsolete command used by cdrecord. What else would one expect?
5020 * This command is not sent to the drive, it is handled internally,
5021 * as the Linux kernel doesn't like it (message "scsi: unknown
5022 * opcode 0x01" in syslog) and replies with a sense code of 0,
5023 * which sends cdrecord to an endless loop. */
5024 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
5025 break;
5026 default:
5027 LogRel(("AHCI: LUN#%d: passthrough unimplemented for command %#x\n", pAhciPort->iLUN, pbPacket[0]));
5028 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
5029 break;
5030 sendcmd:
5031 /* Send a command to the drive, passing data in/out as required. */
5032 Log2(("ATAPI PT: max size %d\n", cbTransfer));
5033 if (cbTransfer == 0)
5034 enmTxDir = AHCITXDIR_NONE;
5035 pAhciReq->enmTxDir = enmTxDir;
5036 pAhciReq->cbTransfer = cbTransfer;
5037 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_PASSTHROUGH);
5038 }
5039
5040 return AHCITXDIR_NONE;
5041}
5042
5043static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5044{
5045 AHCITXDIR enmTxDir = AHCITXDIR_NONE;
5046 const uint8_t *pbPacket;
5047
5048 pbPacket = pAhciReq->aATAPICmd;
5049 Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0], SCSICmdText(pbPacket[0])));
5050 Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8), ATAPI_PACKET_SIZE, pbPacket));
5051
5052 if (pAhciPort->fATAPIPassthrough)
5053 enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciReq);
5054 else
5055 enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq);
5056
5057 return enmTxDir;
5058}
5059
5060/**
5061 * Reset all values after a reset of the attached storage device.
5062 *
5063 * @returns nothing
5064 * @param pAhciPort The port the device is attached to.
5065 * @param pAhciReq The state to get the tag number from.
5066 */
5067static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5068{
5069 int rc;
5070
5071 /* Send a status good D2H FIS. */
5072 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED);
5073 pAhciPort->fResetDevice = false;
5074 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5075 ahciPostFirstD2HFisIntoMemory(pAhciPort);
5076
5077 /* As this is the first D2H FIS after the reset update the signature in the SIG register of the port. */
5078 if (pAhciPort->fATAPI)
5079 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
5080 else
5081 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
5082 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
5083
5084 rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
5085 AssertRC(rc);
5086}
5087
5088/**
5089 * Initiates a device reset caused by ATA_DEVICE_RESET (ATAPI only).
5090 *
5091 * @returns nothing.
5092 * @param pAhciPort The device to reset.
5093 * @param pAhciReq The task state.
5094 */
5095static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5096{
5097 ASMAtomicWriteBool(&pAhciPort->fResetDevice, true);
5098
5099 /*
5100 * Because this ATAPI only and ATAPI can't have
5101 * more than one command active at a time the task counter should be 0
5102 * and it is possible to finish the reset now.
5103 */
5104 Assert(ASMAtomicReadU32(&pAhciPort->cTasksActive) == 0);
5105 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
5106}
5107
5108/**
5109 * Create a PIO setup FIS and post it into the memory area of the guest.
5110 *
5111 * @returns nothing.
5112 * @param pAhciPort The port of the SATA controller.
5113 * @param pAhciReq The state of the task.
5114 * @param pCmdFis Pointer to the command FIS from the guest.
5115 * @param fInterrupt If an interrupt should be send to the guest.
5116 */
5117static void ahciSendPioSetupFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis,
5118 bool fInterrupt)
5119{
5120 uint8_t abPioSetupFis[20];
5121 bool fAssertIntr = false;
5122 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
5123
5124 ahciLog(("%s: building PIO setup Fis\n", __FUNCTION__));
5125
5126 AssertMsg( pAhciReq->cbTransfer > 0
5127 && pAhciReq->cbTransfer <= 65534,
5128 ("Can't send PIO setup FIS for requests with 0 bytes to transfer or greater than 65534\n"));
5129
5130 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5131 {
5132 memset(&abPioSetupFis[0], 0, sizeof(abPioSetupFis));
5133 abPioSetupFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_PIOSETUP;
5134 abPioSetupFis[AHCI_CMDFIS_BITS] = (fInterrupt ? AHCI_CMDFIS_I : 0);
5135 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
5136 abPioSetupFis[AHCI_CMDFIS_BITS] |= AHCI_CMDFIS_D;
5137 abPioSetupFis[AHCI_CMDFIS_STS] = pAhciReq->uATARegStatus;
5138 abPioSetupFis[AHCI_CMDFIS_ERR] = pAhciReq->uATARegError;
5139 abPioSetupFis[AHCI_CMDFIS_SECTN] = pCmdFis[AHCI_CMDFIS_SECTN];
5140 abPioSetupFis[AHCI_CMDFIS_CYLL] = pCmdFis[AHCI_CMDFIS_CYLL];
5141 abPioSetupFis[AHCI_CMDFIS_CYLH] = pCmdFis[AHCI_CMDFIS_CYLH];
5142 abPioSetupFis[AHCI_CMDFIS_HEAD] = pCmdFis[AHCI_CMDFIS_HEAD];
5143 abPioSetupFis[AHCI_CMDFIS_SECTNEXP] = pCmdFis[AHCI_CMDFIS_SECTNEXP];
5144 abPioSetupFis[AHCI_CMDFIS_CYLLEXP] = pCmdFis[AHCI_CMDFIS_CYLLEXP];
5145 abPioSetupFis[AHCI_CMDFIS_CYLHEXP] = pCmdFis[AHCI_CMDFIS_CYLHEXP];
5146 abPioSetupFis[AHCI_CMDFIS_SECTC] = pCmdFis[AHCI_CMDFIS_SECTC];
5147 abPioSetupFis[AHCI_CMDFIS_SECTCEXP] = pCmdFis[AHCI_CMDFIS_SECTCEXP];
5148
5149 /* Set transfer count. */
5150 abPioSetupFis[16] = (pAhciReq->cbTransfer >> 8) & 0xff;
5151 abPioSetupFis[17] = pAhciReq->cbTransfer & 0xff;
5152
5153 /* Update registers. */
5154 pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus;
5155
5156 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_PIOSETUP, abPioSetupFis);
5157
5158 if (fInterrupt)
5159 {
5160 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_PSS);
5161 /* Check if we should assert an interrupt */
5162 if (pAhciPort->regIE & AHCI_PORT_IE_PSE)
5163 fAssertIntr = true;
5164 }
5165
5166 if (fAssertIntr)
5167 {
5168 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
5169 AssertRC(rc);
5170 }
5171 }
5172}
5173
5174/**
5175 * Build a D2H FIS and post into the memory area of the guest.
5176 *
5177 * @returns Nothing
5178 * @param pAhciPort The port of the SATA controller.
5179 * @param pAhciReq The state of the task.
5180 * @param pCmdFis Pointer to the command FIS from the guest.
5181 * @param fInterrupt If an interrupt should be send to the guest.
5182 */
5183static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis, bool fInterrupt)
5184{
5185 uint8_t d2hFis[20];
5186 bool fAssertIntr = false;
5187 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
5188
5189 ahciLog(("%s: building D2H Fis\n", __FUNCTION__));
5190
5191 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5192 {
5193 memset(&d2hFis[0], 0, sizeof(d2hFis));
5194 d2hFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_D2H;
5195 d2hFis[AHCI_CMDFIS_BITS] = (fInterrupt ? AHCI_CMDFIS_I : 0);
5196 d2hFis[AHCI_CMDFIS_STS] = pAhciReq->uATARegStatus;
5197 d2hFis[AHCI_CMDFIS_ERR] = pAhciReq->uATARegError;
5198 d2hFis[AHCI_CMDFIS_SECTN] = pCmdFis[AHCI_CMDFIS_SECTN];
5199 d2hFis[AHCI_CMDFIS_CYLL] = pCmdFis[AHCI_CMDFIS_CYLL];
5200 d2hFis[AHCI_CMDFIS_CYLH] = pCmdFis[AHCI_CMDFIS_CYLH];
5201 d2hFis[AHCI_CMDFIS_HEAD] = pCmdFis[AHCI_CMDFIS_HEAD];
5202 d2hFis[AHCI_CMDFIS_SECTNEXP] = pCmdFis[AHCI_CMDFIS_SECTNEXP];
5203 d2hFis[AHCI_CMDFIS_CYLLEXP] = pCmdFis[AHCI_CMDFIS_CYLLEXP];
5204 d2hFis[AHCI_CMDFIS_CYLHEXP] = pCmdFis[AHCI_CMDFIS_CYLHEXP];
5205 d2hFis[AHCI_CMDFIS_SECTC] = pCmdFis[AHCI_CMDFIS_SECTC];
5206 d2hFis[AHCI_CMDFIS_SECTCEXP] = pCmdFis[AHCI_CMDFIS_SECTCEXP];
5207
5208 /* Update registers. */
5209 pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus;
5210
5211 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis);
5212
5213 if (pAhciReq->uATARegStatus & ATA_STAT_ERR)
5214 {
5215 /* Error bit is set. */
5216 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
5217 if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
5218 fAssertIntr = true;
5219 /*
5220 * Don't mark the command slot as completed because the guest
5221 * needs it to identify the failed command.
5222 */
5223 }
5224 else if (fInterrupt)
5225 {
5226 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_DHRS);
5227 /* Check if we should assert an interrupt */
5228 if (pAhciPort->regIE & AHCI_PORT_IE_DHRE)
5229 fAssertIntr = true;
5230
5231 /* Mark command as completed. */
5232 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
5233 }
5234
5235 if (fAssertIntr)
5236 {
5237 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
5238 AssertRC(rc);
5239 }
5240 }
5241}
5242
5243/**
5244 * Build a SDB Fis and post it into the memory area of the guest.
5245 *
5246 * @returns Nothing
5247 * @param pAhciPort The port for which the SDB Fis is send.
5248 * @param uFinishedTasks Bitmask of finished tasks.
5249 * @param fInterrupt If an interrupt should be asserted.
5250 */
5251static void ahciSendSDBFis(PAHCIPort pAhciPort, uint32_t uFinishedTasks, bool fInterrupt)
5252{
5253 uint32_t sdbFis[2];
5254 bool fAssertIntr = false;
5255 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
5256 PAHCIREQ pTaskErr = ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ);
5257
5258 ahciLog(("%s: Building SDB FIS\n", __FUNCTION__));
5259
5260 if (pAhciPort->regCMD & AHCI_PORT_CMD_FRE)
5261 {
5262 memset(&sdbFis[0], 0, sizeof(sdbFis));
5263 sdbFis[0] = AHCI_CMDFIS_TYPE_SETDEVBITS;
5264 sdbFis[0] |= (fInterrupt ? (1 << 14) : 0);
5265 if (RT_UNLIKELY(pTaskErr))
5266 {
5267 sdbFis[0] = pTaskErr->uATARegError;
5268 sdbFis[0] |= (pTaskErr->uATARegStatus & 0x77) << 16; /* Some bits are marked as reserved and thus are masked out. */
5269
5270 /* Update registers. */
5271 pAhciPort->regTFD = (pTaskErr->uATARegError << 8) | pTaskErr->uATARegStatus;
5272 }
5273 else
5274 {
5275 sdbFis[0] = 0;
5276 sdbFis[0] |= (ATA_STAT_READY | ATA_STAT_SEEK) << 16;
5277 pAhciPort->regTFD = ATA_STAT_READY | ATA_STAT_SEEK;
5278 }
5279
5280 sdbFis[1] = pAhciPort->u32QueuedTasksFinished | uFinishedTasks;
5281
5282 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_SETDEVBITS, (uint8_t *)sdbFis);
5283
5284 if (RT_UNLIKELY(pTaskErr))
5285 {
5286 /* Error bit is set. */
5287 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_TFES);
5288 if (pAhciPort->regIE & AHCI_PORT_IE_TFEE)
5289 fAssertIntr = true;
5290 }
5291
5292 if (fInterrupt)
5293 {
5294 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_SDBS);
5295 /* Check if we should assert an interrupt */
5296 if (pAhciPort->regIE & AHCI_PORT_IE_SDBE)
5297 fAssertIntr = true;
5298 }
5299
5300 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, uFinishedTasks);
5301
5302 if (fAssertIntr)
5303 {
5304 int rc = ahciHbaSetInterrupt(pAhci, pAhciPort->iLUN, VERR_IGNORED);
5305 AssertRC(rc);
5306 }
5307 }
5308}
5309
5310static uint32_t ahciGetNSectors(uint8_t *pCmdFis, bool fLBA48)
5311{
5312 /* 0 means either 256 (LBA28) or 65536 (LBA48) sectors. */
5313 if (fLBA48)
5314 {
5315 if (!pCmdFis[AHCI_CMDFIS_SECTC] && !pCmdFis[AHCI_CMDFIS_SECTCEXP])
5316 return 65536;
5317 else
5318 return pCmdFis[AHCI_CMDFIS_SECTCEXP] << 8 | pCmdFis[AHCI_CMDFIS_SECTC];
5319 }
5320 else
5321 {
5322 if (!pCmdFis[AHCI_CMDFIS_SECTC])
5323 return 256;
5324 else
5325 return pCmdFis[AHCI_CMDFIS_SECTC];
5326 }
5327}
5328
5329static uint64_t ahciGetSector(PAHCIPort pAhciPort, uint8_t *pCmdFis, bool fLBA48)
5330{
5331 uint64_t iLBA;
5332 if (pCmdFis[AHCI_CMDFIS_HEAD] & 0x40)
5333 {
5334 /* any LBA variant */
5335 if (fLBA48)
5336 {
5337 /* LBA48 */
5338 iLBA = ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLHEXP] << 40) |
5339 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLLEXP] << 32) |
5340 ((uint64_t)pCmdFis[AHCI_CMDFIS_SECTNEXP] << 24) |
5341 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLH] << 16) |
5342 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLL] << 8) |
5343 pCmdFis[AHCI_CMDFIS_SECTN];
5344 }
5345 else
5346 {
5347 /* LBA */
5348 iLBA = ((pCmdFis[AHCI_CMDFIS_HEAD] & 0x0f) << 24) | (pCmdFis[AHCI_CMDFIS_CYLH] << 16) |
5349 (pCmdFis[AHCI_CMDFIS_CYLL] << 8) | pCmdFis[AHCI_CMDFIS_SECTN];
5350 }
5351 }
5352 else
5353 {
5354 /* CHS */
5355 iLBA = ((pCmdFis[AHCI_CMDFIS_CYLH] << 8) | pCmdFis[AHCI_CMDFIS_CYLL]) * pAhciPort->PCHSGeometry.cHeads * pAhciPort->PCHSGeometry.cSectors +
5356 (pCmdFis[AHCI_CMDFIS_HEAD] & 0x0f) * pAhciPort->PCHSGeometry.cSectors +
5357 (pCmdFis[AHCI_CMDFIS_SECTN] - 1);
5358 }
5359 return iLBA;
5360}
5361
5362static uint64_t ahciGetSectorQueued(uint8_t *pCmdFis)
5363{
5364 uint64_t uLBA;
5365
5366 uLBA = ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLHEXP] << 40) |
5367 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLLEXP] << 32) |
5368 ((uint64_t)pCmdFis[AHCI_CMDFIS_SECTNEXP] << 24) |
5369 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLH] << 16) |
5370 ((uint64_t)pCmdFis[AHCI_CMDFIS_CYLL] << 8) |
5371 pCmdFis[AHCI_CMDFIS_SECTN];
5372
5373 return uLBA;
5374}
5375
5376DECLINLINE(uint32_t) ahciGetNSectorsQueued(uint8_t *pCmdFis)
5377{
5378 if (!pCmdFis[AHCI_CMDFIS_FETEXP] && !pCmdFis[AHCI_CMDFIS_FET])
5379 return 65536;
5380 else
5381 return pCmdFis[AHCI_CMDFIS_FETEXP] << 8 | pCmdFis[AHCI_CMDFIS_FET];
5382}
5383
5384DECLINLINE(uint8_t) ahciGetTagQueued(uint8_t *pCmdFis)
5385{
5386 return pCmdFis[AHCI_CMDFIS_SECTC] >> 3;
5387}
5388
5389/**
5390 * Allocates memory for the given request using already allocated memory if possible.
5391 *
5392 * @returns Pointer to the memory or NULL on failure
5393 * @param pAhciReq The request to allocate memory for.
5394 * @param cb The amount of memory to allocate.
5395 */
5396static void *ahciReqMemAlloc(PAHCIREQ pAhciReq, size_t cb)
5397{
5398 if (pAhciReq->cbAlloc > cb)
5399 {
5400 pAhciReq->cAllocTooMuch++;
5401 }
5402 else if (pAhciReq->cbAlloc < cb)
5403 {
5404 if (pAhciReq->cbAlloc)
5405 RTMemPageFree(pAhciReq->pvAlloc, pAhciReq->cbAlloc);
5406
5407 pAhciReq->cbAlloc = RT_ALIGN_Z(cb, _4K);
5408 pAhciReq->pvAlloc = RTMemPageAlloc(pAhciReq->cbAlloc);
5409 pAhciReq->cAllocTooMuch = 0;
5410 if (RT_UNLIKELY(!pAhciReq->pvAlloc))
5411 pAhciReq->cbAlloc = 0;
5412 }
5413
5414 return pAhciReq->pvAlloc;
5415}
5416
5417/**
5418 * Frees memory allocated for the given request.
5419 *
5420 * @returns nothing.
5421 * @param pAhciReq The request.
5422 */
5423static void ahciReqMemFree(PAHCIREQ pAhciReq)
5424{
5425 if (pAhciReq->cAllocTooMuch >= AHCI_MAX_ALLOC_TOO_MUCH)
5426 {
5427 RTMemPageFree(pAhciReq->pvAlloc, pAhciReq->cbAlloc);
5428 pAhciReq->cbAlloc = 0;
5429 pAhciReq->cAllocTooMuch = 0;
5430 }
5431}
5432
5433/**
5434 * Copies a data buffer into the S/G buffer set up by the guest.
5435 *
5436 * @returns Amount of bytes copied to the PRDTL.
5437 * @param pDevIns Pointer to the device instance data.
5438 * @param pAhciReq AHCI request structure.
5439 * @param pvBuf The buffer to copy from.
5440 * @param cbBuf The size of the buffer.
5441 */
5442static size_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
5443 void *pvBuf, size_t cbBuf)
5444{
5445 uint8_t *pbBuf = (uint8_t *)pvBuf;
5446 SGLEntry aPrdtlEntries[32];
5447 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
5448 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
5449 size_t cbCopied = 0;
5450
5451 AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
5452
5453 do
5454 {
5455 uint32_t cPrdtlEntriesRead = cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries)
5456 ? cPrdtlEntries
5457 : RT_ELEMENTS(aPrdtlEntries);
5458
5459 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
5460
5461 for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++)
5462 {
5463 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
5464 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
5465
5466 cbThisCopy = RT_MIN(cbThisCopy, cbBuf);
5467
5468 /* Copy into SG entry. */
5469 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy);
5470
5471 pbBuf += cbThisCopy;
5472 cbBuf -= cbThisCopy;
5473 cbCopied += cbThisCopy;
5474 }
5475
5476 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry);
5477 cPrdtlEntries -= cPrdtlEntriesRead;
5478 } while (cPrdtlEntries && cbBuf);
5479
5480 if (cbCopied < cbBuf)
5481 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
5482
5483 return cbCopied;
5484}
5485
5486/**
5487 * Copies the S/G buffer into a data buffer.
5488 *
5489 * @returns Amount of bytes copied to the PRDTL.
5490 * @param pDevIns Pointer to the device instance data.
5491 * @param pAhciReq AHCI request structure.
5492 * @param pvBuf The buffer to copy to.
5493 * @param cbBuf The size of the buffer.
5494 */
5495static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
5496 void *pvBuf, size_t cbBuf)
5497{
5498 uint8_t *pbBuf = (uint8_t *)pvBuf;
5499 SGLEntry aPrdtlEntries[32];
5500 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
5501 unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
5502 size_t cbCopied = 0;
5503
5504 AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
5505
5506 do
5507 {
5508 uint32_t cPrdtlEntriesRead = (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
5509 ? cPrdtlEntries
5510 : RT_ELEMENTS(aPrdtlEntries);
5511
5512 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
5513
5514 for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++)
5515 {
5516 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
5517 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
5518
5519 cbThisCopy = RT_MIN(cbThisCopy, cbBuf);
5520
5521 /* Copy into buffer. */
5522 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy);
5523
5524 pbBuf += cbThisCopy;
5525 cbBuf -= cbThisCopy;
5526 cbCopied += cbThisCopy;
5527 }
5528
5529 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry);
5530 cPrdtlEntries -= cPrdtlEntriesRead;
5531 } while (cPrdtlEntries && cbBuf);
5532
5533 if (cbCopied < cbBuf)
5534 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
5535
5536 return cbCopied;
5537}
5538
5539/**
5540 * Allocate I/O memory and copies the guest buffer for writes.
5541 *
5542 * @returns VBox status code.
5543 * @param pDevIns The device instance.
5544 * @param pAhciReq The request state.
5545 * @param cbTransfer Amount of bytes to allocate.
5546 */
5547static int ahciIoBufAllocate(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, size_t cbTransfer)
5548{
5549 AssertMsg( pAhciReq->enmTxDir == AHCITXDIR_READ
5550 || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
5551 ("Allocating I/O memory for a non I/O request is not allowed\n"));
5552
5553 pAhciReq->u.Io.DataSeg.pvSeg = ahciReqMemAlloc(pAhciReq, cbTransfer);
5554 if (!pAhciReq->u.Io.DataSeg.pvSeg)
5555 return VERR_NO_MEMORY;
5556
5557 pAhciReq->u.Io.DataSeg.cbSeg = cbTransfer;
5558 if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
5559 {
5560 ahciCopyFromPrdtl(pDevIns, pAhciReq,
5561 pAhciReq->u.Io.DataSeg.pvSeg,
5562 cbTransfer);
5563 }
5564 return VINF_SUCCESS;
5565}
5566
5567/**
5568 * Frees the I/O memory of the given request and updates the guest buffer if necessary.
5569 *
5570 * @returns nothing.
5571 * @param pDevIns The device instance.
5572 * @param pAhciReq The request state.
5573 * @param fCopyToGuest Flag whether to update the guest buffer if necessary.
5574 * Nothing is copied if false even if the request was a read.
5575 */
5576static void ahciIoBufFree(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
5577 bool fCopyToGuest)
5578{
5579 AssertMsg( pAhciReq->enmTxDir == AHCITXDIR_READ
5580 || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
5581 ("Freeing I/O memory for a non I/O request is not allowed\n"));
5582
5583 if ( pAhciReq->enmTxDir == AHCITXDIR_READ
5584 && fCopyToGuest)
5585 {
5586 if (pAhciReq->u.Io.pfnPostProcess)
5587 {
5588 void *pv = NULL;
5589 size_t cb = 0;
5590 int rc = pAhciReq->u.Io.pfnPostProcess(pAhciReq, &pv, &cb);
5591
5592 if (RT_SUCCESS(rc))
5593 {
5594 pAhciReq->cbTransfer = ahciCopyToPrdtl(pDevIns, pAhciReq, pv, cb);
5595 RTMemFree(pv);
5596 }
5597 }
5598 else
5599 ahciCopyToPrdtl(pDevIns, pAhciReq,
5600 pAhciReq->u.Io.DataSeg.pvSeg,
5601 pAhciReq->u.Io.DataSeg.cbSeg);
5602 }
5603
5604 ahciReqMemFree(pAhciReq);
5605 pAhciReq->u.Io.DataSeg.pvSeg = NULL;
5606 pAhciReq->u.Io.DataSeg.cbSeg = 0;
5607}
5608
5609
5610/**
5611 * Cancels all active tasks on the port.
5612 *
5613 * @returns Whether all active tasks were canceled.
5614 * @param pAhciPort The ahci port.
5615 */
5616static bool ahciCancelActiveTasks(PAHCIPort pAhciPort)
5617{
5618 for (unsigned i = 0; i < RT_ELEMENTS(pAhciPort->aCachedTasks); i++)
5619 {
5620 PAHCIREQ pAhciReq = pAhciPort->aCachedTasks[i];
5621
5622 if (VALID_PTR(pAhciReq))
5623 {
5624 bool fXchg = false;
5625 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE, fXchg);
5626
5627 if (fXchg)
5628 {
5629 /* Task is active and was canceled. */
5630 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0,
5631 ("Task was canceled but none is active\n"));
5632 ASMAtomicDecU32(&pAhciPort->cTasksActive);
5633
5634 /*
5635 * Clear the pointer in the cached array. The controller will allocate a
5636 * a new task structure for this tag.
5637 */
5638 ASMAtomicWriteNullPtr(&pAhciPort->aCachedTasks[i]);
5639 LogRel(("AHCI#%uP%u: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance,
5640 pAhciPort->iLUN, pAhciReq->uTag));
5641 }
5642 else
5643 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE,
5644 ("Invalid task state, must be free!\n"));
5645 }
5646 }
5647
5648 AssertRelease(!ASMAtomicReadU32(&pAhciPort->cTasksActive));
5649 return true; /* always true for now because tasks don't use guest memory as the buffer which makes canceling a task impossible. */
5650}
5651
5652/* -=-=-=-=- IBlockAsyncPort -=-=-=-=- */
5653
5654/** Makes a PAHCIPort out of a PPDMIBLOCKASYNCPORT. */
5655#define PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface) ( (PAHCIPort)((uintptr_t)pInterface - RT_OFFSETOF(AHCIPort, IPortAsync)) )
5656
5657static void ahciWarningDiskFull(PPDMDEVINS pDevIns)
5658{
5659 int rc;
5660 LogRel(("AHCI: Host disk full\n"));
5661 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevAHCI_DISKFULL",
5662 N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
5663 AssertRC(rc);
5664}
5665
5666static void ahciWarningFileTooBig(PPDMDEVINS pDevIns)
5667{
5668 int rc;
5669 LogRel(("AHCI: File too big\n"));
5670 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevAHCI_FILETOOBIG",
5671 N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files"));
5672 AssertRC(rc);
5673}
5674
5675static void ahciWarningISCSI(PPDMDEVINS pDevIns)
5676{
5677 int rc;
5678 LogRel(("AHCI: iSCSI target unavailable\n"));
5679 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevAHCI_ISCSIDOWN",
5680 N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
5681 AssertRC(rc);
5682}
5683
5684bool ahciIsRedoSetWarning(PAHCIPort pAhciPort, int rc)
5685{
5686 if (rc == VERR_DISK_FULL)
5687 {
5688 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))
5689 ahciWarningDiskFull(pAhciPort->CTX_SUFF(pDevIns));
5690 return true;
5691 }
5692 if (rc == VERR_FILE_TOO_BIG)
5693 {
5694 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))
5695 ahciWarningFileTooBig(pAhciPort->CTX_SUFF(pDevIns));
5696 return true;
5697 }
5698 if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
5699 {
5700 /* iSCSI connection abort (first error) or failure to reestablish
5701 * connection (second error). Pause VM. On resume we'll retry. */
5702 if (ASMAtomicCmpXchgBool(&pAhciPort->fRedo, true, false))
5703 ahciWarningISCSI(pAhciPort->CTX_SUFF(pDevIns));
5704 return true;
5705 }
5706 return false;
5707}
5708
5709/**
5710 * Creates the array of ranges to trim.
5711 *
5712 * @returns VBox status code.
5713 * @param pAhciPort AHCI port state.
5714 * @param pAhciReq The request handling the TRIM request.
5715 */
5716static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
5717{
5718 SGLEntry aPrdtlEntries[32];
5719 uint64_t aRanges[64];
5720 unsigned cRangesMax;
5721 unsigned cRanges = 0;
5722 uint32_t cPrdtlEntries = pAhciReq->cPrdtlEntries;
5723 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
5724 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
5725 int rc = VINF_SUCCESS;
5726
5727 LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq));
5728
5729 AssertMsgReturn(pAhciReq->enmTxDir == AHCITXDIR_TRIM, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);
5730
5731 /* The data buffer contains LBA range entries. Each range is 8 bytes big. */
5732 if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP])
5733 cRangesMax = 65536 * 512 / 8;
5734 else
5735 cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8;
5736
5737 if (!cPrdtlEntries)
5738 {
5739 pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
5740 return VINF_SUCCESS;
5741 }
5742
5743 do
5744 {
5745 uint32_t cPrdtlEntriesRead = (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
5746 ? cPrdtlEntries
5747 : RT_ELEMENTS(aPrdtlEntries);
5748
5749 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
5750
5751 for (uint32_t i = 0; i < cPrdtlEntriesRead; i++)
5752 {
5753 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
5754 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
5755
5756 cbThisCopy = RT_MIN(cbThisCopy, sizeof(aRanges));
5757
5758 /* Copy into buffer. */
5759 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy);
5760
5761 for (unsigned idxRange = 0; idxRange < RT_ELEMENTS(aRanges); idxRange++)
5762 {
5763 aRanges[idxRange] = RT_H2LE_U64(aRanges[idxRange]);
5764 if (AHCI_RANGE_LENGTH_GET(aRanges[idxRange]) != 0)
5765 cRanges++;
5766 else
5767 break;
5768 }
5769 }
5770
5771 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry);
5772 cPrdtlEntries -= cPrdtlEntriesRead;
5773 } while (cPrdtlEntries);
5774
5775 if (RT_UNLIKELY(!cRanges))
5776 {
5777 return VERR_BUFFER_OVERFLOW;
5778 }
5779
5780 pAhciReq->u.Trim.cRanges = cRanges;
5781 pAhciReq->u.Trim.paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges);
5782 if (pAhciReq->u.Trim.paRanges)
5783 {
5784 uint32_t idxRange = 0;
5785
5786 cPrdtlEntries = pAhciReq->cPrdtlEntries;
5787 GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
5788
5789 /* Convert the ranges from the guest to our format. */
5790 do
5791 {
5792 uint32_t cPrdtlEntriesRead = (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
5793 ? cPrdtlEntries
5794 : RT_ELEMENTS(aPrdtlEntries);
5795
5796 PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
5797
5798 for (uint32_t i = 0; i < cPrdtlEntriesRead; i++)
5799 {
5800 RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
5801 uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
5802
5803 cbThisCopy = RT_MIN(cbThisCopy, sizeof(aRanges));
5804
5805 /* Copy into buffer. */
5806 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy);
5807
5808 for (unsigned idxRangeSrc = 0; idxRangeSrc < RT_ELEMENTS(aRanges); idxRangeSrc++)
5809 {
5810 aRanges[idxRangeSrc] = RT_H2LE_U64(aRanges[idxRangeSrc]);
5811 if (AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) != 0)
5812 {
5813 pAhciReq->u.Trim.paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * pAhciPort->cbSector;
5814 pAhciReq->u.Trim.paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * pAhciPort->cbSector;
5815 idxRange++;
5816 }
5817 else
5818 break;
5819 }
5820 }
5821
5822 GCPhysPrdtl += cPrdtlEntriesRead * sizeof(SGLEntry);
5823 cPrdtlEntries -= cPrdtlEntriesRead;
5824 } while (idxRange < cRanges);
5825 }
5826 else
5827 rc = VERR_NO_MEMORY;
5828
5829 LogFlowFunc(("returns rc=%Rrc\n", rc));
5830 return rc;
5831}
5832
5833/**
5834 * Destroy the trim range list.
5835 *
5836 * @returns nothing.
5837 * @param pAhciReq The task state.
5838 */
5839static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq)
5840{
5841 AssertReturnVoid(pAhciReq->enmTxDir == AHCITXDIR_TRIM);
5842 RTMemFree(pAhciReq->u.Trim.paRanges);
5843}
5844
5845/**
5846 * Complete a data transfer task by freeing all occupied resources
5847 * and notifying the guest.
5848 *
5849 * @returns Flag whether the given request was canceled inbetween;
5850 *
5851 * @param pAhciPort Pointer to the port where to request completed.
5852 * @param pAhciReq Pointer to the task which finished.
5853 * @param rcReq IPRT status code of the completed request.
5854 * @param fFreeReq Flag whether to free the request if it was canceled.
5855 */
5856static bool ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcReq, bool fFreeReq)
5857{
5858 bool fXchg = false;
5859 bool fRedo = false;
5860 bool fCanceled = false;
5861 uint64_t tsNow = RTTimeMilliTS();
5862 AHCITXSTATE enmTxState = AHCITXSTATE_INVALID;
5863
5864 LogFlowFunc(("pAhciPort=%p pAhciReq=%p rcReq=%d fFreeReq=%RTbool\n",
5865 pAhciPort, pAhciReq, rcReq, fFreeReq));
5866
5867 ASMAtomicReadSize(&pAhciReq->enmTxState, &enmTxState);
5868 VBOXDD_AHCI_REQ_COMPLETED(pAhciReq, rcReq, enmTxState, pAhciReq->uOffset, pAhciReq->cbTransfer);
5869 VBOXDD_AHCI_REQ_COMPLETED_TIMESTAMP(pAhciReq, tsNow);
5870
5871 /*
5872 * Leave a release log entry if the request was active for more than 25 seconds
5873 * (30 seconds is the timeout of the guest).
5874 */
5875 if (tsNow - pAhciReq->tsStart >= 25 * 1000)
5876 {
5877 const char *pcszReq = NULL;
5878
5879 switch (pAhciReq->enmTxDir)
5880 {
5881 case AHCITXDIR_READ:
5882 pcszReq = "Read";
5883 break;
5884 case AHCITXDIR_WRITE:
5885 pcszReq = "Write";
5886 break;
5887 case AHCITXDIR_FLUSH:
5888 pcszReq = "Flush";
5889 break;
5890 case AHCITXDIR_TRIM:
5891 pcszReq = "Trim";
5892 break;
5893 default:
5894 pcszReq = "<Invalid>";
5895 }
5896
5897 LogRel(("AHCI#%uP%u: %s request was active for %llu seconds\n",
5898 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, pcszReq, (tsNow - pAhciReq->tsStart) / 1000));
5899 }
5900
5901 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
5902
5903 if (fXchg)
5904 {
5905 if (pAhciReq->enmTxDir == AHCITXDIR_READ)
5906 {
5907 ahciIoBufFree(pAhciPort->pDevInsR3, pAhciReq, true /* fCopyToGuest */);
5908 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciReq->cbTransfer);
5909 pAhciPort->Led.Actual.s.fReading = 0;
5910 }
5911 else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
5912 {
5913 ahciIoBufFree(pAhciPort->pDevInsR3, pAhciReq, false /* fCopyToGuest */);
5914 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciReq->cbTransfer);
5915 pAhciPort->Led.Actual.s.fWriting = 0;
5916 }
5917 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
5918 {
5919 ahciTrimRangesDestroy(pAhciReq);
5920 pAhciPort->Led.Actual.s.fWriting = 0;
5921 }
5922
5923 if (RT_FAILURE(rcReq))
5924 {
5925 /* Log the error. */
5926 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
5927 {
5928 if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
5929 LogRel(("AHCI#%uP%u: Flush returned rc=%Rrc\n",
5930 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
5931 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
5932 LogRel(("AHCI#%uP%u: Trim returned rc=%Rrc\n",
5933 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
5934 else
5935 LogRel(("AHCI#%uP%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
5936 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
5937 pAhciReq->enmTxDir == AHCITXDIR_READ
5938 ? "Read"
5939 : "Write",
5940 pAhciReq->uOffset,
5941 pAhciReq->cbTransfer, rcReq));
5942 }
5943
5944 fRedo = ahciIsRedoSetWarning(pAhciPort, rcReq);
5945 if (!fRedo)
5946 {
5947 pAhciReq->cmdHdr.u32PRDBC = 0;
5948 pAhciReq->uATARegError = ID_ERR;
5949 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
5950 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciReq, NULL);
5951 }
5952 else
5953 ASMAtomicOrU32(&pAhciPort->u32TasksRedo, RT_BIT_32(pAhciReq->uTag));
5954 }
5955 else
5956 {
5957 pAhciReq->cmdHdr.u32PRDBC = pAhciReq->cbTransfer;
5958
5959 /* Status will be set by already for non I/O requests. */
5960 if (pAhciReq->enmTxDir != AHCITXDIR_NONE)
5961 {
5962 pAhciReq->uATARegError = 0;
5963 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
5964 }
5965
5966 /* Write updated command header into memory of the guest. */
5967 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
5968
5969 if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
5970 {
5971 /*
5972 * The guest tried to transfer more data than there is space in the buffer.
5973 * Terminate task and set the overflow bit.
5974 */
5975 /* Notify the guest. */
5976 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
5977 if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
5978 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
5979 }
5980 }
5981
5982 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0 ,
5983 ("Inconsistent request counter\n"));
5984 ASMAtomicDecU32(&pAhciPort->cTasksActive);
5985
5986 if (!fRedo)
5987 {
5988
5989 /* Post a PIO setup FIS first if this is a PIO command which transfers data. */
5990 if (pAhciReq->fFlags & AHCI_REQ_PIO_DATA)
5991 ahciSendPioSetupFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false /* fInterrupt */);
5992
5993 if (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT)
5994 {
5995 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ))
5996 ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(pAhciReq->uTag));
5997 }
5998
5999 if (pAhciReq->fFlags & AHCI_REQ_IS_QUEUED)
6000 {
6001 /*
6002 * Always raise an interrupt after task completion; delaying
6003 * this (interrupt coalescing) increases latency and has a significant
6004 * impact on performance (see @bugref{5071})
6005 */
6006 ahciSendSDBFis(pAhciPort, 0, true);
6007 }
6008 else
6009 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
6010 }
6011 }
6012 else
6013 {
6014 /*
6015 * Task was canceled, do the cleanup but DO NOT access the guest memory!
6016 * The guest might use it for other things now because it doesn't know about that task anymore.
6017 */
6018 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_CANCELED,
6019 ("Task is not active but wasn't canceled!\n"));
6020
6021 fCanceled = true;
6022 ASMAtomicXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE);
6023
6024 if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
6025 ahciTrimRangesDestroy(pAhciReq);
6026 else if (pAhciReq->enmTxDir != AHCITXDIR_FLUSH)
6027 ahciIoBufFree(pAhciPort->pDevInsR3, pAhciReq, false /* fCopyToGuest */);
6028
6029 /* Leave a log message about the canceled request. */
6030 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
6031 {
6032 if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
6033 LogRel(("AHCI#%uP%u: Canceled flush returned rc=%Rrc\n",
6034 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq));
6035 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
6036 LogRel(("AHCI#%uP%u: Canceled trim returned rc=%Rrc\n",
6037 pAhciPort->CTX_SUFF(pDevIns)->iInstance,pAhciPort->iLUN, rcReq));
6038 else
6039 LogRel(("AHCI#%uP%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
6040 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN,
6041 pAhciReq->enmTxDir == AHCITXDIR_READ
6042 ? "read"
6043 : "write",
6044 pAhciReq->uOffset,
6045 pAhciReq->cbTransfer, rcReq));
6046 }
6047
6048 /* Finally free the task state structure because it is completely unused now. */
6049 if (fFreeReq)
6050 RTMemFree(pAhciReq);
6051 }
6052
6053 return fCanceled;
6054}
6055
6056/**
6057 * Notification callback for a completed transfer.
6058 *
6059 * @returns VBox status code.
6060 * @param pInterface Pointer to the interface.
6061 * @param pvUser User data.
6062 * @param rcReq IPRT Status code of the completed request.
6063 */
6064static DECLCALLBACK(int) ahciR3TransferCompleteNotify(PPDMIBLOCKASYNCPORT pInterface, void *pvUser, int rcReq)
6065{
6066 PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface);
6067 PAHCIREQ pAhciReq = (PAHCIREQ)pvUser;
6068
6069 ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n",
6070 __FUNCTION__, pInterface, pvUser, pAhciReq->uTag));
6071
6072 int rc = ahciTransferComplete(pAhciPort, pAhciReq, rcReq, true);
6073
6074 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
6075 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
6076 return rc;
6077}
6078
6079/**
6080 * Process an non read/write ATA command.
6081 *
6082 * @returns The direction of the data transfer
6083 * @param pCmdHdr Pointer to the command header.
6084 */
6085static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
6086{
6087 AHCITXDIR enmTxDir = AHCITXDIR_NONE;
6088 bool fLBA48 = false;
6089 CmdHdr *pCmdHdr = &pAhciReq->cmdHdr;
6090
6091 AssertMsg(pCmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D, ("FIS is not a host to device Fis!!\n"));
6092
6093 pAhciReq->cbTransfer = 0;
6094
6095 switch (pCmdFis[AHCI_CMDFIS_CMD])
6096 {
6097 case ATA_IDENTIFY_DEVICE:
6098 {
6099 if (pAhciPort->pDrvBlock && !pAhciPort->fATAPI)
6100 {
6101 uint16_t u16Temp[256];
6102 size_t cbCopied;
6103
6104 /* Fill the buffer. */
6105 ahciIdentifySS(pAhciPort, u16Temp);
6106
6107 /* Copy the buffer. */
6108 cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
6109 &u16Temp[0], sizeof(u16Temp));
6110
6111 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
6112 pAhciReq->cbTransfer = cbCopied;
6113 }
6114 else
6115 {
6116 pAhciReq->uATARegError = ABRT_ERR;
6117 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK | ATA_STAT_ERR;
6118 }
6119 break;
6120 }
6121 case ATA_READ_NATIVE_MAX_ADDRESS_EXT:
6122 case ATA_READ_NATIVE_MAX_ADDRESS:
6123 break;
6124 case ATA_SET_FEATURES:
6125 {
6126 switch (pCmdFis[AHCI_CMDFIS_FET])
6127 {
6128 case 0x02: /* write cache enable */
6129 case 0xaa: /* read look-ahead enable */
6130 case 0x55: /* read look-ahead disable */
6131 case 0xcc: /* reverting to power-on defaults enable */
6132 case 0x66: /* reverting to power-on defaults disable */
6133 pAhciReq->uATARegError = 0;
6134 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6135 break;
6136 case 0x82: /* write cache disable */
6137 enmTxDir = AHCITXDIR_FLUSH;
6138 break;
6139 case 0x03:
6140 {
6141 /* set transfer mode */
6142 Log2(("%s: transfer mode %#04x\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC]));
6143 switch (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8)
6144 {
6145 case 0x00: /* PIO default */
6146 case 0x08: /* PIO mode */
6147 break;
6148 case ATA_MODE_MDMA: /* MDMA mode */
6149 pAhciPort->uATATransferMode = (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8) | RT_MIN(pCmdFis[AHCI_CMDFIS_SECTC] & 0x07, ATA_MDMA_MODE_MAX);
6150 break;
6151 case ATA_MODE_UDMA: /* UDMA mode */
6152 pAhciPort->uATATransferMode = (pCmdFis[AHCI_CMDFIS_SECTC] & 0xf8) | RT_MIN(pCmdFis[AHCI_CMDFIS_SECTC] & 0x07, ATA_UDMA_MODE_MAX);
6153 break;
6154 }
6155 break;
6156 }
6157 default:
6158 pAhciReq->uATARegError = ABRT_ERR;
6159 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6160 }
6161 break;
6162 }
6163 case ATA_DEVICE_RESET:
6164 {
6165 if (!pAhciPort->fATAPI)
6166 {
6167 pAhciReq->uATARegError = ABRT_ERR;
6168 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6169 }
6170 else
6171 {
6172 /* Reset the device. */
6173 ahciDeviceReset(pAhciPort, pAhciReq);
6174 }
6175 break;
6176 }
6177 case ATA_FLUSH_CACHE_EXT:
6178 case ATA_FLUSH_CACHE:
6179 enmTxDir = AHCITXDIR_FLUSH;
6180 break;
6181 case ATA_PACKET:
6182 if (!pAhciPort->fATAPI)
6183 {
6184 pAhciReq->uATARegError = ABRT_ERR;
6185 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6186 }
6187 else
6188 enmTxDir = atapiParseCmd(pAhciPort, pAhciReq);
6189 break;
6190 case ATA_IDENTIFY_PACKET_DEVICE:
6191 if (!pAhciPort->fATAPI)
6192 {
6193 pAhciReq->uATARegError = ABRT_ERR;
6194 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6195 }
6196 else
6197 {
6198 atapiDoTransfer(pAhciPort, pAhciReq, 512, ATAFN_SS_ATAPI_IDENTIFY);
6199
6200 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
6201 pAhciReq->uATARegError = 0;
6202 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6203 }
6204 break;
6205 case ATA_SET_MULTIPLE_MODE:
6206 if ( pCmdFis[AHCI_CMDFIS_SECTC] != 0
6207 && ( pCmdFis[AHCI_CMDFIS_SECTC] > ATA_MAX_MULT_SECTORS
6208 || (pCmdFis[AHCI_CMDFIS_SECTC] & (pCmdFis[AHCI_CMDFIS_SECTC] - 1)) != 0))
6209 {
6210 pAhciReq->uATARegError = ABRT_ERR;
6211 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6212 }
6213 else
6214 {
6215 Log2(("%s: set multi sector count to %d\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC]));
6216 pAhciPort->cMultSectors = pCmdFis[AHCI_CMDFIS_SECTC];
6217 pAhciReq->uATARegError = 0;
6218 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6219 }
6220 break;
6221 case ATA_STANDBY_IMMEDIATE:
6222 break; /* Do nothing. */
6223 case ATA_CHECK_POWER_MODE:
6224 pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] = 0xff; /* drive active or idle */
6225 /* fall through */
6226 case ATA_INITIALIZE_DEVICE_PARAMETERS:
6227 case ATA_IDLE_IMMEDIATE:
6228 case ATA_RECALIBRATE:
6229 case ATA_NOP:
6230 case ATA_READ_VERIFY_SECTORS_EXT:
6231 case ATA_READ_VERIFY_SECTORS:
6232 case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES:
6233 case ATA_SLEEP:
6234 pAhciReq->uATARegError = 0;
6235 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6236 break;
6237 case ATA_READ_DMA_EXT:
6238 fLBA48 = true;
6239 case ATA_READ_DMA:
6240 {
6241 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
6242 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
6243 enmTxDir = AHCITXDIR_READ;
6244 break;
6245 }
6246 case ATA_WRITE_DMA_EXT:
6247 fLBA48 = true;
6248 case ATA_WRITE_DMA:
6249 {
6250 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector;
6251 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector;
6252 enmTxDir = AHCITXDIR_WRITE;
6253 break;
6254 }
6255 case ATA_READ_FPDMA_QUEUED:
6256 {
6257 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
6258 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
6259 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
6260 enmTxDir = AHCITXDIR_READ;
6261 break;
6262 }
6263 case ATA_WRITE_FPDMA_QUEUED:
6264 {
6265 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * pAhciPort->cbSector;
6266 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector;
6267 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED;
6268 enmTxDir = AHCITXDIR_WRITE;
6269 break;
6270 }
6271 case ATA_READ_LOG_EXT:
6272 {
6273 size_t cbLogRead = ((pCmdFis[AHCI_CMDFIS_SECTCEXP] << 8) | pCmdFis[AHCI_CMDFIS_SECTC]) * 512;
6274 unsigned offLogRead = ((pCmdFis[AHCI_CMDFIS_CYLLEXP] << 8) | pCmdFis[AHCI_CMDFIS_CYLL]) * 512;
6275 unsigned iPage = pCmdFis[AHCI_CMDFIS_SECTN];
6276 size_t cbCopied;
6277
6278 LogFlow(("Trying to read %zu bytes starting at offset %u from page %u\n", cbLogRead, offLogRead, iPage));
6279
6280 uint8_t aBuf[512];
6281
6282 memset(aBuf, 0, sizeof(aBuf));
6283
6284 if (offLogRead + cbLogRead <= sizeof(aBuf))
6285 {
6286 switch (iPage)
6287 {
6288 case 0x10:
6289 {
6290 LogFlow(("Reading error page\n"));
6291 PAHCIREQ pTaskErr = ASMAtomicXchgPtrT(&pAhciPort->pTaskErr, NULL, PAHCIREQ);
6292 if (pTaskErr)
6293 {
6294 aBuf[0] = (pTaskErr->fFlags & AHCI_REQ_IS_QUEUED) ? pTaskErr->uTag : (1 << 7);
6295 aBuf[2] = pTaskErr->uATARegStatus;
6296 aBuf[3] = pTaskErr->uATARegError;
6297 aBuf[4] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTN];
6298 aBuf[5] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLL];
6299 aBuf[6] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLH];
6300 aBuf[7] = pTaskErr->cmdFis[AHCI_CMDFIS_HEAD];
6301 aBuf[8] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTNEXP];
6302 aBuf[9] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLLEXP];
6303 aBuf[10] = pTaskErr->cmdFis[AHCI_CMDFIS_CYLHEXP];
6304 aBuf[12] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTC];
6305 aBuf[13] = pTaskErr->cmdFis[AHCI_CMDFIS_SECTCEXP];
6306
6307 /* Calculate checksum */
6308 uint8_t uChkSum = 0;
6309 for (unsigned i = 0; i < RT_ELEMENTS(aBuf)-1; i++)
6310 uChkSum += aBuf[i];
6311
6312 aBuf[511] = (uint8_t)-(int8_t)uChkSum;
6313
6314 /*
6315 * Reading this log page results in an abort of all outstanding commands
6316 * and clearing the SActive register and TaskFile register.
6317 */
6318 ahciSendSDBFis(pAhciPort, 0xffffffff, true);
6319 }
6320 break;
6321 }
6322 }
6323
6324 /* Copy the buffer. */
6325 cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
6326 &aBuf[offLogRead], cbLogRead);
6327
6328 pAhciReq->fFlags |= AHCI_REQ_PIO_DATA;
6329 pAhciReq->cbTransfer = cbCopied;
6330 }
6331
6332 break;
6333 }
6334 case ATA_DATA_SET_MANAGEMENT:
6335 {
6336 if ( ( !pAhciPort->fAsyncInterface
6337 && pAhciPort->pDrvBlock->pfnDiscard)
6338 || ( pAhciPort->fAsyncInterface
6339 && pAhciPort->pDrvBlockAsync->pfnStartDiscard))
6340 {
6341 /* Check that the trim bit is set and all other bits are 0. */
6342 if ( !(pAhciReq->cmdFis[AHCI_CMDFIS_FET] & UINT16_C(0x01))
6343 || (pAhciReq->cmdFis[AHCI_CMDFIS_FET] & ~UINT16_C(0x1)))
6344 {
6345 pAhciReq->uATARegError = ABRT_ERR;
6346 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
6347 }
6348 else
6349 enmTxDir = AHCITXDIR_TRIM;
6350 break;
6351 }
6352 /* else: fall through and report error to the guest. */
6353 }
6354 /* All not implemented commands go below. */
6355 case ATA_SECURITY_FREEZE_LOCK:
6356 case ATA_SMART:
6357 case ATA_NV_CACHE:
6358 case ATA_IDLE:
6359 pAhciReq->uATARegError = ABRT_ERR;
6360 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6361 break;
6362 default: /* For debugging purposes. */
6363 AssertMsgFailed(("Unknown command issued\n"));
6364 pAhciReq->uATARegError = ABRT_ERR;
6365 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
6366 }
6367
6368 return enmTxDir;
6369}
6370
6371/**
6372 * Retrieve a command FIS from guest memory.
6373 *
6374 * @returns whether the H2D FIS was successfully read from the guest memory.
6375 * @param pAhciReq The state of the actual task.
6376 */
6377static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
6378{
6379 RTGCPHYS GCPhysAddrCmdTbl;
6380
6381 AssertMsgReturn(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb,
6382 ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__),
6383 false);
6384
6385 /*
6386 * First we are reading the command header pointed to by regCLB.
6387 * From this we get the address of the command table which we are reading too.
6388 * We can process the Command FIS afterwards.
6389 */
6390 pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr);
6391 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdLst=%RGp cbCmdHdr=%u\n", __FUNCTION__,
6392 pAhciReq->GCPhysCmdHdrAddr, sizeof(CmdHdr)));
6393 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
6394
6395#ifdef LOG_ENABLED
6396 /* Print some infos about the command header. */
6397 ahciDumpCmdHdrInfo(pAhciPort, &pAhciReq->cmdHdr);
6398#endif
6399
6400 GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr);
6401
6402 AssertMsgReturn((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
6403 ("This is not a command FIS!!\n"),
6404 false);
6405
6406 /* Read the command Fis. */
6407 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdTbl=%RGp cbCmdFis=%u\n", __FUNCTION__, GCPhysAddrCmdTbl, AHCI_CMDFIS_TYPE_H2D_SIZE));
6408 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);
6409
6410 AssertMsgReturn(pAhciReq->cmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D,
6411 ("This is not a command FIS\n"),
6412 false);
6413
6414 /* Set transfer direction. */
6415 pAhciReq->enmTxDir = (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;
6416
6417 /* If this is an ATAPI command read the atapi command. */
6418 if (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_A)
6419 {
6420 GCPhysAddrCmdTbl += AHCI_CMDHDR_ACMD_OFFSET;
6421 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->aATAPICmd[0], ATAPI_PACKET_SIZE);
6422 }
6423
6424 /* We "received" the FIS. Clear the BSY bit in regTFD. */
6425 if ((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT))
6426 {
6427 /*
6428 * 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.
6429 * but this FIS does not assert an interrupt
6430 */
6431 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false);
6432 pAhciPort->regTFD &= ~AHCI_PORT_TFD_BSY;
6433 }
6434
6435 pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
6436 pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES(pAhciReq->cmdHdr.u32DescInf);
6437
6438#ifdef LOG_ENABLED
6439 /* Print some infos about the FIS. */
6440 ahciDumpFisInfo(pAhciPort, &pAhciReq->cmdFis[0]);
6441
6442 /* Print the PRDT */
6443 ahciLog(("PRDT address %RGp number of entries %u\n", pAhciReq->GCPhysPrdtl, pAhciReq->cPrdtlEntries));
6444 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
6445
6446 for (unsigned i = 0; i < pAhciReq->cPrdtlEntries; i++)
6447 {
6448 SGLEntry SGEntry;
6449
6450 ahciLog(("Entry %u at address %RGp\n", i, GCPhysPrdtl));
6451 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysPrdtl, &SGEntry, sizeof(SGLEntry));
6452
6453 RTGCPHYS GCPhysDataAddr = AHCI_RTGCPHYS_FROM_U32(SGEntry.u32DBAUp, SGEntry.u32DBA);
6454 ahciLog(("GCPhysAddr=%RGp Size=%u\n", GCPhysDataAddr, SGEntry.u32DescInf & SGLENTRY_DESCINF_DBC));
6455
6456 GCPhysPrdtl += sizeof(SGLEntry);
6457 }
6458#endif
6459
6460 return true;
6461}
6462
6463/**
6464 * Transmit queue consumer
6465 * Queue a new async task.
6466 *
6467 * @returns Success indicator.
6468 * If false the item will not be removed and the flushing will stop.
6469 * @param pDevIns The device instance.
6470 * @param pItem The item to consume. Upon return this item will be freed.
6471 */
6472static DECLCALLBACK(bool) ahciNotifyQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem)
6473{
6474 PDEVPORTNOTIFIERQUEUEITEM pNotifierItem = (PDEVPORTNOTIFIERQUEUEITEM)pItem;
6475 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
6476 PAHCIPort pAhciPort = &pThis->ahciPort[pNotifierItem->iPort];
6477 int rc = VINF_SUCCESS;
6478
6479 ahciLog(("%s: Got notification from GC\n", __FUNCTION__));
6480 /* Notify the async IO thread. */
6481 rc = SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
6482 AssertRC(rc);
6483
6484 return true;
6485}
6486
6487/* The async IO thread for one port. */
6488static DECLCALLBACK(int) ahciAsyncIOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
6489{
6490 PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
6491 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
6492 int rc = VINF_SUCCESS;
6493 uint64_t u64StartTime = 0;
6494 uint64_t u64StopTime = 0;
6495 uint32_t uIORequestsProcessed = 0;
6496 uint32_t uIOsPerSec = 0;
6497 uint32_t fTasksToProcess = 0;
6498
6499 ahciLog(("%s: Port %d entering async IO loop.\n", __FUNCTION__, pAhciPort->iLUN));
6500
6501 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
6502 return VINF_SUCCESS;
6503
6504 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
6505 {
6506 unsigned idx = 0;
6507 uint32_t u32Tasks = 0;
6508 uint32_t u32RegHbaCtrl = 0;
6509
6510 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, true);
6511 u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
6512 if (!u32Tasks)
6513 {
6514 Assert(ASMAtomicReadBool(&pAhciPort->fWrkThreadSleeping));
6515 rc = SUPSemEventWaitNoResume(pAhci->pSupDrvSession, pAhciPort->hEvtProcess, RT_INDEFINITE_WAIT);
6516 AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc);
6517 if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
6518 break;
6519 LogFlowFunc(("Woken up with rc=%Rrc\n", rc));
6520 u32Tasks = ASMAtomicXchgU32(&pAhciPort->u32TasksNew, 0);
6521 }
6522
6523 ASMAtomicWriteBool(&pAhciPort->fWrkThreadSleeping, false);
6524 ASMAtomicIncU32(&pAhci->cThreadsActive);
6525
6526 /*
6527 * Check whether the global host controller bit is set and go to sleep immediately again
6528 * if it is set.
6529 */
6530 u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl);
6531 if ( u32RegHbaCtrl & AHCI_HBA_CTRL_HR
6532 && !ASMAtomicDecU32(&pAhci->cThreadsActive))
6533 {
6534 ahciHBAReset(pAhci);
6535 continue;
6536 }
6537
6538 idx = ASMBitFirstSetU32(u32Tasks);
6539 while (idx)
6540 {
6541 AHCITXDIR enmTxDir;
6542 PAHCIREQ pAhciReq;
6543
6544 /* Decrement to get the slot number. */
6545 idx--;
6546 ahciLog(("%s: Processing command at slot %d\n", __FUNCTION__, idx));
6547
6548 /*
6549 * Check if there is already an allocated task struct in the cache.
6550 * Allocate a new task otherwise.
6551 */
6552 if (!pAhciPort->aCachedTasks[idx])
6553 {
6554 pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ));
6555 AssertMsg(pAhciReq, ("%s: Cannot allocate task state memory!\n"));
6556 pAhciReq->enmTxState = AHCITXSTATE_FREE;
6557 pAhciPort->aCachedTasks[idx] = pAhciReq;
6558 }
6559 else
6560 pAhciReq = pAhciPort->aCachedTasks[idx];
6561
6562 bool fXchg;
6563 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE, fXchg);
6564 AssertMsg(fXchg, ("Task is already active\n"));
6565
6566 pAhciReq->tsStart = RTTimeMilliTS();
6567 pAhciReq->uATARegStatus = 0;
6568 pAhciReq->uATARegError = 0;
6569 pAhciReq->fFlags = 0;
6570
6571 /* Set current command slot */
6572 pAhciReq->uTag = idx;
6573 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
6574
6575 bool fFisRead = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
6576 if (RT_UNLIKELY(!fFisRead))
6577 {
6578 /*
6579 * Couldn't find anything in either the AHCI or SATA spec which
6580 * indicates what should be done if the FIS is not read successfully.
6581 * The closest thing is in the state machine, stating that the device
6582 * should go into idle state again (SATA spec 1.0 chapter 8.7.1).
6583 * Do the same here and ignore any corrupt FIS types, after all
6584 * the guest messed up everything and this behavior is undefined.
6585 */
6586 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
6587 Assert(fXchg);
6588 u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */
6589 idx = ASMBitFirstSetU32(u32Tasks);
6590 continue;
6591 }
6592
6593 /* 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. */
6594 if (pAhciPort->regSACT & (1 << idx))
6595 {
6596 pAhciReq->fFlags |= AHCI_REQ_CLEAR_SACT;
6597 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
6598 }
6599
6600 if (!(pAhciReq->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))
6601 {
6602 /* If the reset bit is set put the device into reset state. */
6603 if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
6604 {
6605 ahciLog(("%s: Setting device into reset state\n", __FUNCTION__));
6606 pAhciPort->fResetDevice = true;
6607 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
6608 }
6609 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
6610 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
6611 else /* We are not in a reset state update the control registers. */
6612 AssertMsgFailed(("%s: Update the control register\n", __FUNCTION__));
6613
6614 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
6615 AssertMsg(fXchg, ("Task is not active\n"));
6616 break;
6617 }
6618 else
6619 {
6620 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) < AHCI_NR_COMMAND_SLOTS,
6621 ("There are more than 32 requests active"));
6622 ASMAtomicIncU32(&pAhciPort->cTasksActive);
6623
6624 enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);
6625 pAhciReq->enmTxDir = enmTxDir;
6626
6627 if (enmTxDir != AHCITXDIR_NONE)
6628 {
6629 if ( enmTxDir != AHCITXDIR_FLUSH
6630 && enmTxDir != AHCITXDIR_TRIM)
6631 {
6632 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
6633
6634 rc = ahciIoBufAllocate(pAhciPort->pDevInsR3, pAhciReq, pAhciReq->cbTransfer);
6635 if (RT_FAILURE(rc))
6636 AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc));
6637 }
6638
6639 if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
6640 {
6641 if (pAhciPort->fAsyncInterface)
6642 {
6643 VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, enmTxDir, pAhciReq->uOffset, pAhciReq->cbTransfer);
6644 VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart);
6645 if (enmTxDir == AHCITXDIR_FLUSH)
6646 {
6647 rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync,
6648 pAhciReq);
6649 }
6650 else if (enmTxDir == AHCITXDIR_TRIM)
6651 {
6652 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
6653 if (RT_SUCCESS(rc))
6654 {
6655 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6656 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciReq->u.Trim.paRanges,
6657 pAhciReq->u.Trim.cRanges, pAhciReq);
6658 }
6659 }
6660 else if (enmTxDir == AHCITXDIR_READ)
6661 {
6662 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
6663 rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
6664 &pAhciReq->u.Io.DataSeg, 1,
6665 pAhciReq->cbTransfer,
6666 pAhciReq);
6667 }
6668 else
6669 {
6670 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6671 rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
6672 &pAhciReq->u.Io.DataSeg, 1,
6673 pAhciReq->cbTransfer,
6674 pAhciReq);
6675 }
6676 if (rc == VINF_VD_ASYNC_IO_FINISHED)
6677 rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
6678 else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
6679 rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
6680 }
6681 else
6682 {
6683 if (enmTxDir == AHCITXDIR_FLUSH)
6684 rc = pAhciPort->pDrvBlock->pfnFlush(pAhciPort->pDrvBlock);
6685 else if (enmTxDir == AHCITXDIR_TRIM)
6686 {
6687 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
6688 if (RT_SUCCESS(rc))
6689 {
6690 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6691 rc = pAhciPort->pDrvBlock->pfnDiscard(pAhciPort->pDrvBlock, pAhciReq->u.Trim.paRanges,
6692 pAhciReq->u.Trim.cRanges);
6693 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
6694 }
6695 }
6696 else if (enmTxDir == AHCITXDIR_READ)
6697 {
6698 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
6699 rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, pAhciReq->uOffset,
6700 pAhciReq->u.Io.DataSeg.pvSeg,
6701 pAhciReq->cbTransfer);
6702 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 0;
6703 }
6704 else
6705 {
6706 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
6707 rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, pAhciReq->uOffset,
6708 pAhciReq->u.Io.DataSeg.pvSeg,
6709 pAhciReq->cbTransfer);
6710 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0;
6711 }
6712 rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
6713 }
6714 }
6715 }
6716 else
6717 rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
6718 } /* Command */
6719
6720 u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */
6721 idx = ASMBitFirstSetU32(u32Tasks);
6722 } /* while tasks available */
6723
6724 /*
6725 * Check whether a host controller reset is pending and execute the reset
6726 * if this is the last active thread.
6727 */
6728 u32RegHbaCtrl = ASMAtomicReadU32(&pAhci->regHbaCtrl);
6729 uint32_t cThreadsActive = ASMAtomicDecU32(&pAhci->cThreadsActive);
6730 if ( (u32RegHbaCtrl & AHCI_HBA_CTRL_HR)
6731 && !cThreadsActive)
6732 ahciHBAReset(pAhci);
6733 } /* While running */
6734
6735 ahciLog(("%s: Port %d async IO thread exiting\n", __FUNCTION__, pAhciPort->iLUN));
6736 return VINF_SUCCESS;
6737}
6738
6739/**
6740 * Unblock the async I/O thread so it can respond to a state change.
6741 *
6742 * @returns VBox status code.
6743 * @param pDevIns The device instance.
6744 * @param pThread The send thread.
6745 */
6746static DECLCALLBACK(int) ahciAsyncIOLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
6747{
6748 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
6749 PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
6750 return SUPSemEventSignal(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
6751}
6752
6753/* -=-=-=-=- DBGF -=-=-=-=- */
6754
6755/**
6756 * AHCI status info callback.
6757 *
6758 * @param pDevIns The device instance.
6759 * @param pHlp The output helpers.
6760 * @param pszArgs The arguments.
6761 */
6762static DECLCALLBACK(void) ahciR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
6763{
6764 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
6765
6766 /*
6767 * Show info.
6768 */
6769 pHlp->pfnPrintf(pHlp,
6770 "%s#%d: mmio=%RGp ports=%u GC=%RTbool R0=%RTbool\n",
6771 pDevIns->pReg->szName,
6772 pDevIns->iInstance,
6773 pThis->MMIOBase,
6774 pThis->cPortsImpl,
6775 pThis->fGCEnabled ? true : false,
6776 pThis->fR0Enabled ? true : false);
6777
6778 /*
6779 * Show global registers.
6780 */
6781 pHlp->pfnPrintf(pHlp, "HbaCap=%#x\n", pThis->regHbaCap);
6782 pHlp->pfnPrintf(pHlp, "HbaCtrl=%#x\n", pThis->regHbaCtrl);
6783 pHlp->pfnPrintf(pHlp, "HbaIs=%#x\n", pThis->regHbaIs);
6784 pHlp->pfnPrintf(pHlp, "HbaPi=%#x", pThis->regHbaPi);
6785 pHlp->pfnPrintf(pHlp, "HbaVs=%#x\n", pThis->regHbaVs);
6786 pHlp->pfnPrintf(pHlp, "HbaCccCtl=%#x\n", pThis->regHbaCccCtl);
6787 pHlp->pfnPrintf(pHlp, "HbaCccPorts=%#x\n", pThis->regHbaCccPorts);
6788 pHlp->pfnPrintf(pHlp, "PortsInterrupted=%#x\n", pThis->u32PortsInterrupted);
6789
6790 /*
6791 * Per port data.
6792 */
6793 for (unsigned i = 0; i < pThis->cPortsImpl; i++)
6794 {
6795 PAHCIPort pThisPort = &pThis->ahciPort[i];
6796
6797 pHlp->pfnPrintf(pHlp, "Port %d: async=%RTbool device-attached=%RTbool\n",
6798 pThisPort->iLUN, pThisPort->fAsyncInterface, pThisPort->pDrvBase != NULL);
6799 pHlp->pfnPrintf(pHlp, "PortClb=%#x\n", pThisPort->regCLB);
6800 pHlp->pfnPrintf(pHlp, "PortClbU=%#x\n", pThisPort->regCLBU);
6801 pHlp->pfnPrintf(pHlp, "PortFb=%#x\n", pThisPort->regFB);
6802 pHlp->pfnPrintf(pHlp, "PortFbU=%#x\n", pThisPort->regFBU);
6803 pHlp->pfnPrintf(pHlp, "PortIs=%#x\n", pThisPort->regIS);
6804 pHlp->pfnPrintf(pHlp, "PortIe=%#x\n", pThisPort->regIE);
6805 pHlp->pfnPrintf(pHlp, "PortCmd=%#x\n", pThisPort->regCMD);
6806 pHlp->pfnPrintf(pHlp, "PortTfd=%#x\n", pThisPort->regTFD);
6807 pHlp->pfnPrintf(pHlp, "PortSig=%#x\n", pThisPort->regSIG);
6808 pHlp->pfnPrintf(pHlp, "PortSSts=%#x\n", pThisPort->regSSTS);
6809 pHlp->pfnPrintf(pHlp, "PortSCtl=%#x\n", pThisPort->regSCTL);
6810 pHlp->pfnPrintf(pHlp, "PortSErr=%#x\n", pThisPort->regSERR);
6811 pHlp->pfnPrintf(pHlp, "PortSAct=%#x\n", pThisPort->regSACT);
6812 pHlp->pfnPrintf(pHlp, "PortCi=%#x\n", pThisPort->regCI);
6813 pHlp->pfnPrintf(pHlp, "PortPhysClb=%RGp\n", pThisPort->GCPhysAddrClb);
6814 pHlp->pfnPrintf(pHlp, "PortPhysFb=%RGp\n", pThisPort->GCPhysAddrFb);
6815 pHlp->pfnPrintf(pHlp, "PortActTasksActive=%u\n", pThisPort->cTasksActive);
6816 pHlp->pfnPrintf(pHlp, "PortPoweredOn=%RTbool\n", pThisPort->fPoweredOn);
6817 pHlp->pfnPrintf(pHlp, "PortSpunUp=%RTbool\n", pThisPort->fSpunUp);
6818 pHlp->pfnPrintf(pHlp, "PortFirstD2HFisSend=%RTbool\n", pThisPort->fFirstD2HFisSend);
6819 pHlp->pfnPrintf(pHlp, "PortATAPI=%RTbool\n", pThisPort->fATAPI);
6820 pHlp->pfnPrintf(pHlp, "PortTasksFinished=%#x\n", pThisPort->u32TasksFinished);
6821 pHlp->pfnPrintf(pHlp, "PortQueuedTasksFinished=%#x\n", pThisPort->u32QueuedTasksFinished);
6822 pHlp->pfnPrintf(pHlp, "\n");
6823 }
6824}
6825
6826/* -=-=-=-=- Helper -=-=-=-=- */
6827
6828/**
6829 * Checks if all asynchronous I/O is finished, both AHCI and IDE.
6830 *
6831 * Used by ahciR3Reset, ahciR3Suspend and ahciR3PowerOff. ahciR3SavePrep makes
6832 * use of it in strict builds (which is why it's up here).
6833 *
6834 * @returns true if quiesced, false if busy.
6835 * @param pDevIns The device instance.
6836 */
6837static bool ahciR3AllAsyncIOIsFinished(PPDMDEVINS pDevIns)
6838{
6839 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
6840
6841 if (pThis->cThreadsActive)
6842 return false;
6843
6844 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->ahciPort); i++)
6845 {
6846 PAHCIPort pThisPort = &pThis->ahciPort[i];
6847 if (pThisPort->pDrvBase)
6848 {
6849 if ( (pThisPort->cTasksActive != 0)
6850 || (pThisPort->u32TasksNew != 0))
6851 return false;
6852 }
6853 }
6854 return true;
6855}
6856
6857/* -=-=-=-=- Saved State -=-=-=-=- */
6858
6859/**
6860 * @copydoc FNDEVSSMSAVEPREP
6861 */
6862static DECLCALLBACK(int) ahciR3SavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
6863{
6864 Assert(ahciR3AllAsyncIOIsFinished(pDevIns));
6865 return VINF_SUCCESS;
6866}
6867
6868/**
6869 * @copydoc FNDEVSSMLOADPREP
6870 */
6871static DECLCALLBACK(int) ahciR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
6872{
6873 Assert(ahciR3AllAsyncIOIsFinished(pDevIns));
6874 return VINF_SUCCESS;
6875}
6876
6877/**
6878 * @copydoc FNDEVSSMLIVEEXEC
6879 */
6880static DECLCALLBACK(int) ahciR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
6881{
6882 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
6883
6884 /* config. */
6885 SSMR3PutU32(pSSM, pThis->cPortsImpl);
6886 for (uint32_t i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
6887 {
6888 SSMR3PutBool(pSSM, pThis->ahciPort[i].pDrvBase != NULL);
6889 SSMR3PutBool(pSSM, pThis->ahciPort[i].fHotpluggable);
6890 SSMR3PutStrZ(pSSM, pThis->ahciPort[i].szSerialNumber);
6891 SSMR3PutStrZ(pSSM, pThis->ahciPort[i].szFirmwareRevision);
6892 SSMR3PutStrZ(pSSM, pThis->ahciPort[i].szModelNumber);
6893 }
6894
6895 static const char *s_apszIdeEmuPortNames[4] = { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
6896 for (size_t i = 0; i < RT_ELEMENTS(s_apszIdeEmuPortNames); i++)
6897 {
6898 uint32_t iPort;
6899 int rc = CFGMR3QueryU32Def(pDevIns->pCfg, s_apszIdeEmuPortNames[i], &iPort, i);
6900 AssertRCReturn(rc, rc);
6901 SSMR3PutU32(pSSM, iPort);
6902 }
6903
6904 return VINF_SSM_DONT_CALL_AGAIN;
6905}
6906
6907/**
6908 * @copydoc FNDEVSSMSAVEEXEC
6909 */
6910static DECLCALLBACK(int) ahciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
6911{
6912 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
6913 uint32_t i;
6914 int rc;
6915
6916 Assert(!pThis->f8ByteMMIO4BytesWrittenSuccessfully);
6917
6918 /* The config */
6919 rc = ahciR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
6920 AssertRCReturn(rc, rc);
6921
6922 /* The main device structure. */
6923 SSMR3PutU32(pSSM, pThis->regHbaCap);
6924 SSMR3PutU32(pSSM, pThis->regHbaCtrl);
6925 SSMR3PutU32(pSSM, pThis->regHbaIs);
6926 SSMR3PutU32(pSSM, pThis->regHbaPi);
6927 SSMR3PutU32(pSSM, pThis->regHbaVs);
6928 SSMR3PutU32(pSSM, pThis->regHbaCccCtl);
6929 SSMR3PutU32(pSSM, pThis->regHbaCccPorts);
6930 SSMR3PutU8(pSSM, pThis->uCccPortNr);
6931 SSMR3PutU64(pSSM, pThis->uCccTimeout);
6932 SSMR3PutU32(pSSM, pThis->uCccNr);
6933 SSMR3PutU32(pSSM, pThis->uCccCurrentNr);
6934 SSMR3PutU32(pSSM, pThis->u32PortsInterrupted);
6935 SSMR3PutBool(pSSM, pThis->fReset);
6936 SSMR3PutBool(pSSM, pThis->f64BitAddr);
6937 SSMR3PutBool(pSSM, pThis->fR0Enabled);
6938 SSMR3PutBool(pSSM, pThis->fGCEnabled);
6939
6940 /* Now every port. */
6941 for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
6942 {
6943 Assert(pThis->ahciPort[i].cTasksActive == 0);
6944 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCLB);
6945 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCLBU);
6946 SSMR3PutU32(pSSM, pThis->ahciPort[i].regFB);
6947 SSMR3PutU32(pSSM, pThis->ahciPort[i].regFBU);
6948 SSMR3PutGCPhys(pSSM, pThis->ahciPort[i].GCPhysAddrClb);
6949 SSMR3PutGCPhys(pSSM, pThis->ahciPort[i].GCPhysAddrFb);
6950 SSMR3PutU32(pSSM, pThis->ahciPort[i].regIS);
6951 SSMR3PutU32(pSSM, pThis->ahciPort[i].regIE);
6952 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCMD);
6953 SSMR3PutU32(pSSM, pThis->ahciPort[i].regTFD);
6954 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSIG);
6955 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSSTS);
6956 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSCTL);
6957 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSERR);
6958 SSMR3PutU32(pSSM, pThis->ahciPort[i].regSACT);
6959 SSMR3PutU32(pSSM, pThis->ahciPort[i].regCI);
6960 SSMR3PutU32(pSSM, pThis->ahciPort[i].PCHSGeometry.cCylinders);
6961 SSMR3PutU32(pSSM, pThis->ahciPort[i].PCHSGeometry.cHeads);
6962 SSMR3PutU32(pSSM, pThis->ahciPort[i].PCHSGeometry.cSectors);
6963 SSMR3PutU64(pSSM, pThis->ahciPort[i].cTotalSectors);
6964 SSMR3PutU32(pSSM, pThis->ahciPort[i].cMultSectors);
6965 SSMR3PutU8(pSSM, pThis->ahciPort[i].uATATransferMode);
6966 SSMR3PutBool(pSSM, pThis->ahciPort[i].fResetDevice);
6967 SSMR3PutBool(pSSM, pThis->ahciPort[i].fPoweredOn);
6968 SSMR3PutBool(pSSM, pThis->ahciPort[i].fSpunUp);
6969 SSMR3PutU32(pSSM, pThis->ahciPort[i].u32TasksFinished);
6970 SSMR3PutU32(pSSM, pThis->ahciPort[i].u32QueuedTasksFinished);
6971 SSMR3PutU32(pSSM, pThis->ahciPort[i].u32CurrentCommandSlot);
6972
6973 /* ATAPI saved state. */
6974 SSMR3PutBool(pSSM, pThis->ahciPort[i].fATAPI);
6975 SSMR3PutMem(pSSM, &pThis->ahciPort[i].abATAPISense[0], sizeof(pThis->ahciPort[i].abATAPISense));
6976 SSMR3PutU8(pSSM, pThis->ahciPort[i].cNotifiedMediaChange);
6977 SSMR3PutU32(pSSM, pThis->ahciPort[i].MediaEventStatus);
6978 }
6979
6980 return SSMR3PutU32(pSSM, UINT32_MAX); /* sanity/terminator */
6981}
6982
6983/**
6984 * Loads a saved legacy ATA emulated device state.
6985 *
6986 * @returns VBox status code.
6987 * @param pSSM The handle to the saved state.
6988 */
6989static int ahciR3LoadLegacyEmulationState(PSSMHANDLE pSSM)
6990{
6991 int rc;
6992 uint32_t u32Version;
6993 uint32_t u32;
6994 uint32_t u32IOBuffer;
6995
6996 /* Test for correct version. */
6997 rc = SSMR3GetU32(pSSM, &u32Version);
6998 AssertRCReturn(rc, rc);
6999 LogFlow(("LoadOldSavedStates u32Version = %d\n", u32Version));
7000
7001 if ( u32Version != ATA_CTL_SAVED_STATE_VERSION
7002 && u32Version != ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE
7003 && u32Version != ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
7004 {
7005 AssertMsgFailed(("u32Version=%d\n", u32Version));
7006 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
7007 }
7008
7009 SSMR3Skip(pSSM, 19 + 5 * sizeof(bool) + sizeof(BMDMAState));
7010
7011 for (uint32_t j = 0; j < 2; j++)
7012 {
7013 SSMR3Skip(pSSM, 88 + 5 * sizeof(bool) );
7014
7015 if (u32Version > ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE)
7016 SSMR3Skip(pSSM, 64);
7017 else
7018 SSMR3Skip(pSSM, 2);
7019 /** @todo triple-check this hack after passthrough is working */
7020 SSMR3Skip(pSSM, 1);
7021
7022 if (u32Version > ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
7023 SSMR3Skip(pSSM, 4);
7024
7025 SSMR3Skip(pSSM, sizeof(PDMLED));
7026 SSMR3GetU32(pSSM, &u32IOBuffer);
7027 if (u32IOBuffer)
7028 SSMR3Skip(pSSM, u32IOBuffer);
7029 }
7030
7031 rc = SSMR3GetU32(pSSM, &u32);
7032 if (RT_FAILURE(rc))
7033 return rc;
7034 if (u32 != ~0U)
7035 {
7036 AssertMsgFailed(("u32=%#x expected ~0\n", u32));
7037 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
7038 return rc;
7039 }
7040
7041 return VINF_SUCCESS;
7042}
7043
7044/**
7045 * Loads a saved AHCI device state.
7046 *
7047 * @returns VBox status code.
7048 * @param pDevIns The device instance.
7049 * @param pSSM The handle to the saved state.
7050 * @param uVersion The data unit version number.
7051 * @param uPass The data pass.
7052 */
7053static DECLCALLBACK(int) ahciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
7054{
7055 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7056 uint32_t u32;
7057 int rc;
7058
7059 if ( uVersion > AHCI_SAVED_STATE_VERSION
7060 || uVersion < AHCI_SAVED_STATE_VERSION_VBOX_30)
7061 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
7062
7063 /* Deal with the priod after removing the saved IDE bits where the saved
7064 state version remained unchanged. */
7065 if ( uVersion == AHCI_SAVED_STATE_VERSION_IDE_EMULATION
7066 && SSMR3HandleRevision(pSSM) >= 79045
7067 && SSMR3HandleRevision(pSSM) < 79201)
7068 uVersion++;
7069
7070 /* Verify config. */
7071 if (uVersion > AHCI_SAVED_STATE_VERSION_VBOX_30)
7072 {
7073 rc = SSMR3GetU32(pSSM, &u32);
7074 AssertRCReturn(rc, rc);
7075 if (u32 != pThis->cPortsImpl)
7076 {
7077 LogRel(("AHCI: Config mismatch: cPortsImpl - saved=%u config=%u\n", u32, pThis->cPortsImpl));
7078 if ( u32 < pThis->cPortsImpl
7079 || u32 > AHCI_MAX_NR_PORTS_IMPL)
7080 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch: cPortsImpl - saved=%u config=%u"),
7081 u32, pThis->cPortsImpl);
7082 }
7083
7084 for (uint32_t i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
7085 {
7086 bool fInUse;
7087 rc = SSMR3GetBool(pSSM, &fInUse);
7088 AssertRCReturn(rc, rc);
7089 if (fInUse != (pThis->ahciPort[i].pDrvBase != NULL))
7090 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
7091 N_("The %s VM is missing a device on port %u. Please make sure the source and target VMs have compatible storage configurations"),
7092 fInUse ? "target" : "source", i );
7093
7094 if (uVersion > AHCI_SAVED_STATE_VERSION_PRE_HOTPLUG_FLAG)
7095 {
7096 bool fHotpluggable;
7097 rc = SSMR3GetBool(pSSM, &fHotpluggable);
7098 AssertRCReturn(rc, rc);
7099 if (fHotpluggable != pThis->ahciPort[i].fHotpluggable)
7100 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
7101 N_("AHCI: Port %u config mismatch: Hotplug flag - saved=%RTbool config=%RTbool\n"),
7102 i, fHotpluggable, pThis->ahciPort[i].fHotpluggable);
7103 }
7104 else
7105 Assert(pThis->ahciPort[i].fHotpluggable);
7106
7107 char szSerialNumber[AHCI_SERIAL_NUMBER_LENGTH+1];
7108 rc = SSMR3GetStrZ(pSSM, szSerialNumber, sizeof(szSerialNumber));
7109 AssertRCReturn(rc, rc);
7110 if (strcmp(szSerialNumber, pThis->ahciPort[i].szSerialNumber))
7111 LogRel(("AHCI: Port %u config mismatch: Serial number - saved='%s' config='%s'\n",
7112 i, szSerialNumber, pThis->ahciPort[i].szSerialNumber));
7113
7114 char szFirmwareRevision[AHCI_FIRMWARE_REVISION_LENGTH+1];
7115 rc = SSMR3GetStrZ(pSSM, szFirmwareRevision, sizeof(szFirmwareRevision));
7116 AssertRCReturn(rc, rc);
7117 if (strcmp(szFirmwareRevision, pThis->ahciPort[i].szFirmwareRevision))
7118 LogRel(("AHCI: Port %u config mismatch: Firmware revision - saved='%s' config='%s'\n",
7119 i, szFirmwareRevision, pThis->ahciPort[i].szFirmwareRevision));
7120
7121 char szModelNumber[AHCI_MODEL_NUMBER_LENGTH+1];
7122 rc = SSMR3GetStrZ(pSSM, szModelNumber, sizeof(szModelNumber));
7123 AssertRCReturn(rc, rc);
7124 if (strcmp(szModelNumber, pThis->ahciPort[i].szModelNumber))
7125 LogRel(("AHCI: Port %u config mismatch: Model number - saved='%s' config='%s'\n",
7126 i, szModelNumber, pThis->ahciPort[i].szModelNumber));
7127 }
7128
7129 static const char *s_apszIdeEmuPortNames[4] = { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
7130 for (size_t i = 0; i < RT_ELEMENTS(s_apszIdeEmuPortNames); i++)
7131 {
7132 uint32_t iPort;
7133 rc = CFGMR3QueryU32Def(pDevIns->pCfg, s_apszIdeEmuPortNames[i], &iPort, i);
7134 AssertRCReturn(rc, rc);
7135
7136 uint32_t iPortSaved;
7137 rc = SSMR3GetU32(pSSM, &iPortSaved);
7138 AssertRCReturn(rc, rc);
7139
7140 if (iPortSaved != iPort)
7141 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("IDE %s config mismatch: saved=%u config=%u"),
7142 s_apszIdeEmuPortNames[i], iPortSaved, iPort);
7143 }
7144 }
7145
7146 if (uPass == SSM_PASS_FINAL)
7147 {
7148 /* Restore data. */
7149
7150 /* The main device structure. */
7151 SSMR3GetU32(pSSM, &pThis->regHbaCap);
7152 SSMR3GetU32(pSSM, &pThis->regHbaCtrl);
7153 SSMR3GetU32(pSSM, &pThis->regHbaIs);
7154 SSMR3GetU32(pSSM, &pThis->regHbaPi);
7155 SSMR3GetU32(pSSM, &pThis->regHbaVs);
7156 SSMR3GetU32(pSSM, &pThis->regHbaCccCtl);
7157 SSMR3GetU32(pSSM, &pThis->regHbaCccPorts);
7158 SSMR3GetU8(pSSM, &pThis->uCccPortNr);
7159 SSMR3GetU64(pSSM, &pThis->uCccTimeout);
7160 SSMR3GetU32(pSSM, &pThis->uCccNr);
7161 SSMR3GetU32(pSSM, &pThis->uCccCurrentNr);
7162
7163 SSMR3GetU32(pSSM, (uint32_t *)&pThis->u32PortsInterrupted);
7164 SSMR3GetBool(pSSM, &pThis->fReset);
7165 SSMR3GetBool(pSSM, &pThis->f64BitAddr);
7166 SSMR3GetBool(pSSM, &pThis->fR0Enabled);
7167 SSMR3GetBool(pSSM, &pThis->fGCEnabled);
7168
7169 /* Now every port. */
7170 for (uint32_t i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
7171 {
7172 PAHCIPort pAhciPort = &pThis->ahciPort[i];
7173
7174 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regCLB);
7175 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regCLBU);
7176 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regFB);
7177 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regFBU);
7178 SSMR3GetGCPhys(pSSM, (RTGCPHYS *)&pThis->ahciPort[i].GCPhysAddrClb);
7179 SSMR3GetGCPhys(pSSM, (RTGCPHYS *)&pThis->ahciPort[i].GCPhysAddrFb);
7180 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].regIS);
7181 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regIE);
7182 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regCMD);
7183 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regTFD);
7184 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSIG);
7185 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSSTS);
7186 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSCTL);
7187 SSMR3GetU32(pSSM, &pThis->ahciPort[i].regSERR);
7188 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].regSACT);
7189 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].regCI);
7190 SSMR3GetU32(pSSM, &pThis->ahciPort[i].PCHSGeometry.cCylinders);
7191 SSMR3GetU32(pSSM, &pThis->ahciPort[i].PCHSGeometry.cHeads);
7192 SSMR3GetU32(pSSM, &pThis->ahciPort[i].PCHSGeometry.cSectors);
7193 SSMR3GetU64(pSSM, &pThis->ahciPort[i].cTotalSectors);
7194 SSMR3GetU32(pSSM, &pThis->ahciPort[i].cMultSectors);
7195 SSMR3GetU8(pSSM, &pThis->ahciPort[i].uATATransferMode);
7196 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fResetDevice);
7197
7198 if (uVersion <= AHCI_SAVED_STATE_VERSION_VBOX_30)
7199 SSMR3Skip(pSSM, AHCI_NR_COMMAND_SLOTS * sizeof(uint8_t)); /* no active data here */
7200
7201 if (uVersion < AHCI_SAVED_STATE_VERSION_IDE_EMULATION)
7202 {
7203 /* The old positions in the FIFO, not required. */
7204 SSMR3Skip(pSSM, 2*sizeof(uint8_t));
7205 }
7206 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fPoweredOn);
7207 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fSpunUp);
7208 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].u32TasksFinished);
7209 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].u32QueuedTasksFinished);
7210
7211 if (uVersion >= AHCI_SAVED_STATE_VERSION_IDE_EMULATION)
7212 SSMR3GetU32(pSSM, (uint32_t *)&pThis->ahciPort[i].u32CurrentCommandSlot);
7213
7214 if (uVersion > AHCI_SAVED_STATE_VERSION_PRE_ATAPI)
7215 {
7216 SSMR3GetBool(pSSM, &pThis->ahciPort[i].fATAPI);
7217 SSMR3GetMem(pSSM, pThis->ahciPort[i].abATAPISense, sizeof(pThis->ahciPort[i].abATAPISense));
7218 SSMR3GetU8(pSSM, &pThis->ahciPort[i].cNotifiedMediaChange);
7219 SSMR3GetU32(pSSM, (uint32_t*)&pThis->ahciPort[i].MediaEventStatus);
7220 }
7221 else if (pThis->ahciPort[i].fATAPI)
7222 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch: atapi - saved=%false config=true"));
7223
7224 /* Check if we have tasks pending. */
7225 uint32_t fTasksOutstanding = pAhciPort->regCI & ~pAhciPort->u32TasksFinished;
7226 uint32_t fQueuedTasksOutstanding = pAhciPort->regSACT & ~pAhciPort->u32QueuedTasksFinished;
7227
7228 pAhciPort->u32TasksNew = fTasksOutstanding | fQueuedTasksOutstanding;
7229
7230 if (pAhciPort->u32TasksNew)
7231 {
7232 /*
7233 * There are tasks pending. The VM was saved after a task failed
7234 * because of non-fatal error. Set the redo flag.
7235 */
7236 pAhciPort->fRedo = true;
7237 }
7238 }
7239
7240 if (uVersion <= AHCI_SAVED_STATE_VERSION_IDE_EMULATION)
7241 {
7242 for (uint32_t i = 0; i < 2; i++)
7243 {
7244 rc = ahciR3LoadLegacyEmulationState(pSSM);
7245 if(RT_FAILURE(rc))
7246 return rc;
7247 }
7248 }
7249
7250 rc = SSMR3GetU32(pSSM, &u32);
7251 if (RT_FAILURE(rc))
7252 return rc;
7253 AssertMsgReturn(u32 == UINT32_MAX, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
7254 }
7255
7256 return VINF_SUCCESS;
7257}
7258
7259/* -=-=-=-=- device PDM interface -=-=-=-=- */
7260
7261static DECLCALLBACK(void) ahciR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
7262{
7263 uint32_t i;
7264 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
7265
7266 pAhci->pDevInsRC += offDelta;
7267 pAhci->pHbaCccTimerRC = TMTimerRCPtr(pAhci->pHbaCccTimerR3);
7268 pAhci->pNotifierQueueRC = PDMQueueRCPtr(pAhci->pNotifierQueueR3);
7269
7270 /* Relocate every port. */
7271 for (i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)
7272 {
7273 PAHCIPort pAhciPort = &pAhci->ahciPort[i];
7274 pAhciPort->pAhciRC += offDelta;
7275 pAhciPort->pDevInsRC += offDelta;
7276 }
7277}
7278
7279/**
7280 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium removed" event
7281 * from now on, regardless if there was a medium inserted or not.
7282 */
7283static void ahciMediumRemoved(PAHCIPort pAhciPort)
7284{
7285 ASMAtomicWriteU32(&pAhciPort->MediaEventStatus, ATA_EVENT_STATUS_MEDIA_REMOVED);
7286}
7287
7288/**
7289 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium inserted". If
7290 * there was already a medium inserted, don't forget to send the "medium
7291 * removed" event first.
7292 */
7293static void ahciMediumInserted(PAHCIPort pAhciPort)
7294{
7295 uint32_t OldStatus, NewStatus;
7296 do
7297 {
7298 OldStatus = ASMAtomicReadU32(&pAhciPort->MediaEventStatus);
7299 switch (OldStatus)
7300 {
7301 case ATA_EVENT_STATUS_MEDIA_CHANGED:
7302 case ATA_EVENT_STATUS_MEDIA_REMOVED:
7303 /* no change, we will send "medium removed" + "medium inserted" */
7304 NewStatus = ATA_EVENT_STATUS_MEDIA_CHANGED;
7305 break;
7306 default:
7307 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW;
7308 break;
7309 }
7310 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus));
7311}
7312
7313/**
7314 * Called when a media is mounted.
7315 *
7316 * @param pInterface Pointer to the interface structure containing the called function pointer.
7317 */
7318static DECLCALLBACK(void) ahciR3MountNotify(PPDMIMOUNTNOTIFY pInterface)
7319{
7320 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface);
7321 Log(("%s: changing LUN#%d\n", __FUNCTION__, pAhciPort->iLUN));
7322
7323 /* Ignore the call if we're called while being attached. */
7324 if (!pAhciPort->pDrvBlock)
7325 return;
7326
7327 if (pAhciPort->fATAPI)
7328 {
7329 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 2048;
7330
7331 LogRel(("AHCI: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pAhciPort->iLUN, pAhciPort->cTotalSectors));
7332
7333 /* Report media changed in TEST UNIT and other (probably incorrect) places. */
7334 if (pAhciPort->cNotifiedMediaChange < 2)
7335 pAhciPort->cNotifiedMediaChange = 2;
7336 ahciMediumInserted(pAhciPort);
7337 ahciMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN);
7338 }
7339 else
7340 AssertMsgFailed(("Hard disks don't have a mount interface!\n"));
7341}
7342
7343/**
7344 * Called when a media is unmounted
7345 * @param pInterface Pointer to the interface structure containing the called function pointer.
7346 */
7347static DECLCALLBACK(void) ahciR3UnmountNotify(PPDMIMOUNTNOTIFY pInterface)
7348{
7349 PAHCIPort pAhciPort = PDMIMOUNTNOTIFY_2_PAHCIPORT(pInterface);
7350 Log(("%s:\n", __FUNCTION__));
7351
7352 pAhciPort->cTotalSectors = 0;
7353
7354 if (pAhciPort->fATAPI)
7355 {
7356 /*
7357 * Whatever I do, XP will not use the GET MEDIA STATUS nor the EVENT stuff.
7358 * However, it will respond to TEST UNIT with a 0x6 0x28 (media changed) sense code.
7359 * So, we'll give it 4 TEST UNIT command to catch up, two which the media is not
7360 * present and 2 in which it is changed.
7361 */
7362 pAhciPort->cNotifiedMediaChange = 4;
7363 ahciMediumRemoved(pAhciPort);
7364 ahciMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN);
7365 }
7366 else
7367 AssertMsgFailed(("Hard disks don't have a mount interface!\n"));
7368}
7369
7370/**
7371 * Configure the attached device for a port.
7372 *
7373 * Used by ahciR3Construct and ahciR3Attach.
7374 *
7375 * @returns VBox status code
7376 * @param pDevIns The device instance data.
7377 * @param pAhciPort The port for which the device is to be configured.
7378 */
7379static int ahciR3ConfigureLUN(PPDMDEVINS pDevIns, PAHCIPort pAhciPort)
7380{
7381 int rc = VINF_SUCCESS;
7382 PDMBLOCKTYPE enmType;
7383
7384 /*
7385 * Query the block and blockbios interfaces.
7386 */
7387 pAhciPort->pDrvBlock = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIBLOCK);
7388 if (!pAhciPort->pDrvBlock)
7389 {
7390 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pAhciPort->iLUN));
7391 return VERR_PDM_MISSING_INTERFACE;
7392 }
7393 pAhciPort->pDrvBlockBios = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIBLOCKBIOS);
7394 if (!pAhciPort->pDrvBlockBios)
7395 {
7396 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block BIOS interface!\n", pAhciPort->iLUN));
7397 return VERR_PDM_MISSING_INTERFACE;
7398 }
7399
7400 pAhciPort->pDrvMount = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMOUNT);
7401
7402 /* Try to get the optional async block interface. */
7403 pAhciPort->pDrvBlockAsync = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIBLOCKASYNC);
7404
7405 /*
7406 * Validate type.
7407 */
7408 enmType = pAhciPort->pDrvBlock->pfnGetType(pAhciPort->pDrvBlock);
7409
7410 if ( enmType != PDMBLOCKTYPE_HARD_DISK
7411 && enmType != PDMBLOCKTYPE_CDROM
7412 && enmType != PDMBLOCKTYPE_DVD)
7413 {
7414 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%d\n", pAhciPort->iLUN, enmType));
7415 return VERR_PDM_UNSUPPORTED_BLOCK_TYPE;
7416 }
7417
7418 if ( (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD)
7419 && !pAhciPort->pDrvMount)
7420 {
7421 AssertMsgFailed(("Internal error: CD/DVD-ROM without a mountable interface\n"));
7422 return VERR_INTERNAL_ERROR;
7423 }
7424 pAhciPort->fATAPI = (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD);
7425 pAhciPort->fATAPIPassthrough = pAhciPort->fATAPI ? (pAhciPort->pDrvBlock->pfnSendCmd != NULL) : false;
7426
7427 if (pAhciPort->fATAPI)
7428 {
7429 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 2048;
7430 pAhciPort->PCHSGeometry.cCylinders = 0;
7431 pAhciPort->PCHSGeometry.cHeads = 0;
7432 pAhciPort->PCHSGeometry.cSectors = 0;
7433 LogRel(("AHCI LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pAhciPort->iLUN, pAhciPort->cTotalSectors, (pAhciPort->fATAPIPassthrough ? "enabled" : "disabled")));
7434 }
7435 else
7436 {
7437 pAhciPort->cbSector = pAhciPort->pDrvBlock->pfnGetSectorSize(pAhciPort->pDrvBlock);
7438 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / pAhciPort->cbSector;
7439 rc = pAhciPort->pDrvBlockBios->pfnGetPCHSGeometry(pAhciPort->pDrvBlockBios,
7440 &pAhciPort->PCHSGeometry);
7441 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED)
7442 {
7443 pAhciPort->PCHSGeometry.cCylinders = 0;
7444 pAhciPort->PCHSGeometry.cHeads = 16; /*??*/
7445 pAhciPort->PCHSGeometry.cSectors = 63; /*??*/
7446 }
7447 else if (rc == VERR_PDM_GEOMETRY_NOT_SET)
7448 {
7449 pAhciPort->PCHSGeometry.cCylinders = 0; /* autodetect marker */
7450 rc = VINF_SUCCESS;
7451 }
7452 AssertRC(rc);
7453
7454 if ( pAhciPort->PCHSGeometry.cCylinders == 0
7455 || pAhciPort->PCHSGeometry.cHeads == 0
7456 || pAhciPort->PCHSGeometry.cSectors == 0)
7457 {
7458 uint64_t cCylinders = pAhciPort->cTotalSectors / (16 * 63);
7459 pAhciPort->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
7460 pAhciPort->PCHSGeometry.cHeads = 16;
7461 pAhciPort->PCHSGeometry.cSectors = 63;
7462 /* Set the disk geometry information. Ignore errors. */
7463 pAhciPort->pDrvBlockBios->pfnSetPCHSGeometry(pAhciPort->pDrvBlockBios,
7464 &pAhciPort->PCHSGeometry);
7465 rc = VINF_SUCCESS;
7466 }
7467 LogRel(("AHCI: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n",
7468 pAhciPort->iLUN, pAhciPort->PCHSGeometry.cCylinders,
7469 pAhciPort->PCHSGeometry.cHeads, pAhciPort->PCHSGeometry.cSectors,
7470 pAhciPort->cTotalSectors));
7471 if (pAhciPort->pDrvBlock->pfnDiscard)
7472 LogRel(("AHCI: LUN#%d: Enabled TRIM support\n", pAhciPort->iLUN));
7473 }
7474 return rc;
7475}
7476
7477/**
7478 * Callback employed by ahciR3Suspend and ahciR3PowerOff..
7479 *
7480 * @returns true if we've quiesced, false if we're still working.
7481 * @param pDevIns The device instance.
7482 */
7483static DECLCALLBACK(bool) ahciR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)
7484{
7485 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
7486 return false;
7487
7488 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7489 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
7490 return true;
7491}
7492
7493/**
7494 * Common worker for ahciR3Suspend and ahciR3PowerOff.
7495 */
7496static void ahciR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
7497{
7498 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7499
7500 ASMAtomicWriteBool(&pThis->fSignalIdle, true);
7501 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
7502 PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncSuspendOrPowerOffDone);
7503 else
7504 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
7505}
7506
7507/**
7508 * Suspend notification.
7509 *
7510 * @param pDevIns The device instance data.
7511 */
7512static DECLCALLBACK(void) ahciR3Suspend(PPDMDEVINS pDevIns)
7513{
7514 Log(("ahciR3Suspend\n"));
7515 ahciR3SuspendOrPowerOff(pDevIns);
7516}
7517
7518/**
7519 * Resume notification.
7520 *
7521 * @param pDevIns The device instance data.
7522 */
7523static DECLCALLBACK(void) ahciR3Resume(PPDMDEVINS pDevIns)
7524{
7525 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
7526
7527 /*
7528 * Check if one of the ports has pending tasks.
7529 * Queue a notification item again in this case.
7530 */
7531 for (unsigned i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)
7532 {
7533 PAHCIPort pAhciPort = &pAhci->ahciPort[i];
7534
7535 if (pAhciPort->u32TasksRedo)
7536 {
7537 PDEVPORTNOTIFIERQUEUEITEM pItem = (PDEVPORTNOTIFIERQUEUEITEM)PDMQueueAlloc(pAhci->CTX_SUFF(pNotifierQueue));
7538 AssertMsg(pItem, ("Allocating item for queue failed\n"));
7539
7540 pAhciPort->u32TasksNew |= pAhciPort->u32TasksRedo;
7541 pAhciPort->u32TasksRedo = 0;
7542
7543 Assert(pAhciPort->fRedo);
7544 pAhciPort->fRedo = false;
7545
7546 pItem->iPort = pAhci->ahciPort[i].iLUN;
7547 PDMQueueInsert(pAhci->CTX_SUFF(pNotifierQueue), (PPDMQUEUEITEMCORE)pItem);
7548 }
7549 }
7550
7551 Log(("%s:\n", __FUNCTION__));
7552}
7553
7554/**
7555 * Initializes the VPD data of a attached device.
7556 *
7557 * @returns VBox status code.
7558 * @param pDevIns The device instance.
7559 * @param pAhciPort The attached device.
7560 * @param szName Name of the port to get the CFGM node.
7561 */
7562static int ahciR3VpdInit(PPDMDEVINS pDevIns, PAHCIPort pAhciPort, const char *pszName)
7563{
7564 int rc = VINF_SUCCESS;
7565 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
7566
7567 /* Generate a default serial number. */
7568 char szSerial[AHCI_SERIAL_NUMBER_LENGTH+1];
7569 RTUUID Uuid;
7570
7571 if (pAhciPort->pDrvBlock)
7572 rc = pAhciPort->pDrvBlock->pfnGetUuid(pAhciPort->pDrvBlock, &Uuid);
7573 else
7574 RTUuidClear(&Uuid);
7575
7576 if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
7577 {
7578 /* Generate a predictable serial for drives which don't have a UUID. */
7579 RTStrPrintf(szSerial, sizeof(szSerial), "VB%x-1a2b3c4d",
7580 pAhciPort->iLUN);
7581 }
7582 else
7583 RTStrPrintf(szSerial, sizeof(szSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
7584
7585 /* Get user config if present using defaults otherwise. */
7586 PCFGMNODE pCfgNode = CFGMR3GetChild(pDevIns->pCfg, pszName);
7587 rc = CFGMR3QueryStringDef(pCfgNode, "SerialNumber", pAhciPort->szSerialNumber, sizeof(pAhciPort->szSerialNumber),
7588 szSerial);
7589 if (RT_FAILURE(rc))
7590 {
7591 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
7592 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
7593 N_("AHCI configuration error: \"SerialNumber\" is longer than 20 bytes"));
7594 return PDMDEV_SET_ERROR(pDevIns, rc,
7595 N_("AHCI configuration error: failed to read \"SerialNumber\" as string"));
7596 }
7597
7598 rc = CFGMR3QueryStringDef(pCfgNode, "FirmwareRevision", pAhciPort->szFirmwareRevision, sizeof(pAhciPort->szFirmwareRevision),
7599 "1.0");
7600 if (RT_FAILURE(rc))
7601 {
7602 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
7603 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
7604 N_("AHCI configuration error: \"FirmwareRevision\" is longer than 8 bytes"));
7605 return PDMDEV_SET_ERROR(pDevIns, rc,
7606 N_("AHCI configuration error: failed to read \"FirmwareRevision\" as string"));
7607 }
7608
7609 rc = CFGMR3QueryStringDef(pCfgNode, "ModelNumber", pAhciPort->szModelNumber, sizeof(pAhciPort->szModelNumber),
7610 pAhciPort->fATAPI ? "VBOX CD-ROM" : "VBOX HARDDISK");
7611 if (RT_FAILURE(rc))
7612 {
7613 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
7614 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
7615 N_("AHCI configuration error: \"ModelNumber\" is longer than 40 bytes"));
7616 return PDMDEV_SET_ERROR(pDevIns, rc,
7617 N_("AHCI configuration error: failed to read \"ModelNumber\" as string"));
7618 }
7619
7620 rc = CFGMR3QueryBoolDef(pCfgNode, "NonRotationalMedium", &pAhciPort->fNonRotational, false);
7621 if (RT_FAILURE(rc))
7622 return PDMDEV_SET_ERROR(pDevIns, rc,
7623 N_("AHCI configuration error: failed to read \"NonRotationalMedium\" as boolean"));
7624
7625 rc = CFGMR3QueryU8Def(pCfgNode, "LogicalSectorsPerPhysical", &pAhciPort->cLogSectorsPerPhysicalExp, 0);
7626 if (RT_FAILURE(rc))
7627 return PDMDEV_SET_ERROR(pDevIns, rc,
7628 N_("AHCI configuration error: failed to read \"LogicalSectorsPerPhysical\" as integer"));
7629 if (pAhciPort->cLogSectorsPerPhysicalExp >= 16)
7630 return PDMDEV_SET_ERROR(pDevIns, rc,
7631 N_("AHCI configuration error: \"LogicalSectorsPerPhysical\" must be between 0 and 15"));
7632
7633 /* There are three other identification strings for CD drives used for INQUIRY */
7634 if (pAhciPort->fATAPI)
7635 {
7636 rc = CFGMR3QueryStringDef(pCfgNode, "ATAPIVendorId", pAhciPort->szInquiryVendorId, sizeof(pAhciPort->szInquiryVendorId),
7637 "VBOX");
7638 if (RT_FAILURE(rc))
7639 {
7640 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
7641 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
7642 N_("AHCI configuration error: \"ATAPIVendorId\" is longer than 16 bytes"));
7643 return PDMDEV_SET_ERROR(pDevIns, rc,
7644 N_("AHCI configuration error: failed to read \"ATAPIVendorId\" as string"));
7645 }
7646
7647 rc = CFGMR3QueryStringDef(pCfgNode, "ATAPIProductId", pAhciPort->szInquiryProductId, sizeof(pAhciPort->szInquiryProductId),
7648 "CD-ROM");
7649 if (RT_FAILURE(rc))
7650 {
7651 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
7652 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
7653 N_("AHCI configuration error: \"ATAPIProductId\" is longer than 16 bytes"));
7654 return PDMDEV_SET_ERROR(pDevIns, rc,
7655 N_("AHCI configuration error: failed to read \"ATAPIProductId\" as string"));
7656 }
7657
7658 rc = CFGMR3QueryStringDef(pCfgNode, "ATAPIRevision", pAhciPort->szInquiryRevision, sizeof(pAhciPort->szInquiryRevision),
7659 "1.0");
7660 if (RT_FAILURE(rc))
7661 {
7662 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
7663 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
7664 N_("AHCI configuration error: \"ATAPIRevision\" is longer than 4 bytes"));
7665 return PDMDEV_SET_ERROR(pDevIns, rc,
7666 N_("AHCI configuration error: failed to read \"ATAPIRevision\" as string"));
7667 }
7668 }
7669
7670 return rc;
7671}
7672
7673
7674/**
7675 * Detach notification.
7676 *
7677 * One harddisk at one port has been unplugged.
7678 * The VM is suspended at this point.
7679 *
7680 * @param pDevIns The device instance.
7681 * @param iLUN The logical unit which is being detached.
7682 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
7683 */
7684static DECLCALLBACK(void) ahciR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
7685{
7686 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
7687 PAHCIPort pAhciPort = &pAhci->ahciPort[iLUN];
7688 int rc = VINF_SUCCESS;
7689
7690 Log(("%s:\n", __FUNCTION__));
7691
7692 AssertMsg(iLUN < pAhci->cPortsImpl, ("iLUN=%u", iLUN));
7693 AssertMsgReturnVoid( pAhciPort->fHotpluggable
7694 || (fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
7695 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN));
7696
7697
7698 if (pAhciPort->pAsyncIOThread)
7699 {
7700 int rcThread;
7701 /* Destroy the thread. */
7702 rc = PDMR3ThreadDestroy(pAhciPort->pAsyncIOThread, &rcThread);
7703 if (RT_FAILURE(rc) || RT_FAILURE(rcThread))
7704 AssertMsgFailed(("%s Failed to destroy async IO thread rc=%Rrc rcThread=%Rrc\n", __FUNCTION__, rc, rcThread));
7705
7706 pAhciPort->pAsyncIOThread = NULL;
7707 }
7708
7709 if (pAhciPort->fATAPI)
7710 ahciMediumRemoved(pAhciPort);
7711
7712 if (!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG))
7713 {
7714 /*
7715 * Inform the guest about the removed device.
7716 */
7717 pAhciPort->regSSTS = 0;
7718 pAhciPort->regSIG = 0;
7719 /*
7720 * Clear CR bit too to prevent submission of new commands when CI is written
7721 * (AHCI Spec 1.2: 7.4 Interaction of the Command List and Port Change Status).
7722 */
7723 ASMAtomicAndU32(&pAhciPort->regCMD, ~(AHCI_PORT_CMD_CPS | AHCI_PORT_CMD_CR));
7724 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS);
7725 ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_X | AHCI_PORT_SERR_N);
7726 if ( (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
7727 || (pAhciPort->regIE & AHCI_PORT_IE_PCE)
7728 || (pAhciPort->regIE & AHCI_PORT_IE_PRCE))
7729 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
7730 }
7731
7732 /*
7733 * Zero some important members.
7734 */
7735 pAhciPort->pDrvBase = NULL;
7736 pAhciPort->pDrvBlock = NULL;
7737 pAhciPort->pDrvBlockAsync = NULL;
7738 pAhciPort->pDrvBlockBios = NULL;
7739}
7740
7741/**
7742 * Attach command.
7743 *
7744 * This is called when we change block driver for one port.
7745 * The VM is suspended at this point.
7746 *
7747 * @returns VBox status code.
7748 * @param pDevIns The device instance.
7749 * @param iLUN The logical unit which is being detached.
7750 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
7751 */
7752static DECLCALLBACK(int) ahciR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
7753{
7754 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7755 PAHCIPort pAhciPort = &pThis->ahciPort[iLUN];
7756 int rc;
7757
7758 Log(("%s:\n", __FUNCTION__));
7759
7760 /* the usual paranoia */
7761 AssertMsg(iLUN < pThis->cPortsImpl, ("iLUN=%u", iLUN));
7762 AssertRelease(!pAhciPort->pDrvBase);
7763 AssertRelease(!pAhciPort->pDrvBlock);
7764 AssertRelease(!pAhciPort->pDrvBlockAsync);
7765 Assert(pAhciPort->iLUN == iLUN);
7766
7767 AssertMsgReturn( pAhciPort->fHotpluggable
7768 || (fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG),
7769 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN),
7770 VERR_INVALID_PARAMETER);
7771
7772 /*
7773 * Try attach the block device and get the interfaces,
7774 * required as well as optional.
7775 */
7776 rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, NULL);
7777 if (RT_SUCCESS(rc))
7778 {
7779 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort);
7780
7781 /*
7782 * In case there is a medium inserted.
7783 */
7784 ahciMediumInserted(pAhciPort);
7785 ahciMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN);
7786 }
7787 else
7788 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", pAhciPort->iLUN, rc));
7789
7790 if (RT_FAILURE(rc))
7791 {
7792 pAhciPort->pDrvBase = NULL;
7793 pAhciPort->pDrvBlock = NULL;
7794 }
7795 else
7796 {
7797 char szName[24];
7798 RTStrPrintf(szName, sizeof(szName), "Port%d", iLUN);
7799
7800 if ( pAhciPort->pDrvBlockAsync
7801 && !pAhciPort->fATAPI)
7802 pAhciPort->fAsyncInterface = true;
7803 else
7804 pAhciPort->fAsyncInterface = false;
7805
7806 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
7807 if (RT_FAILURE(rc))
7808 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
7809 N_("AHCI: Failed to create SUP event semaphore"));
7810
7811 /* Create the async IO thread. */
7812 rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop, ahciAsyncIOLoopWakeUp, 0,
7813 RTTHREADTYPE_IO, szName);
7814 if (RT_FAILURE(rc))
7815 return rc;
7816
7817 /*
7818 * Init vendor product data.
7819 */
7820 if (RT_SUCCESS(rc))
7821 rc = ahciR3VpdInit(pDevIns, pAhciPort, szName);
7822
7823 /* Inform the guest about the added device in case of hotplugging. */
7824 if ( RT_SUCCESS(rc)
7825 && !(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG))
7826 {
7827 AssertMsgReturn(pAhciPort->fHotpluggable,
7828 ("AHCI: Port %d is not marked hotpluggable\n", pAhciPort->iLUN),
7829 VERR_NOT_SUPPORTED);
7830
7831 /*
7832 * Initialize registers
7833 */
7834 ASMAtomicOrU32(&pAhciPort->regCMD, AHCI_PORT_CMD_CPS);
7835 ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_CPDS | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS);
7836 ASMAtomicOrU32(&pAhciPort->regSERR, AHCI_PORT_SERR_X | AHCI_PORT_SERR_N);
7837
7838 if (pAhciPort->fATAPI)
7839 pAhciPort->regSIG = AHCI_PORT_SIG_ATAPI;
7840 else
7841 pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
7842 pAhciPort->regSSTS = (0x01 << 8) | /* Interface is active. */
7843 (0x02 << 4) | /* Generation 2 (3.0GBps) speed. */
7844 (0x03 << 0); /* Device detected and communication established. */
7845
7846 if ( (pAhciPort->regIE & AHCI_PORT_IE_CPDE)
7847 || (pAhciPort->regIE & AHCI_PORT_IE_PCE)
7848 || (pAhciPort->regIE & AHCI_PORT_IE_PRCE))
7849 ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
7850 }
7851
7852 }
7853
7854 return rc;
7855}
7856
7857/**
7858 * Common reset worker.
7859 *
7860 * @param pDevIns The device instance data.
7861 */
7862static int ahciR3ResetCommon(PPDMDEVINS pDevIns, bool fConstructor)
7863{
7864 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);
7865
7866 ahciHBAReset(pAhci);
7867
7868 /* Hardware reset for the ports. */
7869 for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)
7870 ahciPortHwReset(&pAhci->ahciPort[i]);
7871 return VINF_SUCCESS;
7872}
7873
7874/**
7875 * Callback employed by ahciR3Reset.
7876 *
7877 * @returns true if we've quiesced, false if we're still working.
7878 * @param pDevIns The device instance.
7879 */
7880static DECLCALLBACK(bool) ahciR3IsAsyncResetDone(PPDMDEVINS pDevIns)
7881{
7882 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7883
7884 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
7885 return false;
7886 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
7887
7888 ahciR3ResetCommon(pDevIns, false /*fConstructor*/);
7889 return true;
7890}
7891
7892/**
7893 * Reset notification.
7894 *
7895 * @param pDevIns The device instance data.
7896 */
7897static DECLCALLBACK(void) ahciR3Reset(PPDMDEVINS pDevIns)
7898{
7899 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7900
7901 ASMAtomicWriteBool(&pThis->fSignalIdle, true);
7902 if (!ahciR3AllAsyncIOIsFinished(pDevIns))
7903 PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncResetDone);
7904 else
7905 {
7906 ASMAtomicWriteBool(&pThis->fSignalIdle, false);
7907 ahciR3ResetCommon(pDevIns, false /*fConstructor*/);
7908 }
7909}
7910
7911/**
7912 * Poweroff notification.
7913 *
7914 * @param pDevIns Pointer to the device instance
7915 */
7916static DECLCALLBACK(void) ahciR3PowerOff(PPDMDEVINS pDevIns)
7917{
7918 Log(("achiR3PowerOff\n"));
7919 ahciR3SuspendOrPowerOff(pDevIns);
7920}
7921
7922/**
7923 * Destroy a driver instance.
7924 *
7925 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
7926 * resources can be freed correctly.
7927 *
7928 * @param pDevIns The device instance data.
7929 */
7930static DECLCALLBACK(int) ahciR3Destruct(PPDMDEVINS pDevIns)
7931{
7932 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7933 int rc = VINF_SUCCESS;
7934 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
7935
7936 /*
7937 * At this point the async I/O thread is suspended and will not enter
7938 * this module again. So, no coordination is needed here and PDM
7939 * will take care of terminating and cleaning up the thread.
7940 */
7941 if (PDMCritSectIsInitialized(&pThis->lock))
7942 {
7943 TMR3TimerDestroy(pThis->CTX_SUFF(pHbaCccTimer));
7944 pThis->CTX_SUFF(pHbaCccTimer) = NULL;
7945
7946 Log(("%s: Destruct every port\n", __FUNCTION__));
7947 for (unsigned iActPort = 0; iActPort < pThis->cPortsImpl; iActPort++)
7948 {
7949 PAHCIPort pAhciPort = &pThis->ahciPort[iActPort];
7950
7951 if (pAhciPort->hEvtProcess != NIL_SUPSEMEVENT)
7952 {
7953 SUPSemEventClose(pThis->pSupDrvSession, pAhciPort->hEvtProcess);
7954 pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
7955 }
7956
7957 /* Free all cached tasks. */
7958 for (uint32_t i = 0; i < AHCI_NR_COMMAND_SLOTS; i++)
7959 if (pAhciPort->aCachedTasks[i])
7960 {
7961 RTMemFree(pAhciPort->aCachedTasks[i]);
7962 pAhciPort->aCachedTasks[i] = NULL;
7963 }
7964 }
7965
7966 PDMR3CritSectDelete(&pThis->lock);
7967 }
7968
7969 return rc;
7970}
7971
7972/**
7973 * @interface_method_impl{PDMDEVREG,pfnConstruct}
7974 */
7975static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
7976{
7977 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);
7978 PPDMIBASE pBase;
7979 int rc = VINF_SUCCESS;
7980 unsigned i = 0;
7981 bool fGCEnabled = false;
7982 bool fR0Enabled = false;
7983 uint32_t cbTotalBufferSize = 0;
7984 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
7985
7986 LogFlowFunc(("pThis=%#p\n", pThis));
7987
7988 /*
7989 * Validate and read configuration.
7990 */
7991 if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0"
7992 "R0Enabled\0"
7993 "PrimaryMaster\0"
7994 "PrimarySlave\0"
7995 "SecondaryMaster\0"
7996 "SecondarySlave\0"
7997 "PortCount\0"
7998 "UseAsyncInterfaceIfAvailable\0"
7999 "Bootable\0"
8000 "CmdSlotsAvail\0"))
8001 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
8002 N_("AHCI configuration error: unknown option specified"));
8003
8004 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fGCEnabled, true);
8005 if (RT_FAILURE(rc))
8006 return PDMDEV_SET_ERROR(pDevIns, rc,
8007 N_("AHCI configuration error: failed to read GCEnabled as boolean"));
8008 Log(("%s: fGCEnabled=%d\n", __FUNCTION__, fGCEnabled));
8009
8010 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
8011 if (RT_FAILURE(rc))
8012 return PDMDEV_SET_ERROR(pDevIns, rc,
8013 N_("AHCI configuration error: failed to read R0Enabled as boolean"));
8014 Log(("%s: fR0Enabled=%d\n", __FUNCTION__, fR0Enabled));
8015
8016 rc = CFGMR3QueryU32Def(pCfg, "PortCount", &pThis->cPortsImpl, AHCI_MAX_NR_PORTS_IMPL);
8017 if (RT_FAILURE(rc))
8018 return PDMDEV_SET_ERROR(pDevIns, rc,
8019 N_("AHCI configuration error: failed to read PortCount as integer"));
8020 Log(("%s: cPortsImpl=%u\n", __FUNCTION__, pThis->cPortsImpl));
8021 if (pThis->cPortsImpl > AHCI_MAX_NR_PORTS_IMPL)
8022 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
8023 N_("AHCI configuration error: PortCount=%u should not exceed %u"),
8024 pThis->cPortsImpl, AHCI_MAX_NR_PORTS_IMPL);
8025 if (pThis->cPortsImpl < 1)
8026 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
8027 N_("AHCI configuration error: PortCount=%u should be at least 1"),
8028 pThis->cPortsImpl);
8029
8030 rc = CFGMR3QueryBoolDef(pCfg, "UseAsyncInterfaceIfAvailable", &pThis->fUseAsyncInterfaceIfAvailable, true);
8031 if (RT_FAILURE(rc))
8032 return PDMDEV_SET_ERROR(pDevIns, rc,
8033 N_("AHCI configuration error: failed to read UseAsyncInterfaceIfAvailable as boolean"));
8034
8035 rc = CFGMR3QueryBoolDef(pCfg, "Bootable", &pThis->fBootable, true);
8036 if (RT_FAILURE(rc))
8037 return PDMDEV_SET_ERROR(pDevIns, rc,
8038 N_("AHCI configuration error: failed to read Bootable as boolean"));
8039
8040 rc = CFGMR3QueryU32Def(pCfg, "CmdSlotsAvail", &pThis->cCmdSlotsAvail, AHCI_NR_COMMAND_SLOTS);
8041 if (RT_FAILURE(rc))
8042 return PDMDEV_SET_ERROR(pDevIns, rc,
8043 N_("AHCI configuration error: failed to read CmdSlotsAvail as integer"));
8044 Log(("%s: cCmdSlotsAvail=%u\n", __FUNCTION__, pThis->cCmdSlotsAvail));
8045 if (pThis->cCmdSlotsAvail > AHCI_NR_COMMAND_SLOTS)
8046 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
8047 N_("AHCI configuration error: CmdSlotsAvail=%u should not exceed %u"),
8048 pThis->cPortsImpl, AHCI_NR_COMMAND_SLOTS);
8049 if (pThis->cCmdSlotsAvail < 1)
8050 return PDMDevHlpVMSetError(pDevIns, VERR_INVALID_PARAMETER, RT_SRC_POS,
8051 N_("AHCI configuration error: CmdSlotsAvail=%u should be at least 1"),
8052 pThis->cCmdSlotsAvail);
8053
8054 /*
8055 * Initialize the instance data (everything touched by the destructor need
8056 * to be initialized here!).
8057 */
8058 pThis->fR0Enabled = fR0Enabled;
8059 pThis->fGCEnabled = fGCEnabled;
8060 pThis->pDevInsR3 = pDevIns;
8061 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
8062 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
8063 pThis->pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns);
8064
8065 PCIDevSetVendorId (&pThis->dev, 0x8086); /* Intel */
8066 PCIDevSetDeviceId (&pThis->dev, 0x2829); /* ICH-8M */
8067 PCIDevSetCommand (&pThis->dev, 0x0000);
8068#ifdef VBOX_WITH_MSI_DEVICES
8069 PCIDevSetStatus (&pThis->dev, VBOX_PCI_STATUS_CAP_LIST);
8070 PCIDevSetCapabilityList(&pThis->dev, 0x80);
8071#else
8072 PCIDevSetCapabilityList(&pThis->dev, 0x70);
8073#endif
8074 PCIDevSetRevisionId (&pThis->dev, 0x02);
8075 PCIDevSetClassProg (&pThis->dev, 0x01);
8076 PCIDevSetClassSub (&pThis->dev, 0x06);
8077 PCIDevSetClassBase (&pThis->dev, 0x01);
8078 PCIDevSetBaseAddress (&pThis->dev, 5, false, false, false, 0x00000000);
8079
8080 PCIDevSetInterruptLine(&pThis->dev, 0x00);
8081 PCIDevSetInterruptPin (&pThis->dev, 0x01);
8082
8083 pThis->dev.config[0x70] = VBOX_PCI_CAP_ID_PM; /* Capability ID: PCI Power Management Interface */
8084 pThis->dev.config[0x71] = 0xa8; /* next */
8085 pThis->dev.config[0x72] = 0x03; /* version ? */
8086
8087 pThis->dev.config[0x90] = 0x40; /* AHCI mode. */
8088 pThis->dev.config[0x92] = 0x3f;
8089 pThis->dev.config[0x94] = 0x80;
8090 pThis->dev.config[0x95] = 0x01;
8091 pThis->dev.config[0x97] = 0x78;
8092
8093 pThis->dev.config[0xa8] = 0x12; /* SATACR capability */
8094 pThis->dev.config[0xa9] = 0x00; /* next */
8095 PCIDevSetWord(&pThis->dev, 0xaa, 0x0010); /* Revision */
8096 PCIDevSetDWord(&pThis->dev, 0xac, 0x00000028); /* SATA Capability Register 1 */
8097
8098 pThis->cThreadsActive = 0;
8099
8100 /* Initialize port members. */
8101 for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
8102 {
8103 PAHCIPort pAhciPort = &pThis->ahciPort[i];
8104 pAhciPort->pDevInsR3 = pDevIns;
8105 pAhciPort->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
8106 pAhciPort->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
8107 pAhciPort->iLUN = i;
8108 pAhciPort->pAhciR3 = pThis;
8109 pAhciPort->pAhciR0 = PDMINS_2_DATA_R0PTR(pDevIns);
8110 pAhciPort->pAhciRC = PDMINS_2_DATA_RCPTR(pDevIns);
8111 pAhciPort->Led.u32Magic = PDMLED_MAGIC;
8112 pAhciPort->pDrvBase = NULL;
8113 pAhciPort->pAsyncIOThread = NULL;
8114 pAhciPort->hEvtProcess = NIL_SUPSEMEVENT;
8115 pAhciPort->fHotpluggable = true;
8116 }
8117
8118 /*
8119 * Init locks, using explicit locking where necessary.
8120 */
8121 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
8122 if (RT_FAILURE(rc))
8123 return rc;
8124
8125 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->lock, RT_SRC_POS, "AHCI#%u", iInstance);
8126 if (RT_FAILURE(rc))
8127 {
8128 Log(("%s: Failed to create critical section.\n", __FUNCTION__));
8129 return rc;
8130 }
8131
8132 /*
8133 * Register the PCI device, it's I/O regions.
8134 */
8135 rc = PDMDevHlpPCIRegister (pDevIns, &pThis->dev);
8136 if (RT_FAILURE(rc))
8137 return rc;
8138
8139#ifdef VBOX_WITH_MSI_DEVICES
8140 PDMMSIREG MsiReg;
8141 RT_ZERO(MsiReg);
8142 MsiReg.cMsiVectors = 1;
8143 MsiReg.iMsiCapOffset = 0x80;
8144 MsiReg.iMsiNextOffset = 0x70;
8145 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &MsiReg);
8146 if (RT_FAILURE(rc))
8147 {
8148 LogRel(("Chipset cannot do MSI: %Rrc\n", rc));
8149 PCIDevSetCapabilityList(&pThis->dev, 0x70);
8150 /* That's OK, we can work without MSI */
8151 }
8152#endif
8153
8154 /*
8155 * Solaris 10 U5 fails to map the AHCI register space when the sets (0..5) for the legacy
8156 * IDE registers are not available.
8157 * We set up "fake" entries in the PCI configuration register.
8158 * That means they are available but read and writes from/to them have no effect.
8159 * No guest should access them anyway because the controller is marked as AHCI in the Programming interface
8160 * and we don't have an option to change to IDE emulation (real hardware provides an option in the BIOS
8161 * to switch to it which also changes device Id and other things in the PCI configuration space).
8162 */
8163 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
8164 if (RT_FAILURE(rc))
8165 return PDMDEV_SET_ERROR(pDevIns, rc,
8166 N_("AHCI cannot register PCI I/O region"));
8167
8168 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 1, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
8169 if (RT_FAILURE(rc))
8170 return PDMDEV_SET_ERROR(pDevIns, rc,
8171 N_("AHCI cannot register PCI I/O region"));
8172
8173 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, 8, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
8174 if (RT_FAILURE(rc))
8175 return PDMDEV_SET_ERROR(pDevIns, rc,
8176 N_("AHCI cannot register PCI I/O region"));
8177
8178 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 3, 1, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap);
8179 if (RT_FAILURE(rc))
8180 return PDMDEV_SET_ERROR(pDevIns, rc,
8181 N_("AHCI cannot register PCI I/O region"));
8182
8183 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 4, 0x10, PCI_ADDRESS_SPACE_IO, ahciR3IdxDataIORangeMap);
8184 if (RT_FAILURE(rc))
8185 return PDMDEV_SET_ERROR(pDevIns, rc,
8186 N_("AHCI cannot register PCI I/O region for BMDMA"));
8187
8188 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 5, 4352, PCI_ADDRESS_SPACE_MEM, ahciR3MMIOMap);
8189 if (RT_FAILURE(rc))
8190 return PDMDEV_SET_ERROR(pDevIns, rc,
8191 N_("AHCI cannot register PCI memory region for registers"));
8192
8193 /* Create the timer for command completion coalescing feature. */
8194 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, ahciCccTimer, pThis,
8195 TMTIMER_FLAGS_NO_CRIT_SECT, "AHCI CCC Timer", &pThis->pHbaCccTimerR3);
8196 if (RT_FAILURE(rc))
8197 {
8198 AssertMsgFailed(("pfnTMTimerCreate -> %Rrc\n", rc));
8199 return rc;
8200 }
8201 pThis->pHbaCccTimerR0 = TMTimerR0Ptr(pThis->pHbaCccTimerR3);
8202 pThis->pHbaCccTimerRC = TMTimerRCPtr(pThis->pHbaCccTimerR3);
8203
8204 /* Status LUN. */
8205 pThis->IBase.pfnQueryInterface = ahciR3Status_QueryInterface;
8206 pThis->ILeds.pfnQueryStatusLed = ahciR3Status_QueryStatusLed;
8207
8208 /*
8209 * Create the notification queue.
8210 *
8211 * We need 2 items for every port because of SMP races.
8212 */
8213 rc = PDMDevHlpQueueCreate(pDevIns, sizeof(DEVPORTNOTIFIERQUEUEITEM), AHCI_MAX_NR_PORTS_IMPL * 2, 0,
8214 ahciNotifyQueueConsumer, true, "AHCI-Xmit", &pThis->pNotifierQueueR3);
8215 if (RT_FAILURE(rc))
8216 return rc;
8217 pThis->pNotifierQueueR0 = PDMQueueR0Ptr(pThis->pNotifierQueueR3);
8218 pThis->pNotifierQueueRC = PDMQueueRCPtr(pThis->pNotifierQueueR3);
8219
8220 /* Initialize static members on every port. */
8221 for (i = 0; i < AHCI_MAX_NR_PORTS_IMPL; i++)
8222 {
8223 PAHCIPort pAhciPort = &pThis->ahciPort[i];
8224
8225 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatDMA, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
8226 "Number of DMA transfers.", "/Devices/SATA%d/Port%d/DMA", iInstance, i);
8227 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
8228 "Amount of data read.", "/Devices/SATA%d/Port%d/ReadBytes", iInstance, i);
8229 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
8230 "Amount of data written.", "/Devices/SATA%d/Port%d/WrittenBytes", iInstance, i);
8231 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatIORequestsPerSecond, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
8232 "Number of processed I/O requests per second.", "/Devices/SATA%d/Port%d/IORequestsPerSecond", iInstance, i);
8233#ifdef VBOX_WITH_STATISTICS
8234 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatProfileProcessTime, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_NS_PER_CALL,
8235 "Amount of time to process one request.", "/Devices/SATA%d/Port%d/ProfileProcessTime", iInstance, i);
8236 PDMDevHlpSTAMRegisterF(pDevIns, &pAhciPort->StatProfileReadWrite, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_NS_PER_CALL,
8237 "Amount of time for the read/write operation to complete.", "/Devices/SATA%d/Port%d/ProfileReadWrite", iInstance, i);
8238#endif
8239
8240 ahciPortHwReset(pAhciPort);
8241 }
8242
8243 /* Attach drivers to every available port. */
8244 for (i = 0; i < pThis->cPortsImpl; i++)
8245 {
8246 char szName[24];
8247 RTStrPrintf(szName, sizeof(szName), "Port%u", i);
8248
8249 PAHCIPort pAhciPort = &pThis->ahciPort[i];
8250 /*
8251 * Init interfaces.
8252 */
8253 pAhciPort->IBase.pfnQueryInterface = ahciR3PortQueryInterface;
8254 pAhciPort->IPortAsync.pfnTransferCompleteNotify = ahciR3TransferCompleteNotify;
8255 pAhciPort->IPort.pfnQueryDeviceLocation = ahciR3PortQueryDeviceLocation;
8256 pAhciPort->IMountNotify.pfnMountNotify = ahciR3MountNotify;
8257 pAhciPort->IMountNotify.pfnUnmountNotify = ahciR3UnmountNotify;
8258
8259 /* Query per port configuration options if available. */
8260 PCFGMNODE pCfgPort = CFGMR3GetChild(pDevIns->pCfg, szName);
8261 if (pCfgPort)
8262 {
8263 rc = CFGMR3QueryBoolDef(pCfgPort, "Hotpluggable", &pAhciPort->fHotpluggable, true);
8264 if (RT_FAILURE(rc))
8265 return PDMDEV_SET_ERROR(pDevIns, rc,
8266 N_("AHCI configuration error: failed to read Hotpluggable as boolean"));
8267 }
8268
8269 /*
8270 * Attach the block driver
8271 */
8272 rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, szName);
8273 if (RT_SUCCESS(rc))
8274 {
8275 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort);
8276 if (RT_FAILURE(rc))
8277 {
8278 Log(("%s: Failed to configure the %s.\n", __FUNCTION__, szName));
8279 return rc;
8280 }
8281
8282 /* Mark that a device is present on that port */
8283 if (i < 6)
8284 pThis->dev.config[0x93] |= (1 << i);
8285
8286 /*
8287 * Init vendor product data.
8288 */
8289 rc = ahciR3VpdInit(pDevIns, pAhciPort, szName);
8290 if (RT_FAILURE(rc))
8291 return rc;
8292
8293 /*
8294 * If the new async interface is available we use a PDMQueue to transmit
8295 * the requests into R3.
8296 * Otherwise we use a event semaphore and a async I/O thread which processes them.
8297 */
8298 if (pAhciPort->pDrvBlockAsync && pThis->fUseAsyncInterfaceIfAvailable)
8299 {
8300 LogRel(("AHCI: LUN#%d: using async I/O\n", pAhciPort->iLUN));
8301 pAhciPort->fAsyncInterface = true;
8302 }
8303 else
8304 {
8305 LogRel(("AHCI: LUN#%d: using normal I/O\n", pAhciPort->iLUN));
8306 pAhciPort->fAsyncInterface = false;
8307 }
8308
8309 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
8310 if (RT_FAILURE(rc))
8311 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
8312 N_("AHCI: Failed to create SUP event semaphore"));
8313
8314 rc = PDMDevHlpThreadCreate(pDevIns, &pAhciPort->pAsyncIOThread, pAhciPort, ahciAsyncIOLoop,
8315 ahciAsyncIOLoopWakeUp, 0, RTTHREADTYPE_IO, szName);
8316 if (RT_FAILURE(rc))
8317 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
8318 N_("AHCI: Failed to create worker thread %s"), szName);
8319 }
8320 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
8321 {
8322 pAhciPort->pDrvBase = NULL;
8323 rc = VINF_SUCCESS;
8324 LogRel(("%s: no driver attached\n", szName));
8325 }
8326 else
8327 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
8328 N_("AHCI: Failed to attach drive to %s"), szName);
8329 }
8330
8331 /*
8332 * Attach status driver (optional).
8333 */
8334 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThis->IBase, &pBase, "Status Port");
8335 if (RT_SUCCESS(rc))
8336 {
8337 pThis->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS);
8338 pThis->pMediaNotify = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIANOTIFY);
8339 }
8340 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
8341 {
8342 AssertMsgFailed(("Failed to attach to status driver. rc=%Rrc\n", rc));
8343 return PDMDEV_SET_ERROR(pDevIns, rc, N_("AHCI cannot attach to status driver"));
8344 }
8345 rc = PDMDevHlpSSMRegisterEx(pDevIns, AHCI_SAVED_STATE_VERSION, sizeof(*pThis) + cbTotalBufferSize, NULL,
8346 NULL, ahciR3LiveExec, NULL,
8347 ahciR3SavePrep, ahciR3SaveExec, NULL,
8348 ahciR3LoadPrep, ahciR3LoadExec, NULL);
8349 if (RT_FAILURE(rc))
8350 return rc;
8351
8352 /*
8353 * Register the info item.
8354 */
8355 char szTmp[128];
8356 RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance);
8357 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "AHCI info", ahciR3Info);
8358
8359 return ahciR3ResetCommon(pDevIns, true /*fConstructor*/);
8360}
8361
8362/**
8363 * The device registration structure.
8364 */
8365const PDMDEVREG g_DeviceAHCI =
8366{
8367 /* u32Version */
8368 PDM_DEVREG_VERSION,
8369 /* szName */
8370 "ahci",
8371 /* szRCMod */
8372 "VBoxDDGC.gc",
8373 /* szR0Mod */
8374 "VBoxDDR0.r0",
8375 /* pszDescription */
8376 "Intel AHCI controller.\n",
8377 /* fFlags */
8378 PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0 |
8379 PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION |
8380 PDM_DEVREG_FLAGS_FIRST_RESET_NOTIFICATION,
8381 /* fClass */
8382 PDM_DEVREG_CLASS_STORAGE,
8383 /* cMaxInstances */
8384 ~0U,
8385 /* cbInstance */
8386 sizeof(AHCI),
8387 /* pfnConstruct */
8388 ahciR3Construct,
8389 /* pfnDestruct */
8390 ahciR3Destruct,
8391 /* pfnRelocate */
8392 ahciR3Relocate,
8393 /* pfnMemSetup */
8394 NULL,
8395 /* pfnPowerOn */
8396 NULL,
8397 /* pfnReset */
8398 ahciR3Reset,
8399 /* pfnSuspend */
8400 ahciR3Suspend,
8401 /* pfnResume */
8402 ahciR3Resume,
8403 /* pfnAttach */
8404 ahciR3Attach,
8405 /* pfnDetach */
8406 ahciR3Detach,
8407 /* pfnQueryInterface. */
8408 NULL,
8409 /* pfnInitComplete */
8410 NULL,
8411 /* pfnPowerOff */
8412 ahciR3PowerOff,
8413 /* pfnSoftReset */
8414 NULL,
8415 /* u32VersionEnd */
8416 PDM_DEVREG_VERSION
8417};
8418
8419#endif /* IN_RING3 */
8420#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

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