VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DevATA.cpp@ 92548

Last change on this file since 92548 was 92548, checked in by vboxsync, 3 years ago

DevATA: Removed MODE SENSE (6) support. This is not needed for ATAPI devices and the implementation was broken anyway (see bugref:5869).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 332.2 KB
Line 
1/* $Id: DevATA.cpp 92548 2021-11-22 13:40:52Z vboxsync $ */
2/** @file
3 * VBox storage devices: ATA/ATAPI controller device (disk and cdrom).
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_IDE
23#include <VBox/vmm/pdmdev.h>
24#include <VBox/vmm/pdmstorageifs.h>
25#include <iprt/assert.h>
26#include <iprt/string.h>
27#ifdef IN_RING3
28# include <iprt/mem.h>
29# include <iprt/mp.h>
30# include <iprt/semaphore.h>
31# include <iprt/thread.h>
32# include <iprt/time.h>
33# include <iprt/uuid.h>
34#endif /* IN_RING3 */
35#include <iprt/critsect.h>
36#include <iprt/asm.h>
37#include <VBox/vmm/stam.h>
38#include <VBox/vmm/mm.h>
39#include <VBox/vmm/pgm.h>
40
41#include <VBox/sup.h>
42#include <VBox/AssertGuest.h>
43#include <VBox/scsi.h>
44#include <VBox/scsiinline.h>
45#include <VBox/ata.h>
46
47#include "ATAPIPassthrough.h"
48#include "VBoxDD.h"
49
50
51/*********************************************************************************************************************************
52* Defined Constants And Macros *
53*********************************************************************************************************************************/
54/** Temporary instrumentation for tracking down potential virtual disk
55 * write performance issues. */
56#undef VBOX_INSTRUMENT_DMA_WRITES
57
58/** @name The SSM saved state versions.
59 * @{
60 */
61/** The current saved state version. */
62#define ATA_SAVED_STATE_VERSION 20
63/** The saved state version used by VirtualBox 3.0.
64 * This lacks the config part and has the type at the and. */
65#define ATA_SAVED_STATE_VERSION_VBOX_30 19
66#define ATA_SAVED_STATE_VERSION_WITH_BOOL_TYPE 18
67#define ATA_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE 16
68#define ATA_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS 17
69/** @} */
70
71/** Values read from an empty (with no devices attached) ATA bus. */
72#define ATA_EMPTY_BUS_DATA 0x7F
73#define ATA_EMPTY_BUS_DATA_32 0x7F7F7F7F
74
75/**
76 * Maximum number of sectors to transfer in a READ/WRITE MULTIPLE request.
77 * Set to 1 to disable multi-sector read support. According to the ATA
78 * specification this must be a power of 2 and it must fit in an 8 bit
79 * value. Thus the only valid values are 1, 2, 4, 8, 16, 32, 64 and 128.
80 */
81#define ATA_MAX_MULT_SECTORS 128
82
83/** The maxium I/O buffer size (for sanity). */
84#define ATA_MAX_SECTOR_SIZE _4K
85/** The maxium I/O buffer size (for sanity). */
86#define ATA_MAX_IO_BUFFER_SIZE (ATA_MAX_MULT_SECTORS * ATA_MAX_SECTOR_SIZE)
87
88/** Mask to be applied to all indexing into ATACONTROLLER::aIfs. */
89#define ATA_SELECTED_IF_MASK 1
90
91/**
92 * Fastest PIO mode supported by the drive.
93 */
94#define ATA_PIO_MODE_MAX 4
95/**
96 * Fastest MDMA mode supported by the drive.
97 */
98#define ATA_MDMA_MODE_MAX 2
99/**
100 * Fastest UDMA mode supported by the drive.
101 */
102#define ATA_UDMA_MODE_MAX 6
103
104/** ATAPI sense info size. */
105#define ATAPI_SENSE_SIZE 64
106
107/** The maximum number of release log entries per device. */
108#define MAX_LOG_REL_ERRORS 1024
109
110/* MediaEventStatus */
111#define ATA_EVENT_STATUS_UNCHANGED 0 /**< medium event status not changed */
112#define ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED 1 /**< medium eject requested (eject button pressed) */
113#define ATA_EVENT_STATUS_MEDIA_NEW 2 /**< new medium inserted */
114#define ATA_EVENT_STATUS_MEDIA_REMOVED 3 /**< medium removed */
115#define ATA_EVENT_STATUS_MEDIA_CHANGED 4 /**< medium was removed + new medium was inserted */
116
117/* Media track type */
118#define ATA_MEDIA_TYPE_UNKNOWN 0 /**< unknown CD type */
119#define ATA_MEDIA_NO_DISC 0x70 /**< Door closed, no medium */
120
121/** @defgroup grp_piix3atabmdma PIIX3 ATA Bus Master DMA
122 * @{
123 */
124
125/** @name BM_STATUS
126 * @{
127 */
128/** Currently performing a DMA operation. */
129#define BM_STATUS_DMAING 0x01
130/** An error occurred during the DMA operation. */
131#define BM_STATUS_ERROR 0x02
132/** The DMA unit has raised the IDE interrupt line. */
133#define BM_STATUS_INT 0x04
134/** User-defined bit 0, commonly used to signal that drive 0 supports DMA. */
135#define BM_STATUS_D0DMA 0x20
136/** User-defined bit 1, commonly used to signal that drive 1 supports DMA. */
137#define BM_STATUS_D1DMA 0x40
138/** @} */
139
140/** @name BM_CMD
141 * @{
142 */
143/** Start the DMA operation. */
144#define BM_CMD_START 0x01
145/** Data transfer direction: from device to memory if set. */
146#define BM_CMD_WRITE 0x08
147/** @} */
148
149/** Number of I/O ports per bus-master DMA controller. */
150#define BM_DMA_CTL_IOPORTS 8
151/** Mask corresponding to BM_DMA_CTL_IOPORTS. */
152#define BM_DMA_CTL_IOPORTS_MASK 7
153/** Shift count corresponding to BM_DMA_CTL_IOPORTS. */
154#define BM_DMA_CTL_IOPORTS_SHIFT 3
155
156/** @} */
157
158#define ATADEVSTATE_2_DEVINS(pIf) ( (pIf)->CTX_SUFF(pDevIns) )
159#define CONTROLLER_2_DEVINS(pController) ( (pController)->CTX_SUFF(pDevIns) )
160
161
162/*********************************************************************************************************************************
163* Structures and Typedefs *
164*********************************************************************************************************************************/
165/** @defgroup grp_piix3atabmdma PIIX3 ATA Bus Master DMA
166 * @{
167 */
168/** PIIX3 Bus Master DMA unit state. */
169typedef struct BMDMAState
170{
171 /** Command register. */
172 uint8_t u8Cmd;
173 /** Status register. */
174 uint8_t u8Status;
175 /** Explicit alignment padding. */
176 uint8_t abAlignment[2];
177 /** Address of the MMIO region in the guest's memory space. */
178 RTGCPHYS32 GCPhysAddr;
179} BMDMAState;
180
181/** PIIX3 Bus Master DMA descriptor entry. */
182typedef struct BMDMADesc
183{
184 /** Address of the DMA source/target buffer. */
185 RTGCPHYS32 GCPhysBuffer;
186 /** Size of the DMA source/target buffer. */
187 uint32_t cbBuffer;
188} BMDMADesc;
189/** @} */
190
191
192/**
193 * The shared state of an ATA device.
194 */
195typedef struct ATADEVSTATE
196{
197 /** The I/O buffer.
198 * @note Page aligned in case it helps. */
199 uint8_t abIOBuffer[ATA_MAX_IO_BUFFER_SIZE];
200
201 /** Flag indicating whether the current command uses LBA48 mode. */
202 bool fLBA48;
203 /** Flag indicating whether this drive implements the ATAPI command set. */
204 bool fATAPI;
205 /** Set if this interface has asserted the IRQ. */
206 bool fIrqPending;
207 /** Currently configured number of sectors in a multi-sector transfer. */
208 uint8_t cMultSectors;
209 /** Physical CHS disk geometry (static). */
210 PDMMEDIAGEOMETRY PCHSGeometry;
211 /** Translated CHS disk geometry (variable). */
212 PDMMEDIAGEOMETRY XCHSGeometry;
213 /** Total number of sectors on this disk. */
214 uint64_t cTotalSectors;
215 /** Sector size of the medium. */
216 uint32_t cbSector;
217 /** Number of sectors to transfer per IRQ. */
218 uint32_t cSectorsPerIRQ;
219
220 /** ATA/ATAPI register 1: feature (write-only). */
221 uint8_t uATARegFeature;
222 /** ATA/ATAPI register 1: feature, high order byte. */
223 uint8_t uATARegFeatureHOB;
224 /** ATA/ATAPI register 1: error (read-only). */
225 uint8_t uATARegError;
226 /** ATA/ATAPI register 2: sector count (read/write). */
227 uint8_t uATARegNSector;
228 /** ATA/ATAPI register 2: sector count, high order byte. */
229 uint8_t uATARegNSectorHOB;
230 /** ATA/ATAPI register 3: sector (read/write). */
231 uint8_t uATARegSector;
232 /** ATA/ATAPI register 3: sector, high order byte. */
233 uint8_t uATARegSectorHOB;
234 /** ATA/ATAPI register 4: cylinder low (read/write). */
235 uint8_t uATARegLCyl;
236 /** ATA/ATAPI register 4: cylinder low, high order byte. */
237 uint8_t uATARegLCylHOB;
238 /** ATA/ATAPI register 5: cylinder high (read/write). */
239 uint8_t uATARegHCyl;
240 /** ATA/ATAPI register 5: cylinder high, high order byte. */
241 uint8_t uATARegHCylHOB;
242 /** ATA/ATAPI register 6: select drive/head (read/write). */
243 uint8_t uATARegSelect;
244 /** ATA/ATAPI register 7: status (read-only). */
245 uint8_t uATARegStatus;
246 /** ATA/ATAPI register 7: command (write-only). */
247 uint8_t uATARegCommand;
248 /** ATA/ATAPI drive control register (write-only). */
249 uint8_t uATARegDevCtl;
250
251 /** Currently active transfer mode (MDMA/UDMA) and speed. */
252 uint8_t uATATransferMode;
253 /** Current transfer direction. */
254 uint8_t uTxDir;
255 /** Index of callback for begin transfer. */
256 uint8_t iBeginTransfer;
257 /** Index of callback for source/sink of data. */
258 uint8_t iSourceSink;
259 /** Flag indicating whether the current command transfers data in DMA mode. */
260 bool fDMA;
261 /** Set to indicate that ATAPI transfer semantics must be used. */
262 bool fATAPITransfer;
263
264 /** Total ATA/ATAPI transfer size, shared PIO/DMA. */
265 uint32_t cbTotalTransfer;
266 /** Elementary ATA/ATAPI transfer size, shared PIO/DMA. */
267 uint32_t cbElementaryTransfer;
268 /** Maximum ATAPI elementary transfer size, PIO only. */
269 uint32_t cbPIOTransferLimit;
270 /** ATAPI passthrough transfer size, shared PIO/DMA */
271 uint32_t cbAtapiPassthroughTransfer;
272 /** Current read/write buffer position, shared PIO/DMA. */
273 uint32_t iIOBufferCur;
274 /** First element beyond end of valid buffer content, shared PIO/DMA. */
275 uint32_t iIOBufferEnd;
276 /** Align the following fields correctly. */
277 uint32_t Alignment0;
278
279 /** ATA/ATAPI current PIO read/write transfer position. Not shared with DMA for safety reasons. */
280 uint32_t iIOBufferPIODataStart;
281 /** ATA/ATAPI current PIO read/write transfer end. Not shared with DMA for safety reasons. */
282 uint32_t iIOBufferPIODataEnd;
283
284 /** ATAPI current LBA position. */
285 uint32_t iATAPILBA;
286 /** ATAPI current sector size. */
287 uint32_t cbATAPISector;
288 /** ATAPI current command. */
289 uint8_t abATAPICmd[ATAPI_PACKET_SIZE];
290 /** ATAPI sense data. */
291 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
292 /** HACK: Countdown till we report a newly unmounted drive as mounted. */
293 uint8_t cNotifiedMediaChange;
294 /** The same for GET_EVENT_STATUS for mechanism */
295 volatile uint32_t MediaEventStatus;
296
297 /** Media type if known. */
298 volatile uint32_t MediaTrackType;
299
300 /** The status LED state for this drive. */
301 PDMLED Led;
302
303 /** Size of I/O buffer. */
304 uint32_t cbIOBuffer;
305
306 /*
307 * No data that is part of the saved state after this point!!!!!
308 */
309
310 /** Counter for number of busy status seen in R3 in a row. */
311 uint8_t cBusyStatusHackR3;
312 /** Counter for number of busy status seen in GC/R0 in a row. */
313 uint8_t cBusyStatusHackRZ;
314 /** Defines the R3 yield rate by a mask (power of 2 minus one).
315 * Lower is more agressive. */
316 uint8_t cBusyStatusHackR3Rate;
317 /** Defines the R0/RC yield rate by a mask (power of 2 minus one).
318 * Lower is more agressive. */
319 uint8_t cBusyStatusHackRZRate;
320
321 /** Release statistics: number of ATA DMA commands. */
322 STAMCOUNTER StatATADMA;
323 /** Release statistics: number of ATA PIO commands. */
324 STAMCOUNTER StatATAPIO;
325 /** Release statistics: number of ATAPI PIO commands. */
326 STAMCOUNTER StatATAPIDMA;
327 /** Release statistics: number of ATAPI PIO commands. */
328 STAMCOUNTER StatATAPIPIO;
329#ifdef VBOX_INSTRUMENT_DMA_WRITES
330 /** Release statistics: number of DMA sector writes and the time spent. */
331 STAMPROFILEADV StatInstrVDWrites;
332#endif
333 /** Release statistics: Profiling RTThreadYield calls during status polling. */
334 STAMPROFILEADV StatStatusYields;
335
336 /** Statistics: number of read operations and the time spent reading. */
337 STAMPROFILEADV StatReads;
338 /** Statistics: number of bytes read. */
339 STAMCOUNTER StatBytesRead;
340 /** Statistics: number of write operations and the time spent writing. */
341 STAMPROFILEADV StatWrites;
342 /** Statistics: number of bytes written. */
343 STAMCOUNTER StatBytesWritten;
344 /** Statistics: number of flush operations and the time spend flushing. */
345 STAMPROFILE StatFlushes;
346
347 /** Enable passing through commands directly to the ATAPI drive. */
348 bool fATAPIPassthrough;
349 /** Flag whether to overwrite inquiry data in passthrough mode. */
350 bool fOverwriteInquiry;
351 /** Number of errors we've reported to the release log.
352 * This is to prevent flooding caused by something going horribly wrong.
353 * this value against MAX_LOG_REL_ERRORS in places likely to cause floods
354 * like the ones we currently seeing on the linux smoke tests (2006-11-10). */
355 uint32_t cErrors;
356 /** Timestamp of last started command. 0 if no command pending. */
357 uint64_t u64CmdTS;
358
359 /** The LUN number. */
360 uint32_t iLUN;
361 /** The controller number. */
362 uint8_t iCtl;
363 /** The device number. */
364 uint8_t iDev;
365 /** Set if the device is present. */
366 bool fPresent;
367 /** Explicit alignment. */
368 uint8_t bAlignment2;
369
370 /** The serial number to use for IDENTIFY DEVICE commands. */
371 char szSerialNumber[ATA_SERIAL_NUMBER_LENGTH+1];
372 /** The firmware revision to use for IDENTIFY DEVICE commands. */
373 char szFirmwareRevision[ATA_FIRMWARE_REVISION_LENGTH+1];
374 /** The model number to use for IDENTIFY DEVICE commands. */
375 char szModelNumber[ATA_MODEL_NUMBER_LENGTH+1];
376 /** The vendor identification string for SCSI INQUIRY commands. */
377 char szInquiryVendorId[SCSI_INQUIRY_VENDOR_ID_LENGTH+1];
378 /** The product identification string for SCSI INQUIRY commands. */
379 char szInquiryProductId[SCSI_INQUIRY_PRODUCT_ID_LENGTH+1];
380 /** The revision string for SCSI INQUIRY commands. */
381 char szInquiryRevision[SCSI_INQUIRY_REVISION_LENGTH+1];
382
383 /** Padding the structure to a multiple of 4096 for better I/O buffer alignment. */
384 uint8_t abAlignment4[7 + 3528];
385} ATADEVSTATE;
386AssertCompileMemberAlignment(ATADEVSTATE, cTotalSectors, 8);
387AssertCompileMemberAlignment(ATADEVSTATE, StatATADMA, 8);
388AssertCompileMemberAlignment(ATADEVSTATE, u64CmdTS, 8);
389AssertCompileMemberAlignment(ATADEVSTATE, szSerialNumber, 8);
390AssertCompileSizeAlignment(ATADEVSTATE, 4096); /* To align the buffer on a page boundrary. */
391/** Pointer to the shared state of an ATA device. */
392typedef ATADEVSTATE *PATADEVSTATE;
393
394
395/**
396 * The ring-3 state of an ATA device.
397 *
398 * @implements PDMIBASE
399 * @implements PDMIBLOCKPORT
400 * @implements PDMIMOUNTNOTIFY
401 */
402typedef struct ATADEVSTATER3
403{
404 /** Pointer to the attached driver's base interface. */
405 R3PTRTYPE(PPDMIBASE) pDrvBase;
406 /** Pointer to the attached driver's block interface. */
407 R3PTRTYPE(PPDMIMEDIA) pDrvMedia;
408 /** Pointer to the attached driver's mount interface.
409 * This is NULL if the driver isn't a removable unit. */
410 R3PTRTYPE(PPDMIMOUNT) pDrvMount;
411 /** The base interface. */
412 PDMIBASE IBase;
413 /** The block port interface. */
414 PDMIMEDIAPORT IPort;
415 /** The mount notify interface. */
416 PDMIMOUNTNOTIFY IMountNotify;
417
418 /** The LUN number. */
419 uint32_t iLUN;
420 /** The controller number. */
421 uint8_t iCtl;
422 /** The device number. */
423 uint8_t iDev;
424 /** Explicit alignment. */
425 uint8_t abAlignment2[2];
426 /** The device instance so we can get our bearings from an interface method. */
427 PPDMDEVINSR3 pDevIns;
428
429 /** The current tracklist of the loaded medium if passthrough is used. */
430 R3PTRTYPE(PTRACKLIST) pTrackList;
431} ATADEVSTATER3;
432/** Pointer to the ring-3 state of an ATA device. */
433typedef ATADEVSTATER3 *PATADEVSTATER3;
434
435
436/**
437 * Transfer request forwarded to the async I/O thread.
438 */
439typedef struct ATATransferRequest
440{
441 /** The interface index the request is for. */
442 uint8_t iIf;
443 /** The index of the begin transfer callback to call. */
444 uint8_t iBeginTransfer;
445 /** The index of the source sink callback to call for doing the transfer. */
446 uint8_t iSourceSink;
447 /** Transfer direction. */
448 uint8_t uTxDir;
449 /** How many bytes to transfer. */
450 uint32_t cbTotalTransfer;
451} ATATransferRequest;
452
453
454/**
455 * Abort request forwarded to the async I/O thread.
456 */
457typedef struct ATAAbortRequest
458{
459 /** The interface index the request is for. */
460 uint8_t iIf;
461 /** Flag whether to reset the drive. */
462 bool fResetDrive;
463} ATAAbortRequest;
464
465
466/**
467 * Request type indicator.
468 */
469typedef enum
470{
471 /** Begin a new transfer. */
472 ATA_AIO_NEW = 0,
473 /** Continue a DMA transfer. */
474 ATA_AIO_DMA,
475 /** Continue a PIO transfer. */
476 ATA_AIO_PIO,
477 /** Reset the drives on current controller, stop all transfer activity. */
478 ATA_AIO_RESET_ASSERTED,
479 /** Reset the drives on current controller, resume operation. */
480 ATA_AIO_RESET_CLEARED,
481 /** Abort the current transfer of a particular drive. */
482 ATA_AIO_ABORT
483} ATAAIO;
484
485
486/**
487 * Combining structure for an ATA request to the async I/O thread
488 * started with the request type insicator.
489 */
490typedef struct ATARequest
491{
492 /** Request type. */
493 ATAAIO ReqType;
494 /** Request type dependent data. */
495 union
496 {
497 /** Transfer request specific data. */
498 ATATransferRequest t;
499 /** Abort request specific data. */
500 ATAAbortRequest a;
501 } u;
502} ATARequest;
503
504
505/**
506 * The shared state of an ATA controller.
507 *
508 * Has two devices, the master (0) and the slave (1).
509 */
510typedef struct ATACONTROLLER
511{
512 /** The ATA/ATAPI interfaces of this controller. */
513 ATADEVSTATE aIfs[2];
514
515 /** The base of the first I/O Port range. */
516 RTIOPORT IOPortBase1;
517 /** The base of the second I/O Port range. (0 if none) */
518 RTIOPORT IOPortBase2;
519 /** The assigned IRQ. */
520 uint32_t irq;
521 /** Access critical section */
522 PDMCRITSECT lock;
523
524 /** Selected drive. */
525 uint8_t iSelectedIf;
526 /** The interface on which to handle async I/O. */
527 uint8_t iAIOIf;
528 /** The state of the async I/O thread. */
529 uint8_t uAsyncIOState;
530 /** Flag indicating whether the next transfer is part of the current command. */
531 bool fChainedTransfer;
532 /** Set when the reset processing is currently active on this controller. */
533 bool fReset;
534 /** Flag whether the current transfer needs to be redone. */
535 bool fRedo;
536 /** Flag whether the redo suspend has been finished. */
537 bool fRedoIdle;
538 /** Flag whether the DMA operation to be redone is the final transfer. */
539 bool fRedoDMALastDesc;
540 /** The BusMaster DMA state. */
541 BMDMAState BmDma;
542 /** Pointer to first DMA descriptor. */
543 RTGCPHYS32 GCPhysFirstDMADesc;
544 /** Pointer to last DMA descriptor. */
545 RTGCPHYS32 GCPhysLastDMADesc;
546 /** Pointer to current DMA buffer (for redo operations). */
547 RTGCPHYS32 GCPhysRedoDMABuffer;
548 /** Size of current DMA buffer (for redo operations). */
549 uint32_t cbRedoDMABuffer;
550
551 /** The event semaphore the thread is waiting on for requests. */
552 SUPSEMEVENT hAsyncIOSem;
553 /** The request queue for the AIO thread. One element is always unused. */
554 ATARequest aAsyncIORequests[4];
555 /** The position at which to insert a new request for the AIO thread. */
556 volatile uint8_t AsyncIOReqHead;
557 /** The position at which to get a new request for the AIO thread. */
558 volatile uint8_t AsyncIOReqTail;
559 /** The controller number. */
560 uint8_t iCtl;
561 /** Magic delay before triggering interrupts in DMA mode. */
562 uint32_t msDelayIRQ;
563 /** The lock protecting the request queue. */
564 PDMCRITSECT AsyncIORequestLock;
565
566 /** Timestamp we started the reset. */
567 uint64_t u64ResetTime;
568
569 /** The first port in the first I/O port range, regular operation. */
570 IOMIOPORTHANDLE hIoPorts1First;
571 /** The other ports in the first I/O port range, regular operation. */
572 IOMIOPORTHANDLE hIoPorts1Other;
573 /** The second I/O port range, regular operation. */
574 IOMIOPORTHANDLE hIoPorts2;
575 /** The first I/O port range, empty controller operation. */
576 IOMIOPORTHANDLE hIoPortsEmpty1;
577 /** The second I/O port range, empty controller operation. */
578 IOMIOPORTHANDLE hIoPortsEmpty2;
579
580 /* Statistics */
581 STAMCOUNTER StatAsyncOps;
582 uint64_t StatAsyncMinWait;
583 uint64_t StatAsyncMaxWait;
584 STAMCOUNTER StatAsyncTimeUS;
585 STAMPROFILEADV StatAsyncTime;
586 STAMPROFILE StatLockWait;
587 uint8_t abAlignment4[3328];
588} ATACONTROLLER;
589AssertCompileMemberAlignment(ATACONTROLLER, lock, 8);
590AssertCompileMemberAlignment(ATACONTROLLER, aIfs, 8);
591AssertCompileMemberAlignment(ATACONTROLLER, u64ResetTime, 8);
592AssertCompileMemberAlignment(ATACONTROLLER, StatAsyncOps, 8);
593AssertCompileMemberAlignment(ATACONTROLLER, AsyncIORequestLock, 8);
594AssertCompileSizeAlignment(ATACONTROLLER, 4096); /* To align the controllers, devices and I/O buffers on page boundaries. */
595/** Pointer to the shared state of an ATA controller. */
596typedef ATACONTROLLER *PATACONTROLLER;
597
598
599/**
600 * The ring-3 state of an ATA controller.
601 */
602typedef struct ATACONTROLLERR3
603{
604 /** The ATA/ATAPI interfaces of this controller. */
605 ATADEVSTATER3 aIfs[2];
606
607 /** Pointer to device instance. */
608 PPDMDEVINSR3 pDevIns;
609
610 /** The async I/O thread handle. NIL_RTTHREAD if no thread. */
611 RTTHREAD hAsyncIOThread;
612 /** The event semaphore the thread is waiting on during suspended I/O. */
613 RTSEMEVENT hSuspendIOSem;
614 /** Set when the destroying the device instance and the thread must exit. */
615 uint32_t volatile fShutdown;
616 /** Whether to call PDMDevHlpAsyncNotificationCompleted when idle. */
617 bool volatile fSignalIdle;
618
619 /** The controller number. */
620 uint8_t iCtl;
621
622 uint8_t abAlignment[3];
623} ATACONTROLLERR3;
624/** Pointer to the ring-3 state of an ATA controller. */
625typedef ATACONTROLLERR3 *PATACONTROLLERR3;
626
627
628/** ATA chipset type. */
629typedef enum CHIPSET
630{
631 /** PIIX3 chipset, must be 0 for saved state compatibility */
632 CHIPSET_PIIX3 = 0,
633 /** PIIX4 chipset, must be 1 for saved state compatibility */
634 CHIPSET_PIIX4,
635 /** ICH6 chipset */
636 CHIPSET_ICH6,
637 CHIPSET_32BIT_HACK=0x7fffffff
638} CHIPSET;
639AssertCompileSize(CHIPSET, 4);
640
641/**
642 * The shared state of a ATA PCI device.
643 */
644typedef struct ATASTATE
645{
646 /** The controllers. */
647 ATACONTROLLER aCts[2];
648 /** Flag indicating chipset being emulated. */
649 CHIPSET enmChipset;
650 /** Explicit alignment padding. */
651 uint8_t abAlignment1[7];
652 /** PCI region \#4: Bus-master DMA I/O ports. */
653 IOMIOPORTHANDLE hIoPortsBmDma;
654} ATASTATE;
655/** Pointer to the shared state of an ATA PCI device. */
656typedef ATASTATE *PATASTATE;
657
658
659/**
660 * The ring-3 state of a ATA PCI device.
661 *
662 * @implements PDMILEDPORTS
663 */
664typedef struct ATASTATER3
665{
666 /** The controllers. */
667 ATACONTROLLERR3 aCts[2];
668 /** Status LUN: Base interface. */
669 PDMIBASE IBase;
670 /** Status LUN: Leds interface. */
671 PDMILEDPORTS ILeds;
672 /** Status LUN: Partner of ILeds. */
673 R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
674 /** Status LUN: Media Notify. */
675 R3PTRTYPE(PPDMIMEDIANOTIFY) pMediaNotify;
676 /** Pointer to device instance (for getting our bearings in interface methods). */
677 PPDMDEVINSR3 pDevIns;
678} ATASTATER3;
679/** Pointer to the ring-3 state of an ATA PCI device. */
680typedef ATASTATER3 *PATASTATER3;
681
682
683/**
684 * The ring-0 state of the ATA PCI device.
685 */
686typedef struct ATASTATER0
687{
688 uint64_t uUnused;
689} ATASTATER0;
690/** Pointer to the ring-0 state of an ATA PCI device. */
691typedef ATASTATER0 *PATASTATER0;
692
693
694/**
695 * The raw-mode state of the ATA PCI device.
696 */
697typedef struct ATASTATERC
698{
699 uint64_t uUnused;
700} ATASTATERC;
701/** Pointer to the raw-mode state of an ATA PCI device. */
702typedef ATASTATERC *PATASTATERC;
703
704
705/** The current context state of an ATA PCI device. */
706typedef CTX_SUFF(ATASTATE) ATASTATECC;
707/** Pointer to the current context state of an ATA PCI device. */
708typedef CTX_SUFF(PATASTATE) PATASTATECC;
709
710
711#ifndef VBOX_DEVICE_STRUCT_TESTCASE
712
713
714#ifdef IN_RING3
715DECLINLINE(void) ataSetStatusValue(PATACONTROLLER pCtl, PATADEVSTATE s, uint8_t stat)
716{
717 /* Freeze status register contents while processing RESET. */
718 if (!pCtl->fReset)
719 {
720 s->uATARegStatus = stat;
721 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, s->iLUN, s->uATARegStatus));
722 }
723}
724#endif /* IN_RING3 */
725
726
727DECLINLINE(void) ataSetStatus(PATACONTROLLER pCtl, PATADEVSTATE s, uint8_t stat)
728{
729 /* Freeze status register contents while processing RESET. */
730 if (!pCtl->fReset)
731 {
732 s->uATARegStatus |= stat;
733 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, s->iLUN, s->uATARegStatus));
734 }
735}
736
737
738DECLINLINE(void) ataUnsetStatus(PATACONTROLLER pCtl, PATADEVSTATE s, uint8_t stat)
739{
740 /* Freeze status register contents while processing RESET. */
741 if (!pCtl->fReset)
742 {
743 s->uATARegStatus &= ~stat;
744 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, s->iLUN, s->uATARegStatus));
745 }
746}
747
748#if defined(IN_RING3) || defined(IN_RING0)
749
750# ifdef IN_RING3
751typedef void FNBEGINTRANSFER(PATACONTROLLER pCtl, PATADEVSTATE s);
752typedef FNBEGINTRANSFER *PFNBEGINTRANSFER;
753typedef bool FNSOURCESINK(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3);
754typedef FNSOURCESINK *PFNSOURCESINK;
755
756static FNBEGINTRANSFER ataR3ReadWriteSectorsBT;
757static FNBEGINTRANSFER ataR3PacketBT;
758static FNBEGINTRANSFER atapiR3CmdBT;
759static FNBEGINTRANSFER atapiR3PassthroughCmdBT;
760
761static FNSOURCESINK ataR3IdentifySS;
762static FNSOURCESINK ataR3FlushSS;
763static FNSOURCESINK ataR3ReadSectorsSS;
764static FNSOURCESINK ataR3WriteSectorsSS;
765static FNSOURCESINK ataR3ExecuteDeviceDiagnosticSS;
766static FNSOURCESINK ataR3TrimSS;
767static FNSOURCESINK ataR3PacketSS;
768static FNSOURCESINK ataR3InitDevParmSS;
769static FNSOURCESINK ataR3RecalibrateSS;
770static FNSOURCESINK atapiR3GetConfigurationSS;
771static FNSOURCESINK atapiR3GetEventStatusNotificationSS;
772static FNSOURCESINK atapiR3IdentifySS;
773static FNSOURCESINK atapiR3InquirySS;
774static FNSOURCESINK atapiR3MechanismStatusSS;
775static FNSOURCESINK atapiR3ModeSenseErrorRecoverySS;
776static FNSOURCESINK atapiR3ModeSenseCDStatusSS;
777static FNSOURCESINK atapiR3ReadSS;
778static FNSOURCESINK atapiR3ReadCapacitySS;
779static FNSOURCESINK atapiR3ReadDiscInformationSS;
780static FNSOURCESINK atapiR3ReadTOCNormalSS;
781static FNSOURCESINK atapiR3ReadTOCMultiSS;
782static FNSOURCESINK atapiR3ReadTOCRawSS;
783static FNSOURCESINK atapiR3ReadTrackInformationSS;
784static FNSOURCESINK atapiR3RequestSenseSS;
785static FNSOURCESINK atapiR3PassthroughSS;
786static FNSOURCESINK atapiR3ReadDVDStructureSS;
787# endif /* IN_RING3 */
788
789/**
790 * Begin of transfer function indexes for g_apfnBeginTransFuncs.
791 */
792typedef enum ATAFNBT
793{
794 ATAFN_BT_NULL = 0,
795 ATAFN_BT_READ_WRITE_SECTORS,
796 ATAFN_BT_PACKET,
797 ATAFN_BT_ATAPI_CMD,
798 ATAFN_BT_ATAPI_PASSTHROUGH_CMD,
799 ATAFN_BT_MAX
800} ATAFNBT;
801
802# ifdef IN_RING3
803/**
804 * Array of end transfer functions, the index is ATAFNET.
805 * Make sure ATAFNET and this array match!
806 */
807static const PFNBEGINTRANSFER g_apfnBeginTransFuncs[ATAFN_BT_MAX] =
808{
809 NULL,
810 ataR3ReadWriteSectorsBT,
811 ataR3PacketBT,
812 atapiR3CmdBT,
813 atapiR3PassthroughCmdBT,
814};
815# endif /* IN_RING3 */
816
817/**
818 * Source/sink function indexes for g_apfnSourceSinkFuncs.
819 */
820typedef enum ATAFNSS
821{
822 ATAFN_SS_NULL = 0,
823 ATAFN_SS_IDENTIFY,
824 ATAFN_SS_FLUSH,
825 ATAFN_SS_READ_SECTORS,
826 ATAFN_SS_WRITE_SECTORS,
827 ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC,
828 ATAFN_SS_TRIM,
829 ATAFN_SS_PACKET,
830 ATAFN_SS_INITIALIZE_DEVICE_PARAMETERS,
831 ATAFN_SS_RECALIBRATE,
832 ATAFN_SS_ATAPI_GET_CONFIGURATION,
833 ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION,
834 ATAFN_SS_ATAPI_IDENTIFY,
835 ATAFN_SS_ATAPI_INQUIRY,
836 ATAFN_SS_ATAPI_MECHANISM_STATUS,
837 ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY,
838 ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS,
839 ATAFN_SS_ATAPI_READ,
840 ATAFN_SS_ATAPI_READ_CAPACITY,
841 ATAFN_SS_ATAPI_READ_DISC_INFORMATION,
842 ATAFN_SS_ATAPI_READ_TOC_NORMAL,
843 ATAFN_SS_ATAPI_READ_TOC_MULTI,
844 ATAFN_SS_ATAPI_READ_TOC_RAW,
845 ATAFN_SS_ATAPI_READ_TRACK_INFORMATION,
846 ATAFN_SS_ATAPI_REQUEST_SENSE,
847 ATAFN_SS_ATAPI_PASSTHROUGH,
848 ATAFN_SS_ATAPI_READ_DVD_STRUCTURE,
849 ATAFN_SS_MAX
850} ATAFNSS;
851
852# ifdef IN_RING3
853/**
854 * Array of source/sink functions, the index is ATAFNSS.
855 * Make sure ATAFNSS and this array match!
856 */
857static const PFNSOURCESINK g_apfnSourceSinkFuncs[ATAFN_SS_MAX] =
858{
859 NULL,
860 ataR3IdentifySS,
861 ataR3FlushSS,
862 ataR3ReadSectorsSS,
863 ataR3WriteSectorsSS,
864 ataR3ExecuteDeviceDiagnosticSS,
865 ataR3TrimSS,
866 ataR3PacketSS,
867 ataR3InitDevParmSS,
868 ataR3RecalibrateSS,
869 atapiR3GetConfigurationSS,
870 atapiR3GetEventStatusNotificationSS,
871 atapiR3IdentifySS,
872 atapiR3InquirySS,
873 atapiR3MechanismStatusSS,
874 atapiR3ModeSenseErrorRecoverySS,
875 atapiR3ModeSenseCDStatusSS,
876 atapiR3ReadSS,
877 atapiR3ReadCapacitySS,
878 atapiR3ReadDiscInformationSS,
879 atapiR3ReadTOCNormalSS,
880 atapiR3ReadTOCMultiSS,
881 atapiR3ReadTOCRawSS,
882 atapiR3ReadTrackInformationSS,
883 atapiR3RequestSenseSS,
884 atapiR3PassthroughSS,
885 atapiR3ReadDVDStructureSS
886};
887# endif /* IN_RING3 */
888
889
890static const ATARequest g_ataDMARequest = { ATA_AIO_DMA, { { 0, 0, 0, 0, 0 } } };
891static const ATARequest g_ataPIORequest = { ATA_AIO_PIO, { { 0, 0, 0, 0, 0 } } };
892# ifdef IN_RING3
893static const ATARequest g_ataResetARequest = { ATA_AIO_RESET_ASSERTED, { { 0, 0, 0, 0, 0 } } };
894static const ATARequest g_ataResetCRequest = { ATA_AIO_RESET_CLEARED, { { 0, 0, 0, 0, 0 } } };
895# endif
896
897# ifdef IN_RING3
898static void ataR3AsyncIOClearRequests(PPDMDEVINS pDevIns, PATACONTROLLER pCtl)
899{
900 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
901 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
902
903 pCtl->AsyncIOReqHead = 0;
904 pCtl->AsyncIOReqTail = 0;
905
906 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
907 AssertRC(rc);
908}
909# endif /* IN_RING3 */
910
911static void ataHCAsyncIOPutRequest(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, const ATARequest *pReq)
912{
913 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
914 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
915
916 uint8_t const iAsyncIORequest = pCtl->AsyncIOReqHead % RT_ELEMENTS(pCtl->aAsyncIORequests);
917 Assert((iAsyncIORequest + 1) % RT_ELEMENTS(pCtl->aAsyncIORequests) != pCtl->AsyncIOReqTail);
918 memcpy(&pCtl->aAsyncIORequests[iAsyncIORequest], pReq, sizeof(*pReq));
919 pCtl->AsyncIOReqHead = (iAsyncIORequest + 1) % RT_ELEMENTS(pCtl->aAsyncIORequests);
920
921 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
922 AssertRC(rc);
923
924 rc = PDMDevHlpCritSectScheduleExitEvent(pDevIns, &pCtl->lock, pCtl->hAsyncIOSem);
925 if (RT_FAILURE(rc))
926 {
927 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pCtl->hAsyncIOSem);
928 AssertRC(rc);
929 }
930}
931
932# ifdef IN_RING3
933
934static const ATARequest *ataR3AsyncIOGetCurrentRequest(PPDMDEVINS pDevIns, PATACONTROLLER pCtl)
935{
936 const ATARequest *pReq;
937
938 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
939 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
940
941 if (pCtl->AsyncIOReqHead != pCtl->AsyncIOReqTail)
942 pReq = &pCtl->aAsyncIORequests[pCtl->AsyncIOReqTail];
943 else
944 pReq = NULL;
945
946 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
947 AssertRC(rc);
948 return pReq;
949}
950
951
952/**
953 * Remove the request with the given type, as it's finished. The request
954 * is not removed blindly, as this could mean a RESET request that is not
955 * yet processed (but has cleared the request queue) is lost.
956 *
957 * @param pDevIns The device instance.
958 * @param pCtl Controller for which to remove the request.
959 * @param ReqType Type of the request to remove.
960 */
961static void ataR3AsyncIORemoveCurrentRequest(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, ATAAIO ReqType)
962{
963 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
964 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
965
966 if (pCtl->AsyncIOReqHead != pCtl->AsyncIOReqTail && pCtl->aAsyncIORequests[pCtl->AsyncIOReqTail].ReqType == ReqType)
967 {
968 pCtl->AsyncIOReqTail++;
969 pCtl->AsyncIOReqTail %= RT_ELEMENTS(pCtl->aAsyncIORequests);
970 }
971
972 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
973 AssertRC(rc);
974}
975
976
977/**
978 * Dump the request queue for a particular controller. First dump the queue
979 * contents, then the already processed entries, as long as they haven't been
980 * overwritten.
981 *
982 * @param pDevIns The device instance.
983 * @param pCtl Controller for which to dump the queue.
984 */
985static void ataR3AsyncIODumpRequests(PPDMDEVINS pDevIns, PATACONTROLLER pCtl)
986{
987 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
988 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
989
990 LogRel(("PIIX3 ATA: Ctl#%d: request queue dump (topmost is current):\n", pCtl->iCtl));
991 uint8_t curr = pCtl->AsyncIOReqTail;
992 do
993 {
994 if (curr == pCtl->AsyncIOReqHead)
995 LogRel(("PIIX3 ATA: Ctl#%d: processed requests (topmost is oldest):\n", pCtl->iCtl));
996 switch (pCtl->aAsyncIORequests[curr].ReqType)
997 {
998 case ATA_AIO_NEW:
999 LogRel(("new transfer request, iIf=%d iBeginTransfer=%d iSourceSink=%d cbTotalTransfer=%d uTxDir=%d\n",
1000 pCtl->aAsyncIORequests[curr].u.t.iIf, pCtl->aAsyncIORequests[curr].u.t.iBeginTransfer,
1001 pCtl->aAsyncIORequests[curr].u.t.iSourceSink, pCtl->aAsyncIORequests[curr].u.t.cbTotalTransfer,
1002 pCtl->aAsyncIORequests[curr].u.t.uTxDir));
1003 break;
1004 case ATA_AIO_DMA:
1005 LogRel(("dma transfer continuation\n"));
1006 break;
1007 case ATA_AIO_PIO:
1008 LogRel(("pio transfer continuation\n"));
1009 break;
1010 case ATA_AIO_RESET_ASSERTED:
1011 LogRel(("reset asserted request\n"));
1012 break;
1013 case ATA_AIO_RESET_CLEARED:
1014 LogRel(("reset cleared request\n"));
1015 break;
1016 case ATA_AIO_ABORT:
1017 LogRel(("abort request, iIf=%d fResetDrive=%d\n", pCtl->aAsyncIORequests[curr].u.a.iIf,
1018 pCtl->aAsyncIORequests[curr].u.a.fResetDrive));
1019 break;
1020 default:
1021 LogRel(("unknown request %d\n", pCtl->aAsyncIORequests[curr].ReqType));
1022 }
1023 curr = (curr + 1) % RT_ELEMENTS(pCtl->aAsyncIORequests);
1024 } while (curr != pCtl->AsyncIOReqTail);
1025
1026 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
1027 AssertRC(rc);
1028}
1029
1030
1031/**
1032 * Checks whether the request queue for a particular controller is empty
1033 * or whether a particular controller is idle.
1034 *
1035 * @param pDevIns The device instance.
1036 * @param pCtl Controller for which to check the queue.
1037 * @param fStrict If set then the controller is checked to be idle.
1038 */
1039static bool ataR3AsyncIOIsIdle(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, bool fStrict)
1040{
1041 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
1042 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
1043
1044 bool fIdle = pCtl->fRedoIdle;
1045 if (!fIdle)
1046 fIdle = (pCtl->AsyncIOReqHead == pCtl->AsyncIOReqTail);
1047 if (fStrict)
1048 fIdle &= (pCtl->uAsyncIOState == ATA_AIO_NEW);
1049
1050 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
1051 AssertRC(rc);
1052 return fIdle;
1053}
1054
1055
1056/**
1057 * Send a transfer request to the async I/O thread.
1058 *
1059 * @param pDevIns The device instance.
1060 * @param pCtl The ATA controller.
1061 * @param s Pointer to the ATA device state data.
1062 * @param cbTotalTransfer Data transfer size.
1063 * @param uTxDir Data transfer direction.
1064 * @param iBeginTransfer Index of BeginTransfer callback.
1065 * @param iSourceSink Index of SourceSink callback.
1066 * @param fChainedTransfer Whether this is a transfer that is part of the previous command/transfer.
1067 */
1068static void ataR3StartTransfer(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s,
1069 uint32_t cbTotalTransfer, uint8_t uTxDir, ATAFNBT iBeginTransfer,
1070 ATAFNSS iSourceSink, bool fChainedTransfer)
1071{
1072 ATARequest Req;
1073
1074 Assert(PDMDevHlpCritSectIsOwner(pDevIns, &pCtl->lock));
1075
1076 /* Do not issue new requests while the RESET line is asserted. */
1077 if (pCtl->fReset)
1078 {
1079 Log2(("%s: Ctl#%d: suppressed new request as RESET is active\n", __FUNCTION__, pCtl->iCtl));
1080 return;
1081 }
1082
1083 /* If the controller is already doing something else right now, ignore
1084 * the command that is being submitted. Some broken guests issue commands
1085 * twice (e.g. the Linux kernel that comes with Acronis True Image 8). */
1086 if (!fChainedTransfer && !ataR3AsyncIOIsIdle(pDevIns, pCtl, true /*fStrict*/))
1087 {
1088 Log(("%s: Ctl#%d: ignored command %#04x, controller state %d\n", __FUNCTION__, pCtl->iCtl, s->uATARegCommand, pCtl->uAsyncIOState));
1089 LogRel(("PIIX3 IDE: guest issued command %#04x while controller busy\n", s->uATARegCommand));
1090 return;
1091 }
1092
1093 Req.ReqType = ATA_AIO_NEW;
1094 if (fChainedTransfer)
1095 Req.u.t.iIf = pCtl->iAIOIf;
1096 else
1097 Req.u.t.iIf = pCtl->iSelectedIf;
1098 Req.u.t.cbTotalTransfer = cbTotalTransfer;
1099 Req.u.t.uTxDir = uTxDir;
1100 Req.u.t.iBeginTransfer = iBeginTransfer;
1101 Req.u.t.iSourceSink = iSourceSink;
1102 ataSetStatusValue(pCtl, s, ATA_STAT_BUSY);
1103 pCtl->fChainedTransfer = fChainedTransfer;
1104
1105 /*
1106 * Kick the worker thread into action.
1107 */
1108 Log2(("%s: Ctl#%d: message to async I/O thread, new request\n", __FUNCTION__, pCtl->iCtl));
1109 ataHCAsyncIOPutRequest(pDevIns, pCtl, &Req);
1110}
1111
1112
1113/**
1114 * Send an abort command request to the async I/O thread.
1115 *
1116 * @param pDevIns The device instance.
1117 * @param pCtl The ATA controller.
1118 * @param s Pointer to the ATA device state data.
1119 * @param fResetDrive Whether to reset the drive or just abort a command.
1120 */
1121static void ataR3AbortCurrentCommand(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, bool fResetDrive)
1122{
1123 ATARequest Req;
1124
1125 Assert(PDMDevHlpCritSectIsOwner(pDevIns, &pCtl->lock));
1126
1127 /* Do not issue new requests while the RESET line is asserted. */
1128 if (pCtl->fReset)
1129 {
1130 Log2(("%s: Ctl#%d: suppressed aborting command as RESET is active\n", __FUNCTION__, pCtl->iCtl));
1131 return;
1132 }
1133
1134 Req.ReqType = ATA_AIO_ABORT;
1135 Req.u.a.iIf = pCtl->iSelectedIf;
1136 Req.u.a.fResetDrive = fResetDrive;
1137 ataSetStatus(pCtl, s, ATA_STAT_BUSY);
1138 Log2(("%s: Ctl#%d: message to async I/O thread, abort command on LUN#%d\n", __FUNCTION__, pCtl->iCtl, s->iLUN));
1139 ataHCAsyncIOPutRequest(pDevIns, pCtl, &Req);
1140}
1141
1142# endif /* IN_RING3 */
1143
1144/**
1145 * Set the internal interrupt pending status, update INTREQ as appropriate.
1146 *
1147 * @param pDevIns The device instance.
1148 * @param pCtl The ATA controller.
1149 * @param s Pointer to the ATA device state data.
1150 */
1151static void ataHCSetIRQ(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
1152{
1153 if (!s->fIrqPending)
1154 {
1155 if (!(s->uATARegDevCtl & ATA_DEVCTL_DISABLE_IRQ))
1156 {
1157 Log2(("%s: LUN#%d asserting IRQ\n", __FUNCTION__, s->iLUN));
1158 /* The BMDMA unit unconditionally sets BM_STATUS_INT if the interrupt
1159 * line is asserted. It monitors the line for a rising edge. */
1160 pCtl->BmDma.u8Status |= BM_STATUS_INT;
1161 /* Only actually set the IRQ line if updating the currently selected drive. */
1162 if (s == &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK])
1163 {
1164 /** @todo experiment with adaptive IRQ delivery: for reads it is
1165 * better to wait for IRQ delivery, as it reduces latency. */
1166 if (pCtl->irq == 16)
1167 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
1168 else
1169 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 1);
1170 }
1171 }
1172 s->fIrqPending = true;
1173 }
1174}
1175
1176#endif /* IN_RING0 || IN_RING3 */
1177
1178/**
1179 * Clear the internal interrupt pending status, update INTREQ as appropriate.
1180 *
1181 * @param pDevIns The device instance.
1182 * @param pCtl The ATA controller.
1183 * @param s Pointer to the ATA device state data.
1184 */
1185static void ataUnsetIRQ(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
1186{
1187 if (s->fIrqPending)
1188 {
1189 if (!(s->uATARegDevCtl & ATA_DEVCTL_DISABLE_IRQ))
1190 {
1191 Log2(("%s: LUN#%d deasserting IRQ\n", __FUNCTION__, s->iLUN));
1192 /* Only actually unset the IRQ line if updating the currently selected drive. */
1193 if (s == &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK])
1194 {
1195 if (pCtl->irq == 16)
1196 PDMDevHlpPCISetIrq(pDevIns, 0, 0);
1197 else
1198 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 0);
1199 }
1200 }
1201 s->fIrqPending = false;
1202 }
1203}
1204
1205#if defined(IN_RING0) || defined(IN_RING3)
1206
1207static void ataHCPIOTransferStart(PATACONTROLLER pCtl, PATADEVSTATE s, uint32_t start, uint32_t size)
1208{
1209 Log2(("%s: LUN#%d start %d size %d\n", __FUNCTION__, s->iLUN, start, size));
1210 s->iIOBufferPIODataStart = start;
1211 s->iIOBufferPIODataEnd = start + size;
1212 ataSetStatus(pCtl, s, ATA_STAT_DRQ | ATA_STAT_SEEK);
1213 ataUnsetStatus(pCtl, s, ATA_STAT_BUSY);
1214}
1215
1216
1217static void ataHCPIOTransferStop(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
1218{
1219 Log2(("%s: LUN#%d\n", __FUNCTION__, s->iLUN));
1220 if (s->fATAPITransfer)
1221 {
1222 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
1223 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
1224 ataHCSetIRQ(pDevIns, pCtl, s);
1225 s->fATAPITransfer = false;
1226 }
1227 s->cbTotalTransfer = 0;
1228 s->cbElementaryTransfer = 0;
1229 s->iIOBufferPIODataStart = 0;
1230 s->iIOBufferPIODataEnd = 0;
1231 s->iBeginTransfer = ATAFN_BT_NULL;
1232 s->iSourceSink = ATAFN_SS_NULL;
1233}
1234
1235
1236static void ataHCPIOTransferLimitATAPI(PATADEVSTATE s)
1237{
1238 uint32_t cbLimit, cbTransfer;
1239
1240 cbLimit = s->cbPIOTransferLimit;
1241 /* Use maximum transfer size if the guest requested 0. Avoids a hang. */
1242 if (cbLimit == 0)
1243 cbLimit = 0xfffe;
1244 Log2(("%s: byte count limit=%d\n", __FUNCTION__, cbLimit));
1245 if (cbLimit == 0xffff)
1246 cbLimit--;
1247 cbTransfer = RT_MIN(s->cbTotalTransfer, s->iIOBufferEnd - s->iIOBufferCur);
1248 if (cbTransfer > cbLimit)
1249 {
1250 /* Byte count limit for clipping must be even in this case */
1251 if (cbLimit & 1)
1252 cbLimit--;
1253 cbTransfer = cbLimit;
1254 }
1255 s->uATARegLCyl = cbTransfer;
1256 s->uATARegHCyl = cbTransfer >> 8;
1257 s->cbElementaryTransfer = cbTransfer;
1258}
1259
1260# ifdef IN_RING3
1261
1262/**
1263 * Enters the lock protecting the controller data against concurrent access.
1264 *
1265 * @returns nothing.
1266 * @param pDevIns The device instance.
1267 * @param pCtl The controller to lock.
1268 */
1269DECLINLINE(void) ataR3LockEnter(PPDMDEVINS pDevIns, PATACONTROLLER pCtl)
1270{
1271 STAM_PROFILE_START(&pCtl->StatLockWait, a);
1272 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_SUCCESS);
1273 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->lock, rcLock);
1274 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1275}
1276
1277/**
1278 * Leaves the lock protecting the controller against concurrent data access.
1279 *
1280 * @returns nothing.
1281 * @param pDevIns The device instance.
1282 * @param pCtl The controller to unlock.
1283 */
1284DECLINLINE(void) ataR3LockLeave(PPDMDEVINS pDevIns, PATACONTROLLER pCtl)
1285{
1286 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
1287}
1288
1289static uint32_t ataR3GetNSectors(PATADEVSTATE s)
1290{
1291 /* 0 means either 256 (LBA28) or 65536 (LBA48) sectors. */
1292 if (s->fLBA48)
1293 {
1294 if (!s->uATARegNSector && !s->uATARegNSectorHOB)
1295 return 65536;
1296 else
1297 return s->uATARegNSectorHOB << 8 | s->uATARegNSector;
1298 }
1299 else
1300 {
1301 if (!s->uATARegNSector)
1302 return 256;
1303 else
1304 return s->uATARegNSector;
1305 }
1306}
1307
1308
1309static void ataR3PadString(uint8_t *pbDst, const char *pbSrc, uint32_t cbSize)
1310{
1311 for (uint32_t i = 0; i < cbSize; i++)
1312 {
1313 if (*pbSrc)
1314 pbDst[i ^ 1] = *pbSrc++;
1315 else
1316 pbDst[i ^ 1] = ' ';
1317 }
1318}
1319
1320
1321#if 0 /* unused */
1322/**
1323 * Compares two MSF values.
1324 *
1325 * @returns 1 if the first value is greater than the second value.
1326 * 0 if both are equal
1327 * -1 if the first value is smaller than the second value.
1328 */
1329DECLINLINE(int) atapiCmpMSF(const uint8_t *pbMSF1, const uint8_t *pbMSF2)
1330{
1331 int iRes = 0;
1332
1333 for (unsigned i = 0; i < 3; i++)
1334 {
1335 if (pbMSF1[i] < pbMSF2[i])
1336 {
1337 iRes = -1;
1338 break;
1339 }
1340 else if (pbMSF1[i] > pbMSF2[i])
1341 {
1342 iRes = 1;
1343 break;
1344 }
1345 }
1346
1347 return iRes;
1348}
1349#endif /* unused */
1350
1351static void ataR3CmdOK(PATACONTROLLER pCtl, PATADEVSTATE s, uint8_t status)
1352{
1353 s->uATARegError = 0; /* Not needed by ATA spec, but cannot hurt. */
1354 ataSetStatusValue(pCtl, s, ATA_STAT_READY | status);
1355}
1356
1357
1358static void ataR3CmdError(PATACONTROLLER pCtl, PATADEVSTATE s, uint8_t uErrorCode)
1359{
1360 Log(("%s: code=%#x\n", __FUNCTION__, uErrorCode));
1361 Assert(uErrorCode);
1362 s->uATARegError = uErrorCode;
1363 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_SEEK | ATA_STAT_ERR);
1364 s->cbTotalTransfer = 0;
1365 s->cbElementaryTransfer = 0;
1366 s->iIOBufferCur = 0;
1367 s->iIOBufferEnd = 0;
1368 s->uTxDir = PDMMEDIATXDIR_NONE;
1369 s->iBeginTransfer = ATAFN_BT_NULL;
1370 s->iSourceSink = ATAFN_SS_NULL;
1371}
1372
1373static uint32_t ataR3Checksum(void* ptr, size_t count)
1374{
1375 uint8_t u8Sum = 0xa5, *p = (uint8_t*)ptr;
1376 size_t i;
1377
1378 for (i = 0; i < count; i++)
1379 {
1380 u8Sum += *p++;
1381 }
1382
1383 return (uint8_t)-(int32_t)u8Sum;
1384}
1385
1386/**
1387 * Sink/Source: IDENTIFY
1388 */
1389static bool ataR3IdentifySS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
1390{
1391 uint16_t *p;
1392 RT_NOREF(pDevIns);
1393
1394 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
1395 Assert(s->cbElementaryTransfer == 512);
1396
1397 p = (uint16_t *)&s->abIOBuffer[0];
1398 memset(p, 0, 512);
1399 p[0] = RT_H2LE_U16(0x0040);
1400 p[1] = RT_H2LE_U16(RT_MIN(s->PCHSGeometry.cCylinders, 16383));
1401 p[3] = RT_H2LE_U16(s->PCHSGeometry.cHeads);
1402 /* Block size; obsolete, but required for the BIOS. */
1403 p[5] = RT_H2LE_U16(s->cbSector);
1404 p[6] = RT_H2LE_U16(s->PCHSGeometry.cSectors);
1405 ataR3PadString((uint8_t *)(p + 10), s->szSerialNumber, ATA_SERIAL_NUMBER_LENGTH); /* serial number */
1406 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
1407 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
1408 p[22] = RT_H2LE_U16(0); /* ECC bytes per sector */
1409 ataR3PadString((uint8_t *)(p + 23), s->szFirmwareRevision, ATA_FIRMWARE_REVISION_LENGTH); /* firmware version */
1410 ataR3PadString((uint8_t *)(p + 27), s->szModelNumber, ATA_MODEL_NUMBER_LENGTH); /* model */
1411# if ATA_MAX_MULT_SECTORS > 1
1412 p[47] = RT_H2LE_U16(0x8000 | ATA_MAX_MULT_SECTORS);
1413# endif
1414 p[48] = RT_H2LE_U16(1); /* dword I/O, used by the BIOS */
1415 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
1416 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
1417 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
1418 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
1419 p[53] = RT_H2LE_U16(1 | 1 << 1 | 1 << 2); /* words 54-58,64-70,88 valid */
1420 p[54] = RT_H2LE_U16(RT_MIN(s->XCHSGeometry.cCylinders, 16383));
1421 p[55] = RT_H2LE_U16(s->XCHSGeometry.cHeads);
1422 p[56] = RT_H2LE_U16(s->XCHSGeometry.cSectors);
1423 p[57] = RT_H2LE_U16( RT_MIN(s->XCHSGeometry.cCylinders, 16383)
1424 * s->XCHSGeometry.cHeads
1425 * s->XCHSGeometry.cSectors);
1426 p[58] = RT_H2LE_U16( RT_MIN(s->XCHSGeometry.cCylinders, 16383)
1427 * s->XCHSGeometry.cHeads
1428 * s->XCHSGeometry.cSectors >> 16);
1429 if (s->cMultSectors)
1430 p[59] = RT_H2LE_U16(0x100 | s->cMultSectors);
1431 if (s->cTotalSectors <= (1 << 28) - 1)
1432 {
1433 p[60] = RT_H2LE_U16(s->cTotalSectors);
1434 p[61] = RT_H2LE_U16(s->cTotalSectors >> 16);
1435 }
1436 else
1437 {
1438 /* Report maximum number of sectors possible with LBA28 */
1439 p[60] = RT_H2LE_U16(((1 << 28) - 1) & 0xffff);
1440 p[61] = RT_H2LE_U16(((1 << 28) - 1) >> 16);
1441 }
1442 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, s->uATATransferMode)); /* MDMA modes supported / mode enabled */
1443 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
1444 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
1445 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
1446 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
1447 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
1448 if ( pDevR3->pDrvMedia->pfnDiscard
1449 || s->cbSector != 512
1450 || pDevR3->pDrvMedia->pfnIsNonRotational(pDevR3->pDrvMedia))
1451 {
1452 p[80] = RT_H2LE_U16(0x1f0); /* support everything up to ATA/ATAPI-8 ACS */
1453 p[81] = RT_H2LE_U16(0x28); /* conforms to ATA/ATAPI-8 ACS */
1454 }
1455 else
1456 {
1457 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
1458 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
1459 }
1460 p[82] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* supports power management, write cache and look-ahead */
1461 if (s->cTotalSectors <= (1 << 28) - 1)
1462 p[83] = RT_H2LE_U16(1 << 14 | 1 << 12); /* supports FLUSH CACHE */
1463 else
1464 p[83] = RT_H2LE_U16(1 << 14 | 1 << 10 | 1 << 12 | 1 << 13); /* supports LBA48, FLUSH CACHE and FLUSH CACHE EXT */
1465 p[84] = RT_H2LE_U16(1 << 14);
1466 p[85] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* enabled power management, write cache and look-ahead */
1467 if (s->cTotalSectors <= (1 << 28) - 1)
1468 p[86] = RT_H2LE_U16(1 << 12); /* enabled FLUSH CACHE */
1469 else
1470 p[86] = RT_H2LE_U16(1 << 10 | 1 << 12 | 1 << 13); /* enabled LBA48, FLUSH CACHE and FLUSH CACHE EXT */
1471 p[87] = RT_H2LE_U16(1 << 14);
1472 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, s->uATATransferMode)); /* UDMA modes supported / mode enabled */
1473 p[93] = RT_H2LE_U16((1 | 1 << 1) << ((s->iLUN & 1) == 0 ? 0 : 8) | 1 << 13 | 1 << 14);
1474 if (s->cTotalSectors > (1 << 28) - 1)
1475 {
1476 p[100] = RT_H2LE_U16(s->cTotalSectors);
1477 p[101] = RT_H2LE_U16(s->cTotalSectors >> 16);
1478 p[102] = RT_H2LE_U16(s->cTotalSectors >> 32);
1479 p[103] = RT_H2LE_U16(s->cTotalSectors >> 48);
1480 }
1481
1482 if (s->cbSector != 512)
1483 {
1484 uint32_t cSectorSizeInWords = s->cbSector / sizeof(uint16_t);
1485 /* Enable reporting of logical sector size. */
1486 p[106] |= RT_H2LE_U16(RT_BIT(12) | RT_BIT(14));
1487 p[117] = RT_H2LE_U16(cSectorSizeInWords);
1488 p[118] = RT_H2LE_U16(cSectorSizeInWords >> 16);
1489 }
1490
1491 if (pDevR3->pDrvMedia->pfnDiscard) /** @todo Set bit 14 in word 69 too? (Deterministic read after TRIM). */
1492 p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */
1493 if (pDevR3->pDrvMedia->pfnIsNonRotational(pDevR3->pDrvMedia))
1494 p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
1495 uint32_t uCsum = ataR3Checksum(p, 510);
1496 p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
1497 s->iSourceSink = ATAFN_SS_NULL;
1498 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
1499 return false;
1500}
1501
1502
1503/**
1504 * Sink/Source: FLUSH
1505 */
1506static bool ataR3FlushSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
1507{
1508 int rc;
1509
1510 Assert(s->uTxDir == PDMMEDIATXDIR_NONE);
1511 Assert(!s->cbElementaryTransfer);
1512
1513 ataR3LockLeave(pDevIns, pCtl);
1514
1515 STAM_PROFILE_START(&s->StatFlushes, f);
1516 rc = pDevR3->pDrvMedia->pfnFlush(pDevR3->pDrvMedia);
1517 AssertRC(rc);
1518 STAM_PROFILE_STOP(&s->StatFlushes, f);
1519
1520 ataR3LockEnter(pDevIns, pCtl);
1521 ataR3CmdOK(pCtl, s, 0);
1522 return false;
1523}
1524
1525/**
1526 * Sink/Source: ATAPI IDENTIFY
1527 */
1528static bool atapiR3IdentifySS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
1529{
1530 uint16_t *p;
1531 RT_NOREF(pDevIns, pDevR3);
1532
1533 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
1534 Assert(s->cbElementaryTransfer == 512);
1535
1536 p = (uint16_t *)&s->abIOBuffer[0];
1537 memset(p, 0, 512);
1538 /* Removable CDROM, 3ms response, 12 byte packets */
1539 p[0] = RT_H2LE_U16(2 << 14 | 5 << 8 | 1 << 7 | 0 << 5 | 0 << 0);
1540 ataR3PadString((uint8_t *)(p + 10), s->szSerialNumber, ATA_SERIAL_NUMBER_LENGTH); /* serial number */
1541 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
1542 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
1543 ataR3PadString((uint8_t *)(p + 23), s->szFirmwareRevision, ATA_FIRMWARE_REVISION_LENGTH); /* firmware version */
1544 ataR3PadString((uint8_t *)(p + 27), s->szModelNumber, ATA_MODEL_NUMBER_LENGTH); /* model */
1545 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
1546 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
1547 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
1548 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
1549 p[53] = RT_H2LE_U16(1 << 1 | 1 << 2); /* words 64-70,88 are valid */
1550 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, s->uATATransferMode)); /* MDMA modes supported / mode enabled */
1551 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
1552 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
1553 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
1554 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
1555 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
1556 p[73] = RT_H2LE_U16(0x003e); /* ATAPI CDROM major */
1557 p[74] = RT_H2LE_U16(9); /* ATAPI CDROM minor */
1558 p[75] = RT_H2LE_U16(1); /* queue depth 1 */
1559 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
1560 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
1561 p[82] = RT_H2LE_U16(1 << 4 | 1 << 9); /* supports packet command set and DEVICE RESET */
1562 p[83] = RT_H2LE_U16(1 << 14);
1563 p[84] = RT_H2LE_U16(1 << 14);
1564 p[85] = RT_H2LE_U16(1 << 4 | 1 << 9); /* enabled packet command set and DEVICE RESET */
1565 p[86] = RT_H2LE_U16(0);
1566 p[87] = RT_H2LE_U16(1 << 14);
1567 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, s->uATATransferMode)); /* UDMA modes supported / mode enabled */
1568 p[93] = RT_H2LE_U16((1 | 1 << 1) << ((s->iLUN & 1) == 0 ? 0 : 8) | 1 << 13 | 1 << 14);
1569 /* According to ATAPI-5 spec:
1570 *
1571 * The use of this word is optional.
1572 * If bits 7:0 of this word contain the signature A5h, bits 15:8
1573 * contain the data
1574 * structure checksum.
1575 * The data structure checksum is the twos complement of the sum of
1576 * all bytes in words 0 through 254 and the byte consisting of
1577 * bits 7:0 in word 255.
1578 * Each byte shall be added with unsigned arithmetic,
1579 * and overflow shall be ignored.
1580 * The sum of all 512 bytes is zero when the checksum is correct.
1581 */
1582 uint32_t uCsum = ataR3Checksum(p, 510);
1583 p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
1584
1585 s->iSourceSink = ATAFN_SS_NULL;
1586 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
1587 return false;
1588}
1589
1590
1591static void ataR3SetSignature(PATADEVSTATE s)
1592{
1593 s->uATARegSelect &= 0xf0; /* clear head */
1594 /* put signature */
1595 s->uATARegNSector = 1;
1596 s->uATARegSector = 1;
1597 if (s->fATAPI)
1598 {
1599 s->uATARegLCyl = 0x14;
1600 s->uATARegHCyl = 0xeb;
1601 }
1602 else
1603 {
1604 s->uATARegLCyl = 0;
1605 s->uATARegHCyl = 0;
1606 }
1607}
1608
1609
1610static uint64_t ataR3GetSector(PATADEVSTATE s)
1611{
1612 uint64_t iLBA;
1613 if (s->uATARegSelect & 0x40)
1614 {
1615 /* any LBA variant */
1616 if (s->fLBA48)
1617 {
1618 /* LBA48 */
1619 iLBA = ((uint64_t)s->uATARegHCylHOB << 40)
1620 | ((uint64_t)s->uATARegLCylHOB << 32)
1621 | ((uint64_t)s->uATARegSectorHOB << 24)
1622 | ((uint64_t)s->uATARegHCyl << 16)
1623 | ((uint64_t)s->uATARegLCyl << 8)
1624 | s->uATARegSector;
1625 }
1626 else
1627 {
1628 /* LBA */
1629 iLBA = ((uint32_t)(s->uATARegSelect & 0x0f) << 24)
1630 | ((uint32_t)s->uATARegHCyl << 16)
1631 | ((uint32_t)s->uATARegLCyl << 8)
1632 | s->uATARegSector;
1633 }
1634 }
1635 else
1636 {
1637 /* CHS */
1638 iLBA = (((uint32_t)s->uATARegHCyl << 8) | s->uATARegLCyl) * s->XCHSGeometry.cHeads * s->XCHSGeometry.cSectors
1639 + (s->uATARegSelect & 0x0f) * s->XCHSGeometry.cSectors
1640 + (s->uATARegSector - 1);
1641 LogFlowFunc(("CHS %u/%u/%u -> LBA %llu\n", ((uint32_t)s->uATARegHCyl << 8) | s->uATARegLCyl, s->uATARegSelect & 0x0f, s->uATARegSector, iLBA));
1642 }
1643 return iLBA;
1644}
1645
1646static void ataR3SetSector(PATADEVSTATE s, uint64_t iLBA)
1647{
1648 uint32_t cyl, r;
1649 if (s->uATARegSelect & 0x40)
1650 {
1651 /* any LBA variant */
1652 if (s->fLBA48)
1653 {
1654 /* LBA48 */
1655 s->uATARegHCylHOB = iLBA >> 40;
1656 s->uATARegLCylHOB = iLBA >> 32;
1657 s->uATARegSectorHOB = iLBA >> 24;
1658 s->uATARegHCyl = iLBA >> 16;
1659 s->uATARegLCyl = iLBA >> 8;
1660 s->uATARegSector = iLBA;
1661 }
1662 else
1663 {
1664 /* LBA */
1665 s->uATARegSelect = (s->uATARegSelect & 0xf0) | (iLBA >> 24);
1666 s->uATARegHCyl = (iLBA >> 16);
1667 s->uATARegLCyl = (iLBA >> 8);
1668 s->uATARegSector = (iLBA);
1669 }
1670 }
1671 else
1672 {
1673 /* CHS */
1674 AssertMsgReturnVoid(s->XCHSGeometry.cHeads && s->XCHSGeometry.cSectors, ("Device geometry not set!\n"));
1675 cyl = iLBA / (s->XCHSGeometry.cHeads * s->XCHSGeometry.cSectors);
1676 r = iLBA % (s->XCHSGeometry.cHeads * s->XCHSGeometry.cSectors);
1677 s->uATARegHCyl = cyl >> 8;
1678 s->uATARegLCyl = cyl;
1679 s->uATARegSelect = (s->uATARegSelect & 0xf0) | ((r / s->XCHSGeometry.cSectors) & 0x0f);
1680 s->uATARegSector = (r % s->XCHSGeometry.cSectors) + 1;
1681 LogFlowFunc(("LBA %llu -> CHS %u/%u/%u\n", iLBA, cyl, s->uATARegSelect & 0x0f, s->uATARegSector));
1682 }
1683}
1684
1685
1686static void ataR3WarningDiskFull(PPDMDEVINS pDevIns)
1687{
1688 int rc;
1689 LogRel(("PIIX3 ATA: Host disk full\n"));
1690 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_DISKFULL",
1691 N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
1692 AssertRC(rc);
1693}
1694
1695static void ataR3WarningFileTooBig(PPDMDEVINS pDevIns)
1696{
1697 int rc;
1698 LogRel(("PIIX3 ATA: File too big\n"));
1699 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_FILETOOBIG",
1700 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"));
1701 AssertRC(rc);
1702}
1703
1704static void ataR3WarningISCSI(PPDMDEVINS pDevIns)
1705{
1706 int rc;
1707 LogRel(("PIIX3 ATA: iSCSI target unavailable\n"));
1708 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_ISCSIDOWN",
1709 N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
1710 AssertRC(rc);
1711}
1712
1713static bool ataR3IsRedoSetWarning(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, int rc)
1714{
1715 Assert(!PDMDevHlpCritSectIsOwner(pDevIns, &pCtl->lock));
1716 if (rc == VERR_DISK_FULL)
1717 {
1718 pCtl->fRedoIdle = true;
1719 ataR3WarningDiskFull(pDevIns);
1720 return true;
1721 }
1722 if (rc == VERR_FILE_TOO_BIG)
1723 {
1724 pCtl->fRedoIdle = true;
1725 ataR3WarningFileTooBig(pDevIns);
1726 return true;
1727 }
1728 if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1729 {
1730 pCtl->fRedoIdle = true;
1731 /* iSCSI connection abort (first error) or failure to reestablish
1732 * connection (second error). Pause VM. On resume we'll retry. */
1733 ataR3WarningISCSI(pDevIns);
1734 return true;
1735 }
1736 if (rc == VERR_VD_DEK_MISSING)
1737 {
1738 /* Error message already set. */
1739 pCtl->fRedoIdle = true;
1740 return true;
1741 }
1742
1743 return false;
1744}
1745
1746
1747static int ataR3ReadSectors(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3,
1748 uint64_t u64Sector, void *pvBuf, uint32_t cSectors, bool *pfRedo)
1749{
1750 int rc;
1751 uint32_t const cbSector = s->cbSector;
1752 uint32_t cbToRead = cSectors * cbSector;
1753 Assert(pvBuf == &s->abIOBuffer[0]);
1754 AssertReturnStmt(cbToRead <= sizeof(s->abIOBuffer), *pfRedo = false, VERR_BUFFER_OVERFLOW);
1755
1756 ataR3LockLeave(pDevIns, pCtl);
1757
1758 STAM_PROFILE_ADV_START(&s->StatReads, r);
1759 s->Led.Asserted.s.fReading = s->Led.Actual.s.fReading = 1;
1760 rc = pDevR3->pDrvMedia->pfnRead(pDevR3->pDrvMedia, u64Sector * cbSector, pvBuf, cbToRead);
1761 s->Led.Actual.s.fReading = 0;
1762 STAM_PROFILE_ADV_STOP(&s->StatReads, r);
1763 Log4(("ataR3ReadSectors: rc=%Rrc cSectors=%#x u64Sector=%llu\n%.*Rhxd\n",
1764 rc, cSectors, u64Sector, cbToRead, pvBuf));
1765
1766 STAM_REL_COUNTER_ADD(&s->StatBytesRead, cbToRead);
1767
1768 if (RT_SUCCESS(rc))
1769 *pfRedo = false;
1770 else
1771 *pfRedo = ataR3IsRedoSetWarning(pDevIns, pCtl, rc);
1772
1773 ataR3LockEnter(pDevIns, pCtl);
1774 return rc;
1775}
1776
1777
1778static int ataR3WriteSectors(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3,
1779 uint64_t u64Sector, const void *pvBuf, uint32_t cSectors, bool *pfRedo)
1780{
1781 int rc;
1782 uint32_t const cbSector = s->cbSector;
1783 uint32_t cbToWrite = cSectors * cbSector;
1784 Assert(pvBuf == &s->abIOBuffer[0]);
1785 AssertReturnStmt(cbToWrite <= sizeof(s->abIOBuffer), *pfRedo = false, VERR_BUFFER_OVERFLOW);
1786
1787 ataR3LockLeave(pDevIns, pCtl);
1788
1789 STAM_PROFILE_ADV_START(&s->StatWrites, w);
1790 s->Led.Asserted.s.fWriting = s->Led.Actual.s.fWriting = 1;
1791# ifdef VBOX_INSTRUMENT_DMA_WRITES
1792 if (s->fDMA)
1793 STAM_PROFILE_ADV_START(&s->StatInstrVDWrites, vw);
1794# endif
1795 rc = pDevR3->pDrvMedia->pfnWrite(pDevR3->pDrvMedia, u64Sector * cbSector, pvBuf, cbToWrite);
1796# ifdef VBOX_INSTRUMENT_DMA_WRITES
1797 if (s->fDMA)
1798 STAM_PROFILE_ADV_STOP(&s->StatInstrVDWrites, vw);
1799# endif
1800 s->Led.Actual.s.fWriting = 0;
1801 STAM_PROFILE_ADV_STOP(&s->StatWrites, w);
1802 Log4(("ataR3WriteSectors: rc=%Rrc cSectors=%#x u64Sector=%llu\n%.*Rhxd\n",
1803 rc, cSectors, u64Sector, cbToWrite, pvBuf));
1804
1805 STAM_REL_COUNTER_ADD(&s->StatBytesWritten, cbToWrite);
1806
1807 if (RT_SUCCESS(rc))
1808 *pfRedo = false;
1809 else
1810 *pfRedo = ataR3IsRedoSetWarning(pDevIns, pCtl, rc);
1811
1812 ataR3LockEnter(pDevIns, pCtl);
1813 return rc;
1814}
1815
1816
1817/**
1818 * Begin Transfer: READ/WRITE SECTORS
1819 */
1820static void ataR3ReadWriteSectorsBT(PATACONTROLLER pCtl, PATADEVSTATE s)
1821{
1822 uint32_t const cbSector = RT_MAX(s->cbSector, 1);
1823 uint32_t cSectors;
1824
1825 cSectors = s->cbTotalTransfer / cbSector;
1826 if (cSectors > s->cSectorsPerIRQ)
1827 s->cbElementaryTransfer = s->cSectorsPerIRQ * cbSector;
1828 else
1829 s->cbElementaryTransfer = cSectors * cbSector;
1830 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE)
1831 ataR3CmdOK(pCtl, s, 0);
1832}
1833
1834
1835/**
1836 * Sink/Source: READ SECTORS
1837 */
1838static bool ataR3ReadSectorsSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
1839{
1840 uint32_t const cbSector = RT_MAX(s->cbSector, 1);
1841 uint32_t cSectors;
1842 uint64_t iLBA;
1843 bool fRedo;
1844 int rc;
1845
1846 cSectors = s->cbElementaryTransfer / cbSector;
1847 Assert(cSectors);
1848 iLBA = ataR3GetSector(s);
1849 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
1850 rc = ataR3ReadSectors(pDevIns, pCtl, s, pDevR3, iLBA, s->abIOBuffer, cSectors, &fRedo);
1851 if (RT_SUCCESS(rc))
1852 {
1853 /* When READ SECTORS etc. finishes, the address in the task
1854 * file register points at the last sector read, not at the next
1855 * sector that would be read. This ensures the registers always
1856 * contain a valid sector address.
1857 */
1858 if (s->cbElementaryTransfer == s->cbTotalTransfer)
1859 {
1860 s->iSourceSink = ATAFN_SS_NULL;
1861 ataR3SetSector(s, iLBA + cSectors - 1);
1862 }
1863 else
1864 ataR3SetSector(s, iLBA + cSectors);
1865 s->uATARegNSector -= cSectors;
1866 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
1867 }
1868 else
1869 {
1870 if (fRedo)
1871 return fRedo;
1872 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1873 LogRel(("PIIX3 ATA: LUN#%d: disk read error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
1874 s->iLUN, rc, iLBA, cSectors));
1875
1876 /*
1877 * Check if we got interrupted. We don't need to set status variables
1878 * because the request was aborted.
1879 */
1880 if (rc != VERR_INTERRUPTED)
1881 ataR3CmdError(pCtl, s, ID_ERR);
1882 }
1883 return false;
1884}
1885
1886
1887/**
1888 * Sink/Source: WRITE SECTOR
1889 */
1890static bool ataR3WriteSectorsSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
1891{
1892 uint32_t const cbSector = RT_MAX(s->cbSector, 1);
1893 uint64_t iLBA;
1894 uint32_t cSectors;
1895 bool fRedo;
1896 int rc;
1897
1898 cSectors = s->cbElementaryTransfer / cbSector;
1899 Assert(cSectors);
1900 iLBA = ataR3GetSector(s);
1901 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
1902 rc = ataR3WriteSectors(pDevIns, pCtl, s, pDevR3, iLBA, s->abIOBuffer, cSectors, &fRedo);
1903 if (RT_SUCCESS(rc))
1904 {
1905 ataR3SetSector(s, iLBA + cSectors);
1906 if (!s->cbTotalTransfer)
1907 s->iSourceSink = ATAFN_SS_NULL;
1908 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
1909 }
1910 else
1911 {
1912 if (fRedo)
1913 return fRedo;
1914 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1915 LogRel(("PIIX3 ATA: LUN#%d: disk write error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
1916 s->iLUN, rc, iLBA, cSectors));
1917
1918 /*
1919 * Check if we got interrupted. We don't need to set status variables
1920 * because the request was aborted.
1921 */
1922 if (rc != VERR_INTERRUPTED)
1923 ataR3CmdError(pCtl, s, ID_ERR);
1924 }
1925 return false;
1926}
1927
1928
1929static void atapiR3CmdOK(PATACONTROLLER pCtl, PATADEVSTATE s)
1930{
1931 s->uATARegError = 0;
1932 ataSetStatusValue(pCtl, s, ATA_STAT_READY);
1933 s->uATARegNSector = (s->uATARegNSector & ~7)
1934 | ((s->uTxDir != PDMMEDIATXDIR_TO_DEVICE) ? ATAPI_INT_REASON_IO : 0)
1935 | (!s->cbTotalTransfer ? ATAPI_INT_REASON_CD : 0);
1936 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
1937
1938 memset(s->abATAPISense, '\0', sizeof(s->abATAPISense));
1939 s->abATAPISense[0] = 0x70 | (1 << 7);
1940 s->abATAPISense[7] = 10;
1941}
1942
1943
1944static void atapiR3CmdError(PATACONTROLLER pCtl, PATADEVSTATE s, const uint8_t *pabATAPISense, size_t cbATAPISense)
1945{
1946 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, pabATAPISense[2] & 0x0f, SCSISenseText(pabATAPISense[2] & 0x0f),
1947 pabATAPISense[12], pabATAPISense[13], SCSISenseExtText(pabATAPISense[12], pabATAPISense[13])));
1948 s->uATARegError = pabATAPISense[2] << 4;
1949 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_ERR);
1950 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
1951 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
1952 memset(s->abATAPISense, '\0', sizeof(s->abATAPISense));
1953 memcpy(s->abATAPISense, pabATAPISense, RT_MIN(cbATAPISense, sizeof(s->abATAPISense)));
1954 s->cbTotalTransfer = 0;
1955 s->cbElementaryTransfer = 0;
1956 s->cbAtapiPassthroughTransfer = 0;
1957 s->iIOBufferCur = 0;
1958 s->iIOBufferEnd = 0;
1959 s->uTxDir = PDMMEDIATXDIR_NONE;
1960 s->iBeginTransfer = ATAFN_BT_NULL;
1961 s->iSourceSink = ATAFN_SS_NULL;
1962}
1963
1964
1965/** @todo deprecated function - doesn't provide enough info. Replace by direct
1966 * calls to atapiR3CmdError() with full data. */
1967static void atapiR3CmdErrorSimple(PATACONTROLLER pCtl, PATADEVSTATE s, uint8_t uATAPISenseKey, uint8_t uATAPIASC)
1968{
1969 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
1970 memset(abATAPISense, '\0', sizeof(abATAPISense));
1971 abATAPISense[0] = 0x70 | (1 << 7);
1972 abATAPISense[2] = uATAPISenseKey & 0x0f;
1973 abATAPISense[7] = 10;
1974 abATAPISense[12] = uATAPIASC;
1975 atapiR3CmdError(pCtl, s, abATAPISense, sizeof(abATAPISense));
1976}
1977
1978
1979/**
1980 * Begin Transfer: ATAPI command
1981 */
1982static void atapiR3CmdBT(PATACONTROLLER pCtl, PATADEVSTATE s)
1983{
1984 s->fATAPITransfer = true;
1985 s->cbElementaryTransfer = s->cbTotalTransfer;
1986 s->cbAtapiPassthroughTransfer = s->cbTotalTransfer;
1987 s->cbPIOTransferLimit = s->uATARegLCyl | (s->uATARegHCyl << 8);
1988 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE)
1989 atapiR3CmdOK(pCtl, s);
1990}
1991
1992
1993/**
1994 * Begin Transfer: ATAPI Passthrough command
1995 */
1996static void atapiR3PassthroughCmdBT(PATACONTROLLER pCtl, PATADEVSTATE s)
1997{
1998 atapiR3CmdBT(pCtl, s);
1999}
2000
2001
2002/**
2003 * Sink/Source: READ
2004 */
2005static bool atapiR3ReadSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2006{
2007 int rc;
2008 uint64_t cbBlockRegion = 0;
2009 VDREGIONDATAFORM enmDataForm;
2010
2011 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
2012 uint32_t const iATAPILBA = s->iATAPILBA;
2013 uint32_t const cbTransfer = RT_MIN(s->cbTotalTransfer, RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE));
2014 uint32_t const cbATAPISector = s->cbATAPISector;
2015 uint32_t const cSectors = cbTransfer / cbATAPISector;
2016 Assert(cSectors * cbATAPISector <= cbTransfer);
2017 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iATAPILBA));
2018 AssertLogRelReturn(cSectors * cbATAPISector <= sizeof(s->abIOBuffer), false);
2019
2020 ataR3LockLeave(pDevIns, pCtl);
2021
2022 rc = pDevR3->pDrvMedia->pfnQueryRegionPropertiesForLba(pDevR3->pDrvMedia, iATAPILBA, NULL, NULL,
2023 &cbBlockRegion, &enmDataForm);
2024 if (RT_SUCCESS(rc))
2025 {
2026 STAM_PROFILE_ADV_START(&s->StatReads, r);
2027 s->Led.Asserted.s.fReading = s->Led.Actual.s.fReading = 1;
2028
2029 /* If the region block size and requested sector matches we can just pass the request through. */
2030 if (cbBlockRegion == cbATAPISector)
2031 rc = pDevR3->pDrvMedia->pfnRead(pDevR3->pDrvMedia, (uint64_t)iATAPILBA * cbATAPISector,
2032 s->abIOBuffer, cbATAPISector * cSectors);
2033 else
2034 {
2035 uint32_t const iEndSector = iATAPILBA + cSectors;
2036 ASSERT_GUEST(iEndSector >= iATAPILBA);
2037 if (cbBlockRegion == 2048 && cbATAPISector == 2352)
2038 {
2039 /* Generate the sync bytes. */
2040 uint8_t *pbBuf = s->abIOBuffer;
2041
2042 for (uint32_t i = iATAPILBA; i < iEndSector; i++)
2043 {
2044 /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */
2045 *pbBuf++ = 0x00;
2046 memset(pbBuf, 0xff, 10);
2047 pbBuf += 10;
2048 *pbBuf++ = 0x00;
2049 /* MSF */
2050 scsiLBA2MSF(pbBuf, i);
2051 pbBuf += 3;
2052 *pbBuf++ = 0x01; /* mode 1 data */
2053 /* data */
2054 rc = pDevR3->pDrvMedia->pfnRead(pDevR3->pDrvMedia, (uint64_t)i * 2048, pbBuf, 2048);
2055 if (RT_FAILURE(rc))
2056 break;
2057 pbBuf += 2048;
2058 /**
2059 * @todo maybe compute ECC and parity, layout is:
2060 * 2072 4 EDC
2061 * 2076 172 P parity symbols
2062 * 2248 104 Q parity symbols
2063 */
2064 memset(pbBuf, 0, 280);
2065 pbBuf += 280;
2066 }
2067 }
2068 else if (cbBlockRegion == 2352 && cbATAPISector == 2048)
2069 {
2070 /* Read only the user data portion. */
2071 uint8_t *pbBuf = s->abIOBuffer;
2072
2073 for (uint32_t i = iATAPILBA; i < iEndSector; i++)
2074 {
2075 uint8_t abTmp[2352];
2076 uint8_t cbSkip;
2077
2078 rc = pDevR3->pDrvMedia->pfnRead(pDevR3->pDrvMedia, (uint64_t)i * 2352, &abTmp[0], 2352);
2079 if (RT_FAILURE(rc))
2080 break;
2081
2082 /* Mode 2 has an additional subheader before user data; we need to
2083 * skip 16 bytes for Mode 1 (sync + header) and 20 bytes for Mode 2 +
2084 * (sync + header + subheader).
2085 */
2086 switch (enmDataForm) {
2087 case VDREGIONDATAFORM_MODE2_2352:
2088 case VDREGIONDATAFORM_XA_2352:
2089 cbSkip = 24;
2090 break;
2091 case VDREGIONDATAFORM_MODE1_2352:
2092 cbSkip = 16;
2093 break;
2094 default:
2095 AssertMsgFailed(("Unexpected region form (%#u), using default skip value\n", enmDataForm));
2096 cbSkip = 16;
2097 }
2098 memcpy(pbBuf, &abTmp[cbSkip], 2048);
2099 pbBuf += 2048;
2100 }
2101 }
2102 else
2103 ASSERT_GUEST_MSG_FAILED(("Unsupported: cbBlockRegion=%u cbATAPISector=%u\n", cbBlockRegion, cbATAPISector));
2104 }
2105 s->Led.Actual.s.fReading = 0;
2106 STAM_PROFILE_ADV_STOP(&s->StatReads, r);
2107 }
2108
2109 ataR3LockEnter(pDevIns, pCtl);
2110
2111 if (RT_SUCCESS(rc))
2112 {
2113 STAM_REL_COUNTER_ADD(&s->StatBytesRead, cbATAPISector * cSectors);
2114
2115 /* The initial buffer end value has been set up based on the total
2116 * transfer size. But the I/O buffer size limits what can actually be
2117 * done in one transfer, so set the actual value of the buffer end. */
2118 s->cbElementaryTransfer = cbTransfer;
2119 if (cbTransfer >= s->cbTotalTransfer)
2120 s->iSourceSink = ATAFN_SS_NULL;
2121 atapiR3CmdOK(pCtl, s);
2122 s->iATAPILBA = iATAPILBA + cSectors;
2123 }
2124 else
2125 {
2126 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
2127 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM read error, %d sectors at LBA %d\n", s->iLUN, cSectors, iATAPILBA));
2128
2129 /*
2130 * Check if we got interrupted. We don't need to set status variables
2131 * because the request was aborted.
2132 */
2133 if (rc != VERR_INTERRUPTED)
2134 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_MEDIUM_ERROR, SCSI_ASC_READ_ERROR);
2135 }
2136 return false;
2137}
2138
2139/**
2140 * Sets the given media track type.
2141 */
2142static uint32_t ataR3MediumTypeSet(PATADEVSTATE s, uint32_t MediaTrackType)
2143{
2144 return ASMAtomicXchgU32(&s->MediaTrackType, MediaTrackType);
2145}
2146
2147
2148/**
2149 * Sink/Source: Passthrough
2150 */
2151static bool atapiR3PassthroughSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2152{
2153 int rc = VINF_SUCCESS;
2154 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
2155 uint32_t cbTransfer;
2156 PSTAMPROFILEADV pProf = NULL;
2157
2158 cbTransfer = RT_MIN(s->cbAtapiPassthroughTransfer, RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE));
2159
2160 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE)
2161 Log3(("ATAPI PT data write (%d): %.*Rhxs\n", cbTransfer, cbTransfer, s->abIOBuffer));
2162
2163 /* Simple heuristics: if there is at least one sector of data
2164 * to transfer, it's worth updating the LEDs. */
2165 if (cbTransfer >= 2048)
2166 {
2167 if (s->uTxDir != PDMMEDIATXDIR_TO_DEVICE)
2168 {
2169 s->Led.Asserted.s.fReading = s->Led.Actual.s.fReading = 1;
2170 pProf = &s->StatReads;
2171 }
2172 else
2173 {
2174 s->Led.Asserted.s.fWriting = s->Led.Actual.s.fWriting = 1;
2175 pProf = &s->StatWrites;
2176 }
2177 }
2178
2179 ataR3LockLeave(pDevIns, pCtl);
2180
2181# if defined(LOG_ENABLED)
2182 char szBuf[1024];
2183
2184 memset(szBuf, 0, sizeof(szBuf));
2185
2186 switch (s->abATAPICmd[0])
2187 {
2188 case SCSI_MODE_SELECT_10:
2189 {
2190 size_t cbBlkDescLength = scsiBE2H_U16(&s->abIOBuffer[6]);
2191
2192 SCSILogModePage(szBuf, sizeof(szBuf) - 1,
2193 s->abIOBuffer + 8 + cbBlkDescLength,
2194 cbTransfer - 8 - cbBlkDescLength);
2195 break;
2196 }
2197 case SCSI_SEND_CUE_SHEET:
2198 {
2199 SCSILogCueSheet(szBuf, sizeof(szBuf) - 1,
2200 s->abIOBuffer, cbTransfer);
2201 break;
2202 }
2203 default:
2204 break;
2205 }
2206
2207 Log2(("%s\n", szBuf));
2208# endif
2209
2210 if (pProf) { STAM_PROFILE_ADV_START(pProf, b); }
2211
2212 Assert(s->cbATAPISector);
2213 const uint32_t cbATAPISector = RT_MAX(s->cbATAPISector, 1); /* paranoia */
2214 const uint32_t cbIOBuffer = RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE); /* ditto */
2215
2216 if ( cbTransfer > SCSI_MAX_BUFFER_SIZE
2217 || s->cbElementaryTransfer > cbIOBuffer)
2218 {
2219 /* Linux accepts commands with up to 100KB of data, but expects
2220 * us to handle commands with up to 128KB of data. The usual
2221 * imbalance of powers. */
2222 uint8_t abATAPICmd[ATAPI_PACKET_SIZE];
2223 uint32_t iATAPILBA, cSectors, cReqSectors, cbCurrTX;
2224 uint8_t *pbBuf = s->abIOBuffer;
2225 uint32_t cSectorsMax; /**< Maximum amount of sectors to read without exceeding the I/O buffer. */
2226
2227 cSectorsMax = cbTransfer / cbATAPISector;
2228 AssertStmt(cSectorsMax * s->cbATAPISector <= cbIOBuffer, cSectorsMax = cbIOBuffer / cbATAPISector);
2229
2230 switch (s->abATAPICmd[0])
2231 {
2232 case SCSI_READ_10:
2233 case SCSI_WRITE_10:
2234 case SCSI_WRITE_AND_VERIFY_10:
2235 iATAPILBA = scsiBE2H_U32(s->abATAPICmd + 2);
2236 cSectors = scsiBE2H_U16(s->abATAPICmd + 7);
2237 break;
2238 case SCSI_READ_12:
2239 case SCSI_WRITE_12:
2240 iATAPILBA = scsiBE2H_U32(s->abATAPICmd + 2);
2241 cSectors = scsiBE2H_U32(s->abATAPICmd + 6);
2242 break;
2243 case SCSI_READ_CD:
2244 iATAPILBA = scsiBE2H_U32(s->abATAPICmd + 2);
2245 cSectors = scsiBE2H_U24(s->abATAPICmd + 6);
2246 break;
2247 case SCSI_READ_CD_MSF:
2248 iATAPILBA = scsiMSF2LBA(s->abATAPICmd + 3);
2249 cSectors = scsiMSF2LBA(s->abATAPICmd + 6) - iATAPILBA;
2250 break;
2251 default:
2252 AssertMsgFailed(("Don't know how to split command %#04x\n", s->abATAPICmd[0]));
2253 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
2254 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough split error\n", s->iLUN));
2255 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
2256 ataR3LockEnter(pDevIns, pCtl);
2257 return false;
2258 }
2259 cSectorsMax = RT_MIN(cSectorsMax, cSectors);
2260 memcpy(abATAPICmd, s->abATAPICmd, ATAPI_PACKET_SIZE);
2261 cReqSectors = 0;
2262 for (uint32_t i = cSectorsMax; i > 0; i -= cReqSectors)
2263 {
2264 if (i * cbATAPISector > SCSI_MAX_BUFFER_SIZE)
2265 cReqSectors = SCSI_MAX_BUFFER_SIZE / cbATAPISector;
2266 else
2267 cReqSectors = i;
2268 cbCurrTX = cbATAPISector * cReqSectors;
2269 switch (s->abATAPICmd[0])
2270 {
2271 case SCSI_READ_10:
2272 case SCSI_WRITE_10:
2273 case SCSI_WRITE_AND_VERIFY_10:
2274 scsiH2BE_U32(abATAPICmd + 2, iATAPILBA);
2275 scsiH2BE_U16(abATAPICmd + 7, cReqSectors);
2276 break;
2277 case SCSI_READ_12:
2278 case SCSI_WRITE_12:
2279 scsiH2BE_U32(abATAPICmd + 2, iATAPILBA);
2280 scsiH2BE_U32(abATAPICmd + 6, cReqSectors);
2281 break;
2282 case SCSI_READ_CD:
2283 scsiH2BE_U32(abATAPICmd + 2, iATAPILBA);
2284 scsiH2BE_U24(abATAPICmd + 6, cReqSectors);
2285 break;
2286 case SCSI_READ_CD_MSF:
2287 scsiLBA2MSF(abATAPICmd + 3, iATAPILBA);
2288 scsiLBA2MSF(abATAPICmd + 6, iATAPILBA + cReqSectors);
2289 break;
2290 }
2291 AssertLogRelReturn((uintptr_t)(pbBuf - &s->abIOBuffer[0]) + cbCurrTX <= sizeof(s->abIOBuffer), false);
2292 rc = pDevR3->pDrvMedia->pfnSendCmd(pDevR3->pDrvMedia, abATAPICmd, ATAPI_PACKET_SIZE, (PDMMEDIATXDIR)s->uTxDir,
2293 pbBuf, &cbCurrTX, abATAPISense, sizeof(abATAPISense), 30000 /**< @todo timeout */);
2294 if (rc != VINF_SUCCESS)
2295 break;
2296 iATAPILBA += cReqSectors;
2297 pbBuf += cbATAPISector * cReqSectors;
2298 }
2299
2300 if (RT_SUCCESS(rc))
2301 {
2302 /* Adjust ATAPI command for the next call. */
2303 switch (s->abATAPICmd[0])
2304 {
2305 case SCSI_READ_10:
2306 case SCSI_WRITE_10:
2307 case SCSI_WRITE_AND_VERIFY_10:
2308 scsiH2BE_U32(s->abATAPICmd + 2, iATAPILBA);
2309 scsiH2BE_U16(s->abATAPICmd + 7, cSectors - cSectorsMax);
2310 break;
2311 case SCSI_READ_12:
2312 case SCSI_WRITE_12:
2313 scsiH2BE_U32(s->abATAPICmd + 2, iATAPILBA);
2314 scsiH2BE_U32(s->abATAPICmd + 6, cSectors - cSectorsMax);
2315 break;
2316 case SCSI_READ_CD:
2317 scsiH2BE_U32(s->abATAPICmd + 2, iATAPILBA);
2318 scsiH2BE_U24(s->abATAPICmd + 6, cSectors - cSectorsMax);
2319 break;
2320 case SCSI_READ_CD_MSF:
2321 scsiLBA2MSF(s->abATAPICmd + 3, iATAPILBA);
2322 scsiLBA2MSF(s->abATAPICmd + 6, iATAPILBA + cSectors - cSectorsMax);
2323 break;
2324 default:
2325 AssertMsgFailed(("Don't know how to split command %#04x\n", s->abATAPICmd[0]));
2326 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
2327 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough split error\n", s->iLUN));
2328 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
2329 return false;
2330 }
2331 }
2332 }
2333 else
2334 {
2335 AssertLogRelReturn(cbTransfer <= sizeof(s->abIOBuffer), false);
2336 rc = pDevR3->pDrvMedia->pfnSendCmd(pDevR3->pDrvMedia, s->abATAPICmd, ATAPI_PACKET_SIZE, (PDMMEDIATXDIR)s->uTxDir,
2337 s->abIOBuffer, &cbTransfer, abATAPISense, sizeof(abATAPISense), 30000 /**< @todo timeout */);
2338 }
2339 if (pProf) { STAM_PROFILE_ADV_STOP(pProf, b); }
2340
2341 ataR3LockEnter(pDevIns, pCtl);
2342
2343 /* Update the LEDs and the read/write statistics. */
2344 if (cbTransfer >= 2048)
2345 {
2346 if (s->uTxDir != PDMMEDIATXDIR_TO_DEVICE)
2347 {
2348 s->Led.Actual.s.fReading = 0;
2349 STAM_REL_COUNTER_ADD(&s->StatBytesRead, cbTransfer);
2350 }
2351 else
2352 {
2353 s->Led.Actual.s.fWriting = 0;
2354 STAM_REL_COUNTER_ADD(&s->StatBytesWritten, cbTransfer);
2355 }
2356 }
2357
2358 if (RT_SUCCESS(rc))
2359 {
2360 /* Do post processing for certain commands. */
2361 switch (s->abATAPICmd[0])
2362 {
2363 case SCSI_SEND_CUE_SHEET:
2364 case SCSI_READ_TOC_PMA_ATIP:
2365 {
2366 if (!pDevR3->pTrackList)
2367 rc = ATAPIPassthroughTrackListCreateEmpty(&pDevR3->pTrackList);
2368
2369 if (RT_SUCCESS(rc))
2370 rc = ATAPIPassthroughTrackListUpdate(pDevR3->pTrackList, s->abATAPICmd, s->abIOBuffer, sizeof(s->abIOBuffer));
2371
2372 if ( RT_FAILURE(rc)
2373 && s->cErrors++ < MAX_LOG_REL_ERRORS)
2374 LogRel(("ATA: Error (%Rrc) while updating the tracklist during %s, burning the disc might fail\n",
2375 rc, s->abATAPICmd[0] == SCSI_SEND_CUE_SHEET ? "SEND CUE SHEET" : "READ TOC/PMA/ATIP"));
2376 break;
2377 }
2378 case SCSI_SYNCHRONIZE_CACHE:
2379 {
2380 if (pDevR3->pTrackList)
2381 ATAPIPassthroughTrackListClear(pDevR3->pTrackList);
2382 break;
2383 }
2384 }
2385
2386 if (s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE)
2387 {
2388 /*
2389 * Reply with the same amount of data as the real drive
2390 * but only if the command wasn't split.
2391 */
2392 if (s->cbAtapiPassthroughTransfer < cbIOBuffer)
2393 s->cbTotalTransfer = cbTransfer;
2394
2395 if ( s->abATAPICmd[0] == SCSI_INQUIRY
2396 && s->fOverwriteInquiry)
2397 {
2398 /* Make sure that the real drive cannot be identified.
2399 * Motivation: changing the VM configuration should be as
2400 * invisible as possible to the guest. */
2401 Log3(("ATAPI PT inquiry data before (%d): %.*Rhxs\n", cbTransfer, cbTransfer, s->abIOBuffer));
2402 scsiPadStr(&s->abIOBuffer[8], "VBOX", 8);
2403 scsiPadStr(&s->abIOBuffer[16], "CD-ROM", 16);
2404 scsiPadStr(&s->abIOBuffer[32], "1.0", 4);
2405 }
2406
2407 if (cbTransfer)
2408 Log3(("ATAPI PT data read (%d):\n%.*Rhxd\n", cbTransfer, cbTransfer, s->abIOBuffer));
2409 }
2410
2411 /* The initial buffer end value has been set up based on the total
2412 * transfer size. But the I/O buffer size limits what can actually be
2413 * done in one transfer, so set the actual value of the buffer end. */
2414 Assert(cbTransfer <= s->cbAtapiPassthroughTransfer);
2415 s->cbElementaryTransfer = cbTransfer;
2416 s->cbAtapiPassthroughTransfer -= cbTransfer;
2417 if (!s->cbAtapiPassthroughTransfer)
2418 {
2419 s->iSourceSink = ATAFN_SS_NULL;
2420 atapiR3CmdOK(pCtl, s);
2421 }
2422 }
2423 else
2424 {
2425 if (s->cErrors < MAX_LOG_REL_ERRORS)
2426 {
2427 uint8_t u8Cmd = s->abATAPICmd[0];
2428 do
2429 {
2430 /* don't log superfluous errors */
2431 if ( rc == VERR_DEV_IO_ERROR
2432 && ( u8Cmd == SCSI_TEST_UNIT_READY
2433 || u8Cmd == SCSI_READ_CAPACITY
2434 || u8Cmd == SCSI_READ_DVD_STRUCTURE
2435 || u8Cmd == SCSI_READ_TOC_PMA_ATIP))
2436 break;
2437 s->cErrors++;
2438 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough cmd=%#04x sense=%d ASC=%#02x ASCQ=%#02x %Rrc\n",
2439 s->iLUN, u8Cmd, abATAPISense[2] & 0x0f, abATAPISense[12], abATAPISense[13], rc));
2440 } while (0);
2441 }
2442 atapiR3CmdError(pCtl, s, abATAPISense, sizeof(abATAPISense));
2443 }
2444 return false;
2445}
2446
2447
2448/**
2449 * Begin Transfer: Read DVD structures
2450 */
2451static bool atapiR3ReadDVDStructureSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2452{
2453 uint8_t *buf = s->abIOBuffer;
2454 int media = s->abATAPICmd[1];
2455 int format = s->abATAPICmd[7];
2456 RT_NOREF(pDevIns, pDevR3);
2457
2458 AssertCompile(sizeof(s->abIOBuffer) > UINT16_MAX /* want a RT_MIN() below, but clang takes offence at always false stuff */);
2459 uint16_t max_len = scsiBE2H_U16(&s->abATAPICmd[8]);
2460 memset(buf, 0, max_len);
2461
2462 switch (format) {
2463 case 0x00:
2464 case 0x01:
2465 case 0x02:
2466 case 0x03:
2467 case 0x04:
2468 case 0x05:
2469 case 0x06:
2470 case 0x07:
2471 case 0x08:
2472 case 0x09:
2473 case 0x0a:
2474 case 0x0b:
2475 case 0x0c:
2476 case 0x0d:
2477 case 0x0e:
2478 case 0x0f:
2479 case 0x10:
2480 case 0x11:
2481 case 0x30:
2482 case 0x31:
2483 case 0xff:
2484 if (media == 0)
2485 {
2486 int uASC = SCSI_ASC_NONE;
2487
2488 switch (format)
2489 {
2490 case 0x0: /* Physical format information */
2491 {
2492 int layer = s->abATAPICmd[6];
2493 uint64_t total_sectors;
2494
2495 if (layer != 0)
2496 {
2497 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
2498 break;
2499 }
2500
2501 total_sectors = s->cTotalSectors;
2502 total_sectors >>= 2;
2503 if (total_sectors == 0)
2504 {
2505 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT;
2506 break;
2507 }
2508
2509 buf[4] = 1; /* DVD-ROM, part version 1 */
2510 buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */
2511 buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */
2512 buf[7] = 0; /* default densities */
2513
2514 /* FIXME: 0x30000 per spec? */
2515 scsiH2BE_U32(buf + 8, 0); /* start sector */
2516 scsiH2BE_U32(buf + 12, total_sectors - 1); /* end sector */
2517 scsiH2BE_U32(buf + 16, total_sectors - 1); /* l0 end sector */
2518
2519 /* Size of buffer, not including 2 byte size field */
2520 scsiH2BE_U32(&buf[0], 2048 + 2);
2521
2522 /* 2k data + 4 byte header */
2523 uASC = (2048 + 4);
2524 break;
2525 }
2526 case 0x01: /* DVD copyright information */
2527 buf[4] = 0; /* no copyright data */
2528 buf[5] = 0; /* no region restrictions */
2529
2530 /* Size of buffer, not including 2 byte size field */
2531 scsiH2BE_U16(buf, 4 + 2);
2532
2533 /* 4 byte header + 4 byte data */
2534 uASC = (4 + 4);
2535 break;
2536
2537 case 0x03: /* BCA information - invalid field for no BCA info */
2538 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
2539 break;
2540
2541 case 0x04: /* DVD disc manufacturing information */
2542 /* Size of buffer, not including 2 byte size field */
2543 scsiH2BE_U16(buf, 2048 + 2);
2544
2545 /* 2k data + 4 byte header */
2546 uASC = (2048 + 4);
2547 break;
2548 case 0xff:
2549 /*
2550 * This lists all the command capabilities above. Add new ones
2551 * in order and update the length and buffer return values.
2552 */
2553
2554 buf[4] = 0x00; /* Physical format */
2555 buf[5] = 0x40; /* Not writable, is readable */
2556 scsiH2BE_U16((buf + 6), 2048 + 4);
2557
2558 buf[8] = 0x01; /* Copyright info */
2559 buf[9] = 0x40; /* Not writable, is readable */
2560 scsiH2BE_U16((buf + 10), 4 + 4);
2561
2562 buf[12] = 0x03; /* BCA info */
2563 buf[13] = 0x40; /* Not writable, is readable */
2564 scsiH2BE_U16((buf + 14), 188 + 4);
2565
2566 buf[16] = 0x04; /* Manufacturing info */
2567 buf[17] = 0x40; /* Not writable, is readable */
2568 scsiH2BE_U16((buf + 18), 2048 + 4);
2569
2570 /* Size of buffer, not including 2 byte size field */
2571 scsiH2BE_U16(buf, 16 + 2);
2572
2573 /* data written + 4 byte header */
2574 uASC = (16 + 4);
2575 break;
2576 default: /** @todo formats beyond DVD-ROM requires */
2577 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET;
2578 }
2579
2580 if (uASC < 0)
2581 {
2582 s->iSourceSink = ATAFN_SS_NULL;
2583 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, -uASC);
2584 return false;
2585 }
2586 break;
2587 }
2588 /** @todo BD support, fall through for now */
2589 RT_FALL_THRU();
2590
2591 /* Generic disk structures */
2592 case 0x80: /** @todo AACS volume identifier */
2593 case 0x81: /** @todo AACS media serial number */
2594 case 0x82: /** @todo AACS media identifier */
2595 case 0x83: /** @todo AACS media key block */
2596 case 0x90: /** @todo List of recognized format layers */
2597 case 0xc0: /** @todo Write protection status */
2598 default:
2599 s->iSourceSink = ATAFN_SS_NULL;
2600 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
2601 return false;
2602 }
2603
2604 s->iSourceSink = ATAFN_SS_NULL;
2605 atapiR3CmdOK(pCtl, s);
2606 return false;
2607}
2608
2609
2610static bool atapiR3ReadSectors(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s,
2611 uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
2612{
2613 Assert(cSectors > 0);
2614 s->iATAPILBA = iATAPILBA;
2615 s->cbATAPISector = cbSector;
2616 ataR3StartTransfer(pDevIns, pCtl, s, cSectors * cbSector,
2617 PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ, true);
2618 return false;
2619}
2620
2621
2622/**
2623 * Sink/Source: ATAPI READ CAPACITY
2624 */
2625static bool atapiR3ReadCapacitySS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2626{
2627 uint8_t *pbBuf = s->abIOBuffer;
2628 RT_NOREF(pDevIns, pDevR3);
2629
2630 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
2631 Assert(s->cbElementaryTransfer <= 8);
2632 scsiH2BE_U32(pbBuf, s->cTotalSectors - 1);
2633 scsiH2BE_U32(pbBuf + 4, 2048);
2634 s->iSourceSink = ATAFN_SS_NULL;
2635 atapiR3CmdOK(pCtl, s);
2636 return false;
2637}
2638
2639
2640/**
2641 * Sink/Source: ATAPI READ DISCK INFORMATION
2642 */
2643static bool atapiR3ReadDiscInformationSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2644{
2645 uint8_t *pbBuf = s->abIOBuffer;
2646 RT_NOREF(pDevIns, pDevR3);
2647
2648 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
2649 Assert(s->cbElementaryTransfer <= 34);
2650 memset(pbBuf, '\0', 34);
2651 scsiH2BE_U16(pbBuf, 32);
2652 pbBuf[2] = (0 << 4) | (3 << 2) | (2 << 0); /* not erasable, complete session, complete disc */
2653 pbBuf[3] = 1; /* number of first track */
2654 pbBuf[4] = 1; /* number of sessions (LSB) */
2655 pbBuf[5] = 1; /* first track number in last session (LSB) */
2656 pbBuf[6] = (uint8_t)pDevR3->pDrvMedia->pfnGetRegionCount(pDevR3->pDrvMedia); /* last track number in last session (LSB) */
2657 pbBuf[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 */
2658 pbBuf[8] = 0; /* disc type = CD-ROM */
2659 pbBuf[9] = 0; /* number of sessions (MSB) */
2660 pbBuf[10] = 0; /* number of sessions (MSB) */
2661 pbBuf[11] = 0; /* number of sessions (MSB) */
2662 scsiH2BE_U32(pbBuf + 16, 0xffffffff); /* last session lead-in start time is not available */
2663 scsiH2BE_U32(pbBuf + 20, 0xffffffff); /* last possible start time for lead-out is not available */
2664 s->iSourceSink = ATAFN_SS_NULL;
2665 atapiR3CmdOK(pCtl, s);
2666 return false;
2667}
2668
2669
2670/**
2671 * Sink/Source: ATAPI READ TRACK INFORMATION
2672 */
2673static bool atapiR3ReadTrackInformationSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2674{
2675 uint8_t *pbBuf = s->abIOBuffer;
2676 uint32_t u32LogAddr = scsiBE2H_U32(&s->abATAPICmd[2]);
2677 uint8_t u8LogAddrType = s->abATAPICmd[1] & 0x03;
2678 RT_NOREF(pDevIns);
2679
2680 int rc;
2681 uint64_t u64LbaStart = 0;
2682 uint32_t uRegion = 0;
2683 uint64_t cBlocks = 0;
2684 uint64_t cbBlock = 0;
2685 uint8_t u8DataMode = 0xf; /* Unknown data mode. */
2686 uint8_t u8TrackMode = 0;
2687 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_INVALID;
2688
2689 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
2690 Assert(s->cbElementaryTransfer <= 36);
2691
2692 switch (u8LogAddrType)
2693 {
2694 case 0x00:
2695 rc = pDevR3->pDrvMedia->pfnQueryRegionPropertiesForLba(pDevR3->pDrvMedia, u32LogAddr, &uRegion,
2696 NULL, NULL, NULL);
2697 if (RT_SUCCESS(rc))
2698 rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, uRegion, &u64LbaStart,
2699 &cBlocks, &cbBlock, &enmDataForm);
2700 break;
2701 case 0x01:
2702 {
2703 if (u32LogAddr >= 1)
2704 {
2705 uRegion = u32LogAddr - 1;
2706 rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, uRegion, &u64LbaStart,
2707 &cBlocks, &cbBlock, &enmDataForm);
2708 }
2709 else
2710 rc = VERR_NOT_FOUND; /** @todo Return lead-in information. */
2711 break;
2712 }
2713 case 0x02:
2714 default:
2715 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
2716 return false;
2717 }
2718
2719 if (RT_FAILURE(rc))
2720 {
2721 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
2722 return false;
2723 }
2724
2725 switch (enmDataForm)
2726 {
2727 case VDREGIONDATAFORM_MODE1_2048:
2728 case VDREGIONDATAFORM_MODE1_2352:
2729 case VDREGIONDATAFORM_MODE1_0:
2730 u8DataMode = 1;
2731 break;
2732 case VDREGIONDATAFORM_XA_2336:
2733 case VDREGIONDATAFORM_XA_2352:
2734 case VDREGIONDATAFORM_XA_0:
2735 case VDREGIONDATAFORM_MODE2_2336:
2736 case VDREGIONDATAFORM_MODE2_2352:
2737 case VDREGIONDATAFORM_MODE2_0:
2738 u8DataMode = 2;
2739 break;
2740 default:
2741 u8DataMode = 0xf;
2742 }
2743
2744 if (enmDataForm == VDREGIONDATAFORM_CDDA)
2745 u8TrackMode = 0x0;
2746 else
2747 u8TrackMode = 0x4;
2748
2749 memset(pbBuf, '\0', 36);
2750 scsiH2BE_U16(pbBuf, 34);
2751 pbBuf[2] = uRegion + 1; /* track number (LSB) */
2752 pbBuf[3] = 1; /* session number (LSB) */
2753 pbBuf[5] = (0 << 5) | (0 << 4) | u8TrackMode; /* not damaged, primary copy, data track */
2754 pbBuf[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | u8DataMode; /* not reserved track, not blank, not packet writing, not fixed packet */
2755 pbBuf[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */
2756 scsiH2BE_U32(pbBuf + 8, (uint32_t)u64LbaStart); /* track start address is 0 */
2757 scsiH2BE_U32(pbBuf + 24, (uint32_t)cBlocks); /* track size */
2758 pbBuf[32] = 0; /* track number (MSB) */
2759 pbBuf[33] = 0; /* session number (MSB) */
2760 s->iSourceSink = ATAFN_SS_NULL;
2761 atapiR3CmdOK(pCtl, s);
2762 return false;
2763}
2764
2765static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureListProfiles(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2766{
2767 RT_NOREF(s);
2768 if (cbBuf < 3*4)
2769 return 0;
2770
2771 scsiH2BE_U16(pbBuf, 0x0); /* feature 0: list of profiles supported */
2772 pbBuf[2] = (0 << 2) | (1 << 1) | (1 << 0); /* version 0, persistent, current */
2773 pbBuf[3] = 8; /* additional bytes for profiles */
2774 /* The MMC-3 spec says that DVD-ROM read capability should be reported
2775 * before CD-ROM read capability. */
2776 scsiH2BE_U16(pbBuf + 4, 0x10); /* profile: read-only DVD */
2777 pbBuf[6] = (0 << 0); /* NOT current profile */
2778 scsiH2BE_U16(pbBuf + 8, 0x08); /* profile: read only CD */
2779 pbBuf[10] = (1 << 0); /* current profile */
2780
2781 return 3*4; /* Header + 2 profiles entries */
2782}
2783
2784static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureCore(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2785{
2786 RT_NOREF(s);
2787 if (cbBuf < 12)
2788 return 0;
2789
2790 scsiH2BE_U16(pbBuf, 0x1); /* feature 0001h: Core Feature */
2791 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
2792 pbBuf[3] = 8; /* Additional length */
2793 scsiH2BE_U16(pbBuf + 4, 0x00000002); /* Physical interface ATAPI. */
2794 pbBuf[8] = RT_BIT(0); /* DBE */
2795 /* Rest is reserved. */
2796
2797 return 12;
2798}
2799
2800static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureMorphing(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2801{
2802 RT_NOREF(s);
2803 if (cbBuf < 8)
2804 return 0;
2805
2806 scsiH2BE_U16(pbBuf, 0x2); /* feature 0002h: Morphing Feature */
2807 pbBuf[2] = (0x1 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
2808 pbBuf[3] = 4; /* Additional length */
2809 pbBuf[4] = RT_BIT(1) | 0x0; /* OCEvent | !ASYNC */
2810 /* Rest is reserved. */
2811
2812 return 8;
2813}
2814
2815static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureRemovableMedium(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2816{
2817 RT_NOREF(s);
2818 if (cbBuf < 8)
2819 return 0;
2820
2821 scsiH2BE_U16(pbBuf, 0x3); /* feature 0003h: Removable Medium Feature */
2822 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
2823 pbBuf[3] = 4; /* Additional length */
2824 /* Tray type loading | Load | Eject | !Pvnt Jmpr | !DBML | Lock */
2825 pbBuf[4] = (0x2 << 5) | RT_BIT(4) | RT_BIT(3) | (0x0 << 2) | (0x0 << 1) | RT_BIT(0);
2826 /* Rest is reserved. */
2827
2828 return 8;
2829}
2830
2831static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureRandomReadable (PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2832{
2833 RT_NOREF(s);
2834 if (cbBuf < 12)
2835 return 0;
2836
2837 scsiH2BE_U16(pbBuf, 0x10); /* feature 0010h: Random Readable Feature */
2838 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
2839 pbBuf[3] = 8; /* Additional length */
2840 scsiH2BE_U32(pbBuf + 4, 2048); /* Logical block size. */
2841 scsiH2BE_U16(pbBuf + 8, 0x10); /* Blocking (0x10 for DVD, CD is not defined). */
2842 pbBuf[10] = 0; /* PP not present */
2843 /* Rest is reserved. */
2844
2845 return 12;
2846}
2847
2848static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureCDRead(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2849{
2850 RT_NOREF(s);
2851 if (cbBuf < 8)
2852 return 0;
2853
2854 scsiH2BE_U16(pbBuf, 0x1e); /* feature 001Eh: CD Read Feature */
2855 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
2856 pbBuf[3] = 0; /* Additional length */
2857 pbBuf[4] = (0x0 << 7) | (0x0 << 1) | 0x0; /* !DAP | !C2-Flags | !CD-Text. */
2858 /* Rest is reserved. */
2859
2860 return 8;
2861}
2862
2863static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeaturePowerManagement(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2864{
2865 RT_NOREF(s);
2866 if (cbBuf < 4)
2867 return 0;
2868
2869 scsiH2BE_U16(pbBuf, 0x100); /* feature 0100h: Power Management Feature */
2870 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
2871 pbBuf[3] = 0; /* Additional length */
2872
2873 return 4;
2874}
2875
2876static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureTimeout(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf)
2877{
2878 RT_NOREF(s);
2879 if (cbBuf < 8)
2880 return 0;
2881
2882 scsiH2BE_U16(pbBuf, 0x105); /* feature 0105h: Timeout Feature */
2883 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */
2884 pbBuf[3] = 4; /* Additional length */
2885 pbBuf[4] = 0x0; /* !Group3 */
2886
2887 return 8;
2888}
2889
2890/**
2891 * Callback to fill in the correct data for a feature.
2892 *
2893 * @returns Number of bytes written into the buffer.
2894 * @param s The ATA device state.
2895 * @param pbBuf The buffer to fill the data with.
2896 * @param cbBuf Size of the buffer.
2897 */
2898typedef DECLCALLBACKTYPE(uint32_t, FNATAPIR3FEATUREFILL,(PATADEVSTATE s, uint8_t *pbBuf, size_t cbBuf));
2899/** Pointer to a feature fill callback. */
2900typedef FNATAPIR3FEATUREFILL *PFNATAPIR3FEATUREFILL;
2901
2902/**
2903 * ATAPI feature descriptor.
2904 */
2905typedef struct ATAPIR3FEATDESC
2906{
2907 /** The feature number. */
2908 uint16_t u16Feat;
2909 /** The callback to fill in the correct data. */
2910 PFNATAPIR3FEATUREFILL pfnFeatureFill;
2911} ATAPIR3FEATDESC;
2912
2913/**
2914 * Array of known ATAPI feature descriptors.
2915 */
2916static const ATAPIR3FEATDESC s_aAtapiR3Features[] =
2917{
2918 { 0x0000, atapiR3GetConfigurationFillFeatureListProfiles},
2919 { 0x0001, atapiR3GetConfigurationFillFeatureCore},
2920 { 0x0002, atapiR3GetConfigurationFillFeatureMorphing},
2921 { 0x0003, atapiR3GetConfigurationFillFeatureRemovableMedium},
2922 { 0x0010, atapiR3GetConfigurationFillFeatureRandomReadable},
2923 { 0x001e, atapiR3GetConfigurationFillFeatureCDRead},
2924 { 0x0100, atapiR3GetConfigurationFillFeaturePowerManagement},
2925 { 0x0105, atapiR3GetConfigurationFillFeatureTimeout}
2926};
2927
2928/**
2929 * Sink/Source: ATAPI GET CONFIGURATION
2930 */
2931static bool atapiR3GetConfigurationSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2932{
2933 uint32_t const cbIOBuffer = RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE);
2934 uint8_t *pbBuf = s->abIOBuffer;
2935 uint32_t cbBuf = cbIOBuffer;
2936 uint32_t cbCopied = 0;
2937 uint16_t u16Sfn = scsiBE2H_U16(&s->abATAPICmd[2]);
2938 uint8_t u8Rt = s->abATAPICmd[1] & 0x03;
2939 RT_NOREF(pDevIns, pDevR3);
2940
2941 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
2942 Assert(s->cbElementaryTransfer <= 80);
2943 /* Accept valid request types only. */
2944 if (u8Rt == 3)
2945 {
2946 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
2947 return false;
2948 }
2949 memset(pbBuf, '\0', cbBuf);
2950 /** @todo implement switching between CD-ROM and DVD-ROM profile (the only
2951 * way to differentiate them right now is based on the image size). */
2952 if (s->cTotalSectors)
2953 scsiH2BE_U16(pbBuf + 6, 0x08); /* current profile: read-only CD */
2954 else
2955 scsiH2BE_U16(pbBuf + 6, 0x00); /* current profile: none -> no media */
2956 cbBuf -= 8;
2957 pbBuf += 8;
2958
2959 if (u8Rt == 0x2)
2960 {
2961 for (uint32_t i = 0; i < RT_ELEMENTS(s_aAtapiR3Features); i++)
2962 {
2963 if (s_aAtapiR3Features[i].u16Feat == u16Sfn)
2964 {
2965 cbCopied = s_aAtapiR3Features[i].pfnFeatureFill(s, pbBuf, cbBuf);
2966 cbBuf -= cbCopied;
2967 pbBuf += cbCopied;
2968 break;
2969 }
2970 }
2971 }
2972 else
2973 {
2974 for (uint32_t i = 0; i < RT_ELEMENTS(s_aAtapiR3Features); i++)
2975 {
2976 if (s_aAtapiR3Features[i].u16Feat > u16Sfn)
2977 {
2978 cbCopied = s_aAtapiR3Features[i].pfnFeatureFill(s, pbBuf, cbBuf);
2979 cbBuf -= cbCopied;
2980 pbBuf += cbCopied;
2981 }
2982 }
2983 }
2984
2985 /* Set data length now - the field is not included in the final length. */
2986 scsiH2BE_U32(s->abIOBuffer, cbIOBuffer - cbBuf - 4);
2987
2988 /* Other profiles we might want to add in the future: 0x40 (BD-ROM) and 0x50 (HDDVD-ROM) */
2989 s->iSourceSink = ATAFN_SS_NULL;
2990 atapiR3CmdOK(pCtl, s);
2991 return false;
2992}
2993
2994
2995/**
2996 * Sink/Source: ATAPI GET EVENT STATUS NOTIFICATION
2997 */
2998static bool atapiR3GetEventStatusNotificationSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
2999{
3000 uint8_t *pbBuf = s->abIOBuffer;
3001 RT_NOREF(pDevIns, pDevR3);
3002
3003 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3004 Assert(s->cbElementaryTransfer <= 8);
3005
3006 if (!(s->abATAPICmd[1] & 1))
3007 {
3008 /* no asynchronous operation supported */
3009 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3010 return false;
3011 }
3012
3013 uint32_t OldStatus, NewStatus;
3014 do
3015 {
3016 OldStatus = ASMAtomicReadU32(&s->MediaEventStatus);
3017 NewStatus = ATA_EVENT_STATUS_UNCHANGED;
3018 switch (OldStatus)
3019 {
3020 case ATA_EVENT_STATUS_MEDIA_NEW:
3021 /* mount */
3022 scsiH2BE_U16(pbBuf + 0, 6);
3023 pbBuf[2] = 0x04; /* media */
3024 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3025 pbBuf[4] = 0x02; /* new medium */
3026 pbBuf[5] = 0x02; /* medium present / door closed */
3027 pbBuf[6] = 0x00;
3028 pbBuf[7] = 0x00;
3029 break;
3030
3031 case ATA_EVENT_STATUS_MEDIA_CHANGED:
3032 case ATA_EVENT_STATUS_MEDIA_REMOVED:
3033 /* umount */
3034 scsiH2BE_U16(pbBuf + 0, 6);
3035 pbBuf[2] = 0x04; /* media */
3036 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3037 pbBuf[4] = OldStatus == ATA_EVENT_STATUS_MEDIA_CHANGED ? 0x04 /* media changed */ : 0x03; /* media removed */
3038 pbBuf[5] = 0x00; /* medium absent / door closed */
3039 pbBuf[6] = 0x00;
3040 pbBuf[7] = 0x00;
3041 if (OldStatus == ATA_EVENT_STATUS_MEDIA_CHANGED)
3042 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW;
3043 break;
3044
3045 case ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED: /* currently unused */
3046 scsiH2BE_U16(pbBuf + 0, 6);
3047 pbBuf[2] = 0x04; /* media */
3048 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3049 pbBuf[4] = 0x01; /* eject requested (eject button pressed) */
3050 pbBuf[5] = 0x02; /* medium present / door closed */
3051 pbBuf[6] = 0x00;
3052 pbBuf[7] = 0x00;
3053 break;
3054
3055 case ATA_EVENT_STATUS_UNCHANGED:
3056 default:
3057 scsiH2BE_U16(pbBuf + 0, 6);
3058 pbBuf[2] = 0x01; /* operational change request / notification */
3059 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
3060 pbBuf[4] = 0x00;
3061 pbBuf[5] = 0x00;
3062 pbBuf[6] = 0x00;
3063 pbBuf[7] = 0x00;
3064 break;
3065 }
3066 } while (!ASMAtomicCmpXchgU32(&s->MediaEventStatus, NewStatus, OldStatus));
3067
3068 s->iSourceSink = ATAFN_SS_NULL;
3069 atapiR3CmdOK(pCtl, s);
3070 return false;
3071}
3072
3073
3074/**
3075 * Sink/Source: ATAPI INQUIRY
3076 */
3077static bool atapiR3InquirySS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3078{
3079 uint8_t *pbBuf = s->abIOBuffer;
3080 RT_NOREF(pDevIns, pDevR3);
3081
3082 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3083 Assert(s->cbElementaryTransfer <= 36);
3084 pbBuf[0] = 0x05; /* CD-ROM */
3085 pbBuf[1] = 0x80; /* removable */
3086# if 1/*ndef VBOX*/ /** @todo implement MESN + AENC. (async notification on removal and stuff.) */
3087 pbBuf[2] = 0x00; /* ISO */
3088 pbBuf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
3089# else
3090 pbBuf[2] = 0x00; /* ISO */
3091 pbBuf[3] = 0x91; /* format 1, MESN=1, AENC=9 ??? */
3092# endif
3093 pbBuf[4] = 31; /* additional length */
3094 pbBuf[5] = 0; /* reserved */
3095 pbBuf[6] = 0; /* reserved */
3096 pbBuf[7] = 0; /* reserved */
3097 scsiPadStr(pbBuf + 8, s->szInquiryVendorId, 8);
3098 scsiPadStr(pbBuf + 16, s->szInquiryProductId, 16);
3099 scsiPadStr(pbBuf + 32, s->szInquiryRevision, 4);
3100 s->iSourceSink = ATAFN_SS_NULL;
3101 atapiR3CmdOK(pCtl, s);
3102 return false;
3103}
3104
3105
3106/**
3107 * Sink/Source: ATAPI MODE SENSE ERROR RECOVERY
3108 */
3109static bool atapiR3ModeSenseErrorRecoverySS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3110{
3111 uint8_t *pbBuf = s->abIOBuffer;
3112 RT_NOREF(pDevIns, pDevR3);
3113
3114 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3115 Assert(s->cbElementaryTransfer <= 16);
3116 scsiH2BE_U16(&pbBuf[0], 16 + 6);
3117 pbBuf[2] = (uint8_t)s->MediaTrackType;
3118 pbBuf[3] = 0;
3119 pbBuf[4] = 0;
3120 pbBuf[5] = 0;
3121 pbBuf[6] = 0;
3122 pbBuf[7] = 0;
3123
3124 pbBuf[8] = 0x01;
3125 pbBuf[9] = 0x06;
3126 pbBuf[10] = 0x00; /* Maximum error recovery */
3127 pbBuf[11] = 0x05; /* 5 retries */
3128 pbBuf[12] = 0x00;
3129 pbBuf[13] = 0x00;
3130 pbBuf[14] = 0x00;
3131 pbBuf[15] = 0x00;
3132 s->iSourceSink = ATAFN_SS_NULL;
3133 atapiR3CmdOK(pCtl, s);
3134 return false;
3135}
3136
3137
3138/**
3139 * Sink/Source: ATAPI MODE SENSE CD STATUS
3140 */
3141static bool atapiR3ModeSenseCDStatusSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3142{
3143 uint8_t *pbBuf = s->abIOBuffer;
3144 RT_NOREF(pDevIns);
3145
3146 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3147 Assert(s->cbElementaryTransfer <= 40);
3148 scsiH2BE_U16(&pbBuf[0], 38);
3149 pbBuf[2] = (uint8_t)s->MediaTrackType;
3150 pbBuf[3] = 0;
3151 pbBuf[4] = 0;
3152 pbBuf[5] = 0;
3153 pbBuf[6] = 0;
3154 pbBuf[7] = 0;
3155
3156 pbBuf[8] = 0x2a;
3157 pbBuf[9] = 30; /* page length */
3158 pbBuf[10] = 0x08; /* DVD-ROM read support */
3159 pbBuf[11] = 0x00; /* no write support */
3160 /* The following claims we support audio play. This is obviously false,
3161 * but the Linux generic CDROM support makes many features depend on this
3162 * capability. If it's not set, this causes many things to be disabled. */
3163 pbBuf[12] = 0x71; /* multisession support, mode 2 form 1/2 support, audio play */
3164 pbBuf[13] = 0x00; /* no subchannel reads supported */
3165 pbBuf[14] = (1 << 0) | (1 << 3) | (1 << 5); /* lock supported, eject supported, tray type loading mechanism */
3166 if (pDevR3->pDrvMount->pfnIsLocked(pDevR3->pDrvMount))
3167 pbBuf[14] |= 1 << 1; /* report lock state */
3168 pbBuf[15] = 0; /* no subchannel reads supported, no separate audio volume control, no changer etc. */
3169 scsiH2BE_U16(&pbBuf[16], 5632); /* (obsolete) claim 32x speed support */
3170 scsiH2BE_U16(&pbBuf[18], 2); /* number of audio volume levels */
3171 scsiH2BE_U16(&pbBuf[20], RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE) / _1K); /* buffer size supported in Kbyte */
3172 scsiH2BE_U16(&pbBuf[22], 5632); /* (obsolete) current read speed 32x */
3173 pbBuf[24] = 0; /* reserved */
3174 pbBuf[25] = 0; /* reserved for digital audio (see idx 15) */
3175 scsiH2BE_U16(&pbBuf[26], 0); /* (obsolete) maximum write speed */
3176 scsiH2BE_U16(&pbBuf[28], 0); /* (obsolete) current write speed */
3177 scsiH2BE_U16(&pbBuf[30], 0); /* copy management revision supported 0=no CSS */
3178 pbBuf[32] = 0; /* reserved */
3179 pbBuf[33] = 0; /* reserved */
3180 pbBuf[34] = 0; /* reserved */
3181 pbBuf[35] = 1; /* rotation control CAV */
3182 scsiH2BE_U16(&pbBuf[36], 0); /* current write speed */
3183 scsiH2BE_U16(&pbBuf[38], 0); /* number of write speed performance descriptors */
3184 s->iSourceSink = ATAFN_SS_NULL;
3185 atapiR3CmdOK(pCtl, s);
3186 return false;
3187}
3188
3189
3190/**
3191 * Sink/Source: ATAPI REQUEST SENSE
3192 */
3193static bool atapiR3RequestSenseSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3194{
3195 uint8_t *pbBuf = s->abIOBuffer;
3196 RT_NOREF(pDevIns, pDevR3);
3197
3198 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3199 memset(pbBuf, '\0', RT_MIN(s->cbElementaryTransfer, sizeof(s->abIOBuffer)));
3200 AssertCompile(sizeof(s->abIOBuffer) >= sizeof(s->abATAPISense));
3201 memcpy(pbBuf, s->abATAPISense, RT_MIN(s->cbElementaryTransfer, sizeof(s->abATAPISense)));
3202 s->iSourceSink = ATAFN_SS_NULL;
3203 atapiR3CmdOK(pCtl, s);
3204 return false;
3205}
3206
3207
3208/**
3209 * Sink/Source: ATAPI MECHANISM STATUS
3210 */
3211static bool atapiR3MechanismStatusSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3212{
3213 uint8_t *pbBuf = s->abIOBuffer;
3214 RT_NOREF(pDevIns, pDevR3);
3215
3216 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3217 Assert(s->cbElementaryTransfer <= 8);
3218 scsiH2BE_U16(pbBuf, 0);
3219 /* no current LBA */
3220 pbBuf[2] = 0;
3221 pbBuf[3] = 0;
3222 pbBuf[4] = 0;
3223 pbBuf[5] = 1;
3224 scsiH2BE_U16(pbBuf + 6, 0);
3225 s->iSourceSink = ATAFN_SS_NULL;
3226 atapiR3CmdOK(pCtl, s);
3227 return false;
3228}
3229
3230
3231/**
3232 * Sink/Source: ATAPI READ TOC NORMAL
3233 */
3234static bool atapiR3ReadTOCNormalSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3235{
3236 uint8_t *pbBuf = s->abIOBuffer;
3237 uint8_t *q;
3238 uint8_t iStartTrack;
3239 bool fMSF;
3240 uint32_t cbSize;
3241 RT_NOREF(pDevIns);
3242
3243 /* Track fields are 8-bit and 1-based, so cut the track count at 255,
3244 avoiding any potentially buffer overflow issues below. */
3245 uint32_t cTracks = pDevR3->pDrvMedia->pfnGetRegionCount(pDevR3->pDrvMedia);
3246 AssertStmt(cTracks <= UINT8_MAX, cTracks = UINT8_MAX);
3247 AssertCompile(sizeof(s->abIOBuffer) >= 2 + 256 + 8);
3248
3249 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3250 fMSF = (s->abATAPICmd[1] >> 1) & 1;
3251 iStartTrack = s->abATAPICmd[6];
3252 if (iStartTrack == 0)
3253 iStartTrack = 1;
3254
3255 if (iStartTrack > cTracks && iStartTrack != 0xaa)
3256 {
3257 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3258 return false;
3259 }
3260 q = pbBuf + 2;
3261 *q++ = iStartTrack; /* first track number */
3262 *q++ = cTracks; /* last track number */
3263 for (uint32_t iTrack = iStartTrack; iTrack <= cTracks; iTrack++)
3264 {
3265 uint64_t uLbaStart = 0;
3266 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048;
3267
3268 int rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, iTrack - 1, &uLbaStart,
3269 NULL, NULL, &enmDataForm);
3270 AssertRC(rc);
3271
3272 *q++ = 0; /* reserved */
3273
3274 if (enmDataForm == VDREGIONDATAFORM_CDDA)
3275 *q++ = 0x10; /* ADR, control */
3276 else
3277 *q++ = 0x14; /* ADR, control */
3278
3279 *q++ = (uint8_t)iTrack; /* track number */
3280 *q++ = 0; /* reserved */
3281 if (fMSF)
3282 {
3283 *q++ = 0; /* reserved */
3284 scsiLBA2MSF(q, (uint32_t)uLbaStart);
3285 q += 3;
3286 }
3287 else
3288 {
3289 /* sector 0 */
3290 scsiH2BE_U32(q, (uint32_t)uLbaStart);
3291 q += 4;
3292 }
3293 }
3294 /* lead out track */
3295 *q++ = 0; /* reserved */
3296 *q++ = 0x14; /* ADR, control */
3297 *q++ = 0xaa; /* track number */
3298 *q++ = 0; /* reserved */
3299
3300 /* Query start and length of last track to get the start of the lead out track. */
3301 uint64_t uLbaStart = 0;
3302 uint64_t cBlocks = 0;
3303
3304 int rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, cTracks - 1, &uLbaStart,
3305 &cBlocks, NULL, NULL);
3306 AssertRC(rc);
3307
3308 uLbaStart += cBlocks;
3309 if (fMSF)
3310 {
3311 *q++ = 0; /* reserved */
3312 scsiLBA2MSF(q, (uint32_t)uLbaStart);
3313 q += 3;
3314 }
3315 else
3316 {
3317 scsiH2BE_U32(q, (uint32_t)uLbaStart);
3318 q += 4;
3319 }
3320 cbSize = q - pbBuf;
3321 scsiH2BE_U16(pbBuf, cbSize - 2);
3322 if (cbSize < s->cbTotalTransfer)
3323 s->cbTotalTransfer = cbSize;
3324 s->iSourceSink = ATAFN_SS_NULL;
3325 atapiR3CmdOK(pCtl, s);
3326 return false;
3327}
3328
3329
3330/**
3331 * Sink/Source: ATAPI READ TOC MULTI
3332 */
3333static bool atapiR3ReadTOCMultiSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3334{
3335 uint8_t *pbBuf = s->abIOBuffer;
3336 bool fMSF;
3337 RT_NOREF(pDevIns);
3338
3339 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3340 Assert(s->cbElementaryTransfer <= 12);
3341 fMSF = (s->abATAPICmd[1] >> 1) & 1;
3342 /* multi session: only a single session defined */
3343 /** @todo double-check this stuff against what a real drive says for a CD-ROM (not a CD-R)
3344 * with only a single data session. Maybe solve the problem with "cdrdao read-toc" not being
3345 * able to figure out whether numbers are in BCD or hex. */
3346 memset(pbBuf, 0, 12);
3347 pbBuf[1] = 0x0a;
3348 pbBuf[2] = 0x01;
3349 pbBuf[3] = 0x01;
3350
3351 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048;
3352 int rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, 0, NULL, NULL, NULL, &enmDataForm);
3353 AssertRC(rc);
3354
3355 if (enmDataForm == VDREGIONDATAFORM_CDDA)
3356 pbBuf[5] = 0x10; /* ADR, control */
3357 else
3358 pbBuf[5] = 0x14; /* ADR, control */
3359
3360 pbBuf[6] = 1; /* first track in last complete session */
3361 if (fMSF)
3362 {
3363 pbBuf[8] = 0; /* reserved */
3364 scsiLBA2MSF(&pbBuf[9], 0);
3365 }
3366 else
3367 {
3368 /* sector 0 */
3369 scsiH2BE_U32(pbBuf + 8, 0);
3370 }
3371 s->iSourceSink = ATAFN_SS_NULL;
3372 atapiR3CmdOK(pCtl, s);
3373 return false;
3374}
3375
3376
3377/**
3378 * Sink/Source: ATAPI READ TOC RAW
3379 */
3380static bool atapiR3ReadTOCRawSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3381{
3382 uint8_t *pbBuf = s->abIOBuffer;
3383 uint8_t *q;
3384 uint8_t iStartTrack;
3385 bool fMSF;
3386 uint32_t cbSize;
3387 RT_NOREF(pDevIns, pDevR3);
3388
3389 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3390 fMSF = (s->abATAPICmd[1] >> 1) & 1;
3391 iStartTrack = s->abATAPICmd[6];
3392
3393 q = pbBuf + 2;
3394 *q++ = 1; /* first session */
3395 *q++ = 1; /* last session */
3396
3397 *q++ = 1; /* session number */
3398 *q++ = 0x14; /* data track */
3399 *q++ = 0; /* track number */
3400 *q++ = 0xa0; /* first track in program area */
3401 *q++ = 0; /* min */
3402 *q++ = 0; /* sec */
3403 *q++ = 0; /* frame */
3404 *q++ = 0;
3405 *q++ = 1; /* first track */
3406 *q++ = 0x00; /* disk type CD-DA or CD data */
3407 *q++ = 0;
3408
3409 *q++ = 1; /* session number */
3410 *q++ = 0x14; /* data track */
3411 *q++ = 0; /* track number */
3412 *q++ = 0xa1; /* last track in program area */
3413 *q++ = 0; /* min */
3414 *q++ = 0; /* sec */
3415 *q++ = 0; /* frame */
3416 *q++ = 0;
3417 *q++ = 1; /* last track */
3418 *q++ = 0;
3419 *q++ = 0;
3420
3421 *q++ = 1; /* session number */
3422 *q++ = 0x14; /* data track */
3423 *q++ = 0; /* track number */
3424 *q++ = 0xa2; /* lead-out */
3425 *q++ = 0; /* min */
3426 *q++ = 0; /* sec */
3427 *q++ = 0; /* frame */
3428 if (fMSF)
3429 {
3430 *q++ = 0; /* reserved */
3431 scsiLBA2MSF(q, s->cTotalSectors);
3432 q += 3;
3433 }
3434 else
3435 {
3436 scsiH2BE_U32(q, s->cTotalSectors);
3437 q += 4;
3438 }
3439
3440 *q++ = 1; /* session number */
3441 *q++ = 0x14; /* ADR, control */
3442 *q++ = 0; /* track number */
3443 *q++ = 1; /* point */
3444 *q++ = 0; /* min */
3445 *q++ = 0; /* sec */
3446 *q++ = 0; /* frame */
3447 if (fMSF)
3448 {
3449 *q++ = 0; /* reserved */
3450 scsiLBA2MSF(q, 0);
3451 q += 3;
3452 }
3453 else
3454 {
3455 /* sector 0 */
3456 scsiH2BE_U32(q, 0);
3457 q += 4;
3458 }
3459
3460 cbSize = q - pbBuf;
3461 scsiH2BE_U16(pbBuf, cbSize - 2);
3462 if (cbSize < s->cbTotalTransfer)
3463 s->cbTotalTransfer = cbSize;
3464 s->iSourceSink = ATAFN_SS_NULL;
3465 atapiR3CmdOK(pCtl, s);
3466 return false;
3467}
3468
3469
3470static void atapiR3ParseCmdVirtualATAPI(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3471{
3472 const uint8_t *pbPacket = s->abATAPICmd;
3473 uint32_t cbMax;
3474 uint32_t cSectors, iATAPILBA;
3475
3476 switch (pbPacket[0])
3477 {
3478 case SCSI_TEST_UNIT_READY:
3479 if (s->cNotifiedMediaChange > 0)
3480 {
3481 if (s->cNotifiedMediaChange-- > 2)
3482 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3483 else
3484 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3485 }
3486 else if (pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3487 atapiR3CmdOK(pCtl, s);
3488 else
3489 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3490 break;
3491 case SCSI_GET_EVENT_STATUS_NOTIFICATION:
3492 cbMax = scsiBE2H_U16(pbPacket + 7);
3493 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
3494 break;
3495 case SCSI_MODE_SENSE_10:
3496 {
3497 uint8_t uPageControl, uPageCode;
3498 cbMax = scsiBE2H_U16(pbPacket + 7);
3499 uPageControl = pbPacket[2] >> 6;
3500 uPageCode = pbPacket[2] & 0x3f;
3501 switch (uPageControl)
3502 {
3503 case SCSI_PAGECONTROL_CURRENT:
3504 switch (uPageCode)
3505 {
3506 case SCSI_MODEPAGE_ERROR_RECOVERY:
3507 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 16), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true);
3508 break;
3509 case SCSI_MODEPAGE_CD_STATUS:
3510 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 40), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
3511 break;
3512 default:
3513 goto error_cmd;
3514 }
3515 break;
3516 case SCSI_PAGECONTROL_CHANGEABLE:
3517 goto error_cmd;
3518 case SCSI_PAGECONTROL_DEFAULT:
3519 goto error_cmd;
3520 default:
3521 case SCSI_PAGECONTROL_SAVED:
3522 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
3523 break;
3524 }
3525 break;
3526 }
3527 case SCSI_REQUEST_SENSE:
3528 cbMax = pbPacket[4];
3529 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
3530 break;
3531 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
3532 if (pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3533 {
3534 if (pbPacket[4] & 1)
3535 pDevR3->pDrvMount->pfnLock(pDevR3->pDrvMount);
3536 else
3537 pDevR3->pDrvMount->pfnUnlock(pDevR3->pDrvMount);
3538 atapiR3CmdOK(pCtl, s);
3539 }
3540 else
3541 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3542 break;
3543 case SCSI_READ_10:
3544 case SCSI_READ_12:
3545 {
3546 if (s->cNotifiedMediaChange > 0)
3547 {
3548 s->cNotifiedMediaChange-- ;
3549 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3550 break;
3551 }
3552 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3553 {
3554 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3555 break;
3556 }
3557 if (pbPacket[0] == SCSI_READ_10)
3558 cSectors = scsiBE2H_U16(pbPacket + 7);
3559 else
3560 cSectors = scsiBE2H_U32(pbPacket + 6);
3561 iATAPILBA = scsiBE2H_U32(pbPacket + 2);
3562
3563 if (cSectors == 0)
3564 {
3565 atapiR3CmdOK(pCtl, s);
3566 break;
3567 }
3568
3569 /* Check that the sector size is valid. */
3570 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_INVALID;
3571 int rc = pDevR3->pDrvMedia->pfnQueryRegionPropertiesForLba(pDevR3->pDrvMedia, iATAPILBA,
3572 NULL, NULL, NULL, &enmDataForm);
3573 if (RT_UNLIKELY( rc == VERR_NOT_FOUND
3574 || ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)))
3575 {
3576 /* Rate limited logging, one log line per second. For
3577 * guests that insist on reading from places outside the
3578 * valid area this often generates too many release log
3579 * entries otherwise. */
3580 static uint64_t uLastLogTS = 0;
3581 if (RTTimeMilliTS() >= uLastLogTS + 1000)
3582 {
3583 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
3584 uLastLogTS = RTTimeMilliTS();
3585 }
3586 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
3587 break;
3588 }
3589 else if ( enmDataForm != VDREGIONDATAFORM_MODE1_2048
3590 && enmDataForm != VDREGIONDATAFORM_MODE1_2352
3591 && enmDataForm != VDREGIONDATAFORM_MODE2_2336
3592 && enmDataForm != VDREGIONDATAFORM_MODE2_2352
3593 && enmDataForm != VDREGIONDATAFORM_RAW)
3594 {
3595 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
3596 RT_ZERO(abATAPISense);
3597
3598 abATAPISense[0] = 0x70 | (1 << 7);
3599 abATAPISense[2] = (SCSI_SENSE_ILLEGAL_REQUEST & 0x0f) | SCSI_SENSE_FLAG_ILI;
3600 scsiH2BE_U32(&abATAPISense[3], iATAPILBA);
3601 abATAPISense[7] = 10;
3602 abATAPISense[12] = SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK;
3603 atapiR3CmdError(pCtl, s, &abATAPISense[0], sizeof(abATAPISense));
3604 break;
3605 }
3606 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2048);
3607 break;
3608 }
3609 case SCSI_READ_CD_MSF:
3610 case SCSI_READ_CD:
3611 {
3612 if (s->cNotifiedMediaChange > 0)
3613 {
3614 s->cNotifiedMediaChange-- ;
3615 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3616 break;
3617 }
3618 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3619 {
3620 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3621 break;
3622 }
3623 if ((pbPacket[10] & 0x7) != 0)
3624 {
3625 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3626 break;
3627 }
3628 if (pbPacket[0] == SCSI_READ_CD)
3629 {
3630 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
3631 iATAPILBA = scsiBE2H_U32(pbPacket + 2);
3632 }
3633 else /* READ CD MSF */
3634 {
3635 iATAPILBA = scsiMSF2LBA(pbPacket + 3);
3636 if (iATAPILBA > scsiMSF2LBA(pbPacket + 6))
3637 {
3638 Log2(("Start MSF %02u:%02u:%02u > end MSF %02u:%02u:%02u!\n", *(pbPacket + 3), *(pbPacket + 4), *(pbPacket + 5),
3639 *(pbPacket + 6), *(pbPacket + 7), *(pbPacket + 8)));
3640 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3641 break;
3642 }
3643 cSectors = scsiMSF2LBA(pbPacket + 6) - iATAPILBA;
3644 Log2(("Start MSF %02u:%02u:%02u -> LBA %u\n", *(pbPacket + 3), *(pbPacket + 4), *(pbPacket + 5), iATAPILBA));
3645 Log2(("End MSF %02u:%02u:%02u -> %u sectors\n", *(pbPacket + 6), *(pbPacket + 7), *(pbPacket + 8), cSectors));
3646 }
3647 if (cSectors == 0)
3648 {
3649 atapiR3CmdOK(pCtl, s);
3650 break;
3651 }
3652 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
3653 {
3654 /* Rate limited logging, one log line per second. For
3655 * guests that insist on reading from places outside the
3656 * valid area this often generates too many release log
3657 * entries otherwise. */
3658 static uint64_t uLastLogTS = 0;
3659 if (RTTimeMilliTS() >= uLastLogTS + 1000)
3660 {
3661 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
3662 uLastLogTS = RTTimeMilliTS();
3663 }
3664 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
3665 break;
3666 }
3667 /*
3668 * If the LBA is in an audio track we are required to ignore pretty much all
3669 * of the channel selection values (except 0x00) and map everything to 0x10
3670 * which means read user data with a sector size of 2352 bytes.
3671 *
3672 * (MMC-6 chapter 6.19.2.6)
3673 */
3674 uint8_t uChnSel = pbPacket[9] & 0xf8;
3675 VDREGIONDATAFORM enmDataForm;
3676 int rc = pDevR3->pDrvMedia->pfnQueryRegionPropertiesForLba(pDevR3->pDrvMedia, iATAPILBA,
3677 NULL, NULL, NULL, &enmDataForm);
3678 AssertRC(rc);
3679
3680 if (enmDataForm == VDREGIONDATAFORM_CDDA)
3681 {
3682 if (uChnSel == 0)
3683 {
3684 /* nothing */
3685 atapiR3CmdOK(pCtl, s);
3686 }
3687 else
3688 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2352);
3689 }
3690 else
3691 {
3692 switch (uChnSel)
3693 {
3694 case 0x00:
3695 /* nothing */
3696 atapiR3CmdOK(pCtl, s);
3697 break;
3698 case 0x10:
3699 /* normal read */
3700 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2048);
3701 break;
3702 case 0xf8:
3703 /* read all data */
3704 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2352);
3705 break;
3706 default:
3707 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8));
3708 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3709 break;
3710 }
3711 }
3712 break;
3713 }
3714 case SCSI_SEEK_10:
3715 {
3716 if (s->cNotifiedMediaChange > 0)
3717 {
3718 s->cNotifiedMediaChange-- ;
3719 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3720 break;
3721 }
3722 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3723 {
3724 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3725 break;
3726 }
3727 iATAPILBA = scsiBE2H_U32(pbPacket + 2);
3728 if (iATAPILBA > s->cTotalSectors)
3729 {
3730 /* Rate limited logging, one log line per second. For
3731 * guests that insist on seeking to places outside the
3732 * valid area this often generates too many release log
3733 * entries otherwise. */
3734 static uint64_t uLastLogTS = 0;
3735 if (RTTimeMilliTS() >= uLastLogTS + 1000)
3736 {
3737 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA));
3738 uLastLogTS = RTTimeMilliTS();
3739 }
3740 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
3741 break;
3742 }
3743 atapiR3CmdOK(pCtl, s);
3744 ataSetStatus(pCtl, s, ATA_STAT_SEEK); /* Linux expects this. */
3745 break;
3746 }
3747 case SCSI_START_STOP_UNIT:
3748 {
3749 int rc = VINF_SUCCESS;
3750 switch (pbPacket[4] & 3)
3751 {
3752 case 0: /* 00 - Stop motor */
3753 case 1: /* 01 - Start motor */
3754 break;
3755 case 2: /* 10 - Eject media */
3756 {
3757 /* This must be done from EMT. */
3758 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
3759
3760 ataR3LockLeave(pDevIns, pCtl);
3761 rc = PDMDevHlpVMReqPriorityCallWait(pDevIns, VMCPUID_ANY,
3762 (PFNRT)pDevR3->pDrvMount->pfnUnmount, 3,
3763 pDevR3->pDrvMount, false /*=fForce*/, true /*=fEject*/);
3764 Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc == VERR_PDM_MEDIA_NOT_MOUNTED);
3765 if (RT_SUCCESS(rc) && pThisCC->pMediaNotify)
3766 {
3767 rc = PDMDevHlpVMReqCallNoWait(pDevIns, VMCPUID_ANY,
3768 (PFNRT)pThisCC->pMediaNotify->pfnEjected, 2,
3769 pThisCC->pMediaNotify, s->iLUN);
3770 AssertRC(rc);
3771 }
3772
3773 ataR3LockEnter(pDevIns, pCtl);
3774 break;
3775 }
3776 case 3: /* 11 - Load media */
3777 /** @todo rc = pDevR3->pDrvMount->pfnLoadMedia(pDevR3->pDrvMount) */
3778 break;
3779 }
3780 if (RT_SUCCESS(rc))
3781 atapiR3CmdOK(pCtl, s);
3782 else
3783 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
3784 break;
3785 }
3786 case SCSI_MECHANISM_STATUS:
3787 {
3788 cbMax = scsiBE2H_U16(pbPacket + 8);
3789 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true);
3790 break;
3791 }
3792 case SCSI_READ_TOC_PMA_ATIP:
3793 {
3794 uint8_t format;
3795
3796 if (s->cNotifiedMediaChange > 0)
3797 {
3798 s->cNotifiedMediaChange-- ;
3799 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3800 break;
3801 }
3802 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3803 {
3804 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3805 break;
3806 }
3807 cbMax = scsiBE2H_U16(pbPacket + 7);
3808 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
3809 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
3810 * the other field is clear... */
3811 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
3812 switch (format)
3813 {
3814 case 0:
3815 ataR3StartTransfer(pDevIns, pCtl, s, cbMax, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true);
3816 break;
3817 case 1:
3818 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 12), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true);
3819 break;
3820 case 2:
3821 ataR3StartTransfer(pDevIns, pCtl, s, cbMax, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true);
3822 break;
3823 default:
3824 error_cmd:
3825 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3826 break;
3827 }
3828 break;
3829 }
3830 case SCSI_READ_CAPACITY:
3831 if (s->cNotifiedMediaChange > 0)
3832 {
3833 s->cNotifiedMediaChange-- ;
3834 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3835 break;
3836 }
3837 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3838 {
3839 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3840 break;
3841 }
3842 ataR3StartTransfer(pDevIns, pCtl, s, 8, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_CAPACITY, true);
3843 break;
3844 case SCSI_READ_DISC_INFORMATION:
3845 if (s->cNotifiedMediaChange > 0)
3846 {
3847 s->cNotifiedMediaChange-- ;
3848 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3849 break;
3850 }
3851 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3852 {
3853 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3854 break;
3855 }
3856 cbMax = scsiBE2H_U16(pbPacket + 7);
3857 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 34), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_DISC_INFORMATION, true);
3858 break;
3859 case SCSI_READ_TRACK_INFORMATION:
3860 if (s->cNotifiedMediaChange > 0)
3861 {
3862 s->cNotifiedMediaChange-- ;
3863 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3864 break;
3865 }
3866 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3867 {
3868 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3869 break;
3870 }
3871 cbMax = scsiBE2H_U16(pbPacket + 7);
3872 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 36), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION, true);
3873 break;
3874 case SCSI_GET_CONFIGURATION:
3875 /* No media change stuff here, it can confuse Linux guests. */
3876 cbMax = scsiBE2H_U16(pbPacket + 7);
3877 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 80), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_CONFIGURATION, true);
3878 break;
3879 case SCSI_INQUIRY:
3880 cbMax = scsiBE2H_U16(pbPacket + 3);
3881 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 36), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_INQUIRY, true);
3882 break;
3883 case SCSI_READ_DVD_STRUCTURE:
3884 {
3885 cbMax = scsiBE2H_U16(pbPacket + 8);
3886 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 4), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_DVD_STRUCTURE, true);
3887 break;
3888 }
3889 default:
3890 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
3891 break;
3892 }
3893}
3894
3895
3896/*
3897 * Parse ATAPI commands, passing them directly to the CD/DVD drive.
3898 */
3899static void atapiR3ParseCmdPassthrough(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3900{
3901 const uint8_t *pbPacket = &s->abATAPICmd[0];
3902
3903 /* Some cases we have to handle here. */
3904 if ( pbPacket[0] == SCSI_GET_EVENT_STATUS_NOTIFICATION
3905 && ASMAtomicReadU32(&s->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
3906 {
3907 uint32_t cbTransfer = scsiBE2H_U16(pbPacket + 7);
3908 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbTransfer, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
3909 }
3910 else if ( pbPacket[0] == SCSI_REQUEST_SENSE
3911 && (s->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
3912 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(pbPacket[4], 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
3913 else
3914 {
3915 size_t cbBuf = 0;
3916 size_t cbATAPISector = 0;
3917 size_t cbTransfer = 0;
3918 PDMMEDIATXDIR uTxDir = PDMMEDIATXDIR_NONE;
3919 uint8_t u8ScsiSts = SCSI_STATUS_OK;
3920
3921 if (pbPacket[0] == SCSI_FORMAT_UNIT || pbPacket[0] == SCSI_GET_PERFORMANCE)
3922 cbBuf = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */
3923
3924 bool fPassthrough = ATAPIPassthroughParseCdb(pbPacket, sizeof(s->abATAPICmd), cbBuf, pDevR3->pTrackList,
3925 &s->abATAPISense[0], sizeof(s->abATAPISense), &uTxDir, &cbTransfer,
3926 &cbATAPISector, &u8ScsiSts);
3927 if (fPassthrough)
3928 {
3929 s->cbATAPISector = (uint32_t)cbATAPISector;
3930 Assert(s->cbATAPISector == (uint32_t)cbATAPISector);
3931 Assert(cbTransfer == (uint32_t)cbTransfer);
3932
3933 /*
3934 * Send a command to the drive, passing data in/out as required.
3935 * Commands which exceed the I/O buffer size are split below
3936 * or aborted if splitting is not implemented.
3937 */
3938 Log2(("ATAPI PT: max size %d\n", cbTransfer));
3939 if (cbTransfer == 0)
3940 uTxDir = PDMMEDIATXDIR_NONE;
3941 ataR3StartTransfer(pDevIns, pCtl, s, (uint32_t)cbTransfer, uTxDir, ATAFN_BT_ATAPI_PASSTHROUGH_CMD, ATAFN_SS_ATAPI_PASSTHROUGH, true);
3942 }
3943 else if (u8ScsiSts == SCSI_STATUS_CHECK_CONDITION)
3944 {
3945 /* Sense data is already set, end the request and notify the guest. */
3946 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, s->abATAPISense[2] & 0x0f, SCSISenseText(s->abATAPISense[2] & 0x0f),
3947 s->abATAPISense[12], s->abATAPISense[13], SCSISenseExtText(s->abATAPISense[12], s->abATAPISense[13])));
3948 s->uATARegError = s->abATAPISense[2] << 4;
3949 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_ERR);
3950 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
3951 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
3952 s->cbTotalTransfer = 0;
3953 s->cbElementaryTransfer = 0;
3954 s->cbAtapiPassthroughTransfer = 0;
3955 s->iIOBufferCur = 0;
3956 s->iIOBufferEnd = 0;
3957 s->uTxDir = PDMMEDIATXDIR_NONE;
3958 s->iBeginTransfer = ATAFN_BT_NULL;
3959 s->iSourceSink = ATAFN_SS_NULL;
3960 }
3961 else if (u8ScsiSts == SCSI_STATUS_OK)
3962 atapiR3CmdOK(pCtl, s);
3963 }
3964}
3965
3966
3967static void atapiR3ParseCmd(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3968{
3969 const uint8_t *pbPacket;
3970
3971 pbPacket = s->abATAPICmd;
3972# ifdef DEBUG
3973 Log(("%s: LUN#%d DMA=%d CMD=%#04x \"%s\"\n", __FUNCTION__, s->iLUN, s->fDMA, pbPacket[0], SCSICmdText(pbPacket[0])));
3974# else /* !DEBUG */
3975 Log(("%s: LUN#%d DMA=%d CMD=%#04x\n", __FUNCTION__, s->iLUN, s->fDMA, pbPacket[0]));
3976# endif /* !DEBUG */
3977 Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, s->uATARegLCyl | (s->uATARegHCyl << 8), ATAPI_PACKET_SIZE, pbPacket));
3978
3979 if (s->fATAPIPassthrough)
3980 atapiR3ParseCmdPassthrough(pDevIns, pCtl, s, pDevR3);
3981 else
3982 atapiR3ParseCmdVirtualATAPI(pDevIns, pCtl, s, pDevR3);
3983}
3984
3985
3986/**
3987 * Sink/Source: PACKET
3988 */
3989static bool ataR3PacketSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3990{
3991 s->fDMA = !!(s->uATARegFeature & 1);
3992 memcpy(s->abATAPICmd, s->abIOBuffer, ATAPI_PACKET_SIZE);
3993 s->uTxDir = PDMMEDIATXDIR_NONE;
3994 s->cbTotalTransfer = 0;
3995 s->cbElementaryTransfer = 0;
3996 s->cbAtapiPassthroughTransfer = 0;
3997 atapiR3ParseCmd(pDevIns, pCtl, s, pDevR3);
3998 return false;
3999}
4000
4001
4002/**
4003 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium removed" event
4004 * from now on, regardless if there was a medium inserted or not.
4005 */
4006static void ataR3MediumRemoved(PATADEVSTATE s)
4007{
4008 ASMAtomicWriteU32(&s->MediaEventStatus, ATA_EVENT_STATUS_MEDIA_REMOVED);
4009}
4010
4011
4012/**
4013 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium inserted". If
4014 * there was already a medium inserted, don't forget to send the "medium
4015 * removed" event first.
4016 */
4017static void ataR3MediumInserted(PATADEVSTATE s)
4018{
4019 uint32_t OldStatus, NewStatus;
4020 do
4021 {
4022 OldStatus = ASMAtomicReadU32(&s->MediaEventStatus);
4023 switch (OldStatus)
4024 {
4025 case ATA_EVENT_STATUS_MEDIA_CHANGED:
4026 case ATA_EVENT_STATUS_MEDIA_REMOVED:
4027 /* no change, we will send "medium removed" + "medium inserted" */
4028 NewStatus = ATA_EVENT_STATUS_MEDIA_CHANGED;
4029 break;
4030 default:
4031 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW;
4032 break;
4033 }
4034 } while (!ASMAtomicCmpXchgU32(&s->MediaEventStatus, NewStatus, OldStatus));
4035}
4036
4037
4038/**
4039 * @interface_method_impl{PDMIMOUNTNOTIFY,pfnMountNotify}
4040 */
4041static DECLCALLBACK(void) ataR3MountNotify(PPDMIMOUNTNOTIFY pInterface)
4042{
4043 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IMountNotify);
4044 PATASTATE pThis = PDMDEVINS_2_DATA(pIfR3->pDevIns, PATASTATE);
4045 PATADEVSTATE pIf = &RT_SAFE_SUBSCRIPT(RT_SAFE_SUBSCRIPT(pThis->aCts, pIfR3->iCtl).aIfs, pIfR3->iDev);
4046 Log(("%s: changing LUN#%d\n", __FUNCTION__, pIfR3->iLUN));
4047
4048 /* Ignore the call if we're called while being attached. */
4049 if (!pIfR3->pDrvMedia)
4050 return;
4051
4052 uint32_t cRegions = pIfR3->pDrvMedia->pfnGetRegionCount(pIfR3->pDrvMedia);
4053 for (uint32_t i = 0; i < cRegions; i++)
4054 {
4055 uint64_t cBlocks = 0;
4056 int rc = pIfR3->pDrvMedia->pfnQueryRegionProperties(pIfR3->pDrvMedia, i, NULL, &cBlocks,
4057 NULL, NULL);
4058 AssertRC(rc);
4059 pIf->cTotalSectors += cBlocks;
4060 }
4061
4062 LogRel(("PIIX3 ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors));
4063
4064 /* Report media changed in TEST UNIT and other (probably incorrect) places. */
4065 if (pIf->cNotifiedMediaChange < 2)
4066 pIf->cNotifiedMediaChange = 1;
4067 ataR3MediumInserted(pIf);
4068 ataR3MediumTypeSet(pIf, ATA_MEDIA_TYPE_UNKNOWN);
4069}
4070
4071/**
4072 * @interface_method_impl{PDMIMOUNTNOTIFY,pfnUnmountNotify}
4073 */
4074static DECLCALLBACK(void) ataR3UnmountNotify(PPDMIMOUNTNOTIFY pInterface)
4075{
4076 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IMountNotify);
4077 PATASTATE pThis = PDMDEVINS_2_DATA(pIfR3->pDevIns, PATASTATE);
4078 PATADEVSTATE pIf = &RT_SAFE_SUBSCRIPT(RT_SAFE_SUBSCRIPT(pThis->aCts, pIfR3->iCtl).aIfs, pIfR3->iDev);
4079 Log(("%s:\n", __FUNCTION__));
4080 pIf->cTotalSectors = 0;
4081
4082 /*
4083 * Whatever I do, XP will not use the GET MEDIA STATUS nor the EVENT stuff.
4084 * However, it will respond to TEST UNIT with a 0x6 0x28 (media changed) sense code.
4085 * So, we'll give it 4 TEST UNIT command to catch up, two which the media is not
4086 * present and 2 in which it is changed.
4087 */
4088 pIf->cNotifiedMediaChange = 1;
4089 ataR3MediumRemoved(pIf);
4090 ataR3MediumTypeSet(pIf, ATA_MEDIA_NO_DISC);
4091}
4092
4093/**
4094 * Begin Transfer: PACKET
4095 */
4096static void ataR3PacketBT(PATACONTROLLER pCtl, PATADEVSTATE s)
4097{
4098 s->cbElementaryTransfer = s->cbTotalTransfer;
4099 s->cbAtapiPassthroughTransfer = s->cbTotalTransfer;
4100 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_CD;
4101 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
4102 ataSetStatusValue(pCtl, s, ATA_STAT_READY);
4103}
4104
4105
4106static void ataR3ResetDevice(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
4107{
4108 LogFlowFunc(("\n"));
4109 s->cMultSectors = ATA_MAX_MULT_SECTORS;
4110 s->cNotifiedMediaChange = 0;
4111 ASMAtomicWriteU32(&s->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED);
4112 ASMAtomicWriteU32(&s->MediaTrackType, ATA_MEDIA_TYPE_UNKNOWN);
4113 ataUnsetIRQ(pDevIns, pCtl, s);
4114
4115 s->uATARegSelect = 0x20;
4116 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_SEEK);
4117 ataR3SetSignature(s);
4118 s->cbTotalTransfer = 0;
4119 s->cbElementaryTransfer = 0;
4120 s->cbAtapiPassthroughTransfer = 0;
4121 s->iIOBufferPIODataStart = 0;
4122 s->iIOBufferPIODataEnd = 0;
4123 s->iBeginTransfer = ATAFN_BT_NULL;
4124 s->iSourceSink = ATAFN_SS_NULL;
4125 s->fDMA = false;
4126 s->fATAPITransfer = false;
4127 s->uATATransferMode = ATA_MODE_UDMA | 2; /* PIIX3 supports only up to UDMA2 */
4128
4129 s->XCHSGeometry = s->PCHSGeometry; /* Restore default CHS translation. */
4130
4131 s->uATARegFeature = 0;
4132}
4133
4134
4135static void ataR3DeviceDiag(PATACONTROLLER pCtl, PATADEVSTATE s)
4136{
4137 ataR3SetSignature(s);
4138 if (s->fATAPI)
4139 ataSetStatusValue(pCtl, s, 0); /* NOTE: READY is _not_ set */
4140 else
4141 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_SEEK);
4142 s->uATARegError = 0x01;
4143}
4144
4145
4146/**
4147 * Sink/Source: EXECUTE DEVICE DIAGNOTIC
4148 */
4149static bool ataR3ExecuteDeviceDiagnosticSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4150{
4151 RT_NOREF(pDevIns, s, pDevR3);
4152
4153 /* EXECUTE DEVICE DIAGNOSTIC is a very special command which always
4154 * gets executed, regardless of which device is selected. As a side
4155 * effect, it always completes with device 0 selected.
4156 */
4157 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
4158 ataR3DeviceDiag(pCtl, &pCtl->aIfs[i]);
4159
4160 LogRel(("ATA: LUN#%d: EXECUTE DEVICE DIAGNOSTIC, status %02X\n", s->iLUN, s->uATARegStatus));
4161 pCtl->iSelectedIf = 0;
4162
4163 return false;
4164}
4165
4166
4167/**
4168 * Sink/Source: INITIALIZE DEVICE PARAMETERS
4169 */
4170static bool ataR3InitDevParmSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4171{
4172 RT_NOREF(pDevR3);
4173 LogFlowFunc(("\n"));
4174
4175 /* Technical Note:
4176 * On ST506 type drives with a separate controller, the INITIALIZE DRIVE PARAMETERS command was
4177 * required to inform the controller of drive geometry. The controller needed to know the
4178 * number of heads and sectors per track so that it could correctly advance to the next track
4179 * or cylinder when executing multi-sector commands. Setting a geometry that didn't match the
4180 * drive made very little sense because sectors had fixed CHS addresses. It was at best
4181 * possible to reduce the drive's capacity by limiting the number of heads and/or sectors
4182 * per track.
4183 *
4184 * IDE drives inherently have to know their true geometry, but most of them also support
4185 * programmable translation that can be set through the INITIALIZE DEVICE PARAMETERS command.
4186 * In fact most older IDE drives typically weren't operated using their default (native) geometry,
4187 * and with newer IDE drives that's not even an option.
4188 *
4189 * Up to and including ATA-5, the standard defined a CHS to LBA translation (since ATA-6, CHS
4190 * support is optional):
4191 *
4192 * LBA = (((cyl_num * heads_per_cyl) + head_num) * sectors_per_track) + sector_num - 1
4193 *
4194 * The INITIALIZE DEVICE PARAMETERS command sets the heads_per_cyl and sectors_per_track
4195 * values used in the above formula.
4196 *
4197 * Drives must obviously support an INITIALIZE DRIVE PARAMETERS command matching the drive's
4198 * default CHS translation. Everything else is optional.
4199 *
4200 * We support any geometry with non-zero sectors per track because there's no reason not to;
4201 * this behavior is common in many if not most IDE drives.
4202 */
4203
4204 PDMMEDIAGEOMETRY Geom = { 0 };
4205
4206 Geom.cHeads = (s->uATARegSelect & 0x0f) + 1; /* Effective range 1-16. */
4207 Geom.cSectors = s->uATARegNSector; /* Range 0-255, zero is not valid. */
4208
4209 if (Geom.cSectors)
4210 {
4211 uint64_t cCylinders = s->cTotalSectors / (Geom.cHeads * Geom.cSectors);
4212 Geom.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
4213
4214 s->XCHSGeometry = Geom;
4215
4216 ataR3LockLeave(pDevIns, pCtl);
4217 LogRel(("ATA: LUN#%d: INITIALIZE DEVICE PARAMETERS: %u sectors per track, %u heads\n",
4218 s->iLUN, s->uATARegNSector, (s->uATARegSelect & 0x0f) + 1));
4219 RTThreadSleep(pCtl->msDelayIRQ);
4220 ataR3LockEnter(pDevIns, pCtl);
4221 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4222 }
4223 else
4224 {
4225 ataR3LockLeave(pDevIns, pCtl);
4226 LogRel(("ATA: LUN#%d: INITIALIZE DEVICE PARAMETERS error (zero sectors per track)!\n", s->iLUN));
4227 RTThreadSleep(pCtl->msDelayIRQ);
4228 ataR3LockEnter(pDevIns, pCtl);
4229 ataR3CmdError(pCtl, s, ABRT_ERR);
4230 }
4231 return false;
4232}
4233
4234
4235/**
4236 * Sink/Source: RECALIBRATE
4237 */
4238static bool ataR3RecalibrateSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4239{
4240 RT_NOREF(pDevR3);
4241 LogFlowFunc(("\n"));
4242 ataR3LockLeave(pDevIns, pCtl);
4243 RTThreadSleep(pCtl->msDelayIRQ);
4244 ataR3LockEnter(pDevIns, pCtl);
4245 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4246 return false;
4247}
4248
4249
4250static int ataR3TrimSectors(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3,
4251 uint64_t u64Sector, uint32_t cSectors, bool *pfRedo)
4252{
4253 RTRANGE TrimRange;
4254 int rc;
4255
4256 ataR3LockLeave(pDevIns, pCtl);
4257
4258 TrimRange.offStart = u64Sector * s->cbSector;
4259 TrimRange.cbRange = cSectors * s->cbSector;
4260
4261 s->Led.Asserted.s.fWriting = s->Led.Actual.s.fWriting = 1;
4262 rc = pDevR3->pDrvMedia->pfnDiscard(pDevR3->pDrvMedia, &TrimRange, 1);
4263 s->Led.Actual.s.fWriting = 0;
4264
4265 if (RT_SUCCESS(rc))
4266 *pfRedo = false;
4267 else
4268 *pfRedo = ataR3IsRedoSetWarning(pDevIns, pCtl, rc);
4269
4270 ataR3LockEnter(pDevIns, pCtl);
4271 return rc;
4272}
4273
4274
4275/**
4276 * Sink/Source: TRIM
4277 */
4278static bool ataR3TrimSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4279{
4280 int rc = VERR_GENERAL_FAILURE;
4281 uint32_t cRangesMax;
4282 uint64_t *pu64Range = (uint64_t *)&s->abIOBuffer[0];
4283 bool fRedo = false;
4284
4285 cRangesMax = RT_MIN(s->cbElementaryTransfer, sizeof(s->abIOBuffer)) / sizeof(uint64_t);
4286 Assert(cRangesMax);
4287
4288 while (cRangesMax-- > 0)
4289 {
4290 if (ATA_RANGE_LENGTH_GET(*pu64Range) == 0)
4291 break;
4292
4293 rc = ataR3TrimSectors(pDevIns, pCtl, s, pDevR3, *pu64Range & ATA_RANGE_LBA_MASK,
4294 ATA_RANGE_LENGTH_GET(*pu64Range), &fRedo);
4295 if (RT_FAILURE(rc))
4296 break;
4297
4298 pu64Range++;
4299 }
4300
4301 if (RT_SUCCESS(rc))
4302 {
4303 s->iSourceSink = ATAFN_SS_NULL;
4304 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4305 }
4306 else
4307 {
4308 if (fRedo)
4309 return fRedo;
4310 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
4311 LogRel(("PIIX3 ATA: LUN#%d: disk trim error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
4312 s->iLUN, rc, *pu64Range & ATA_RANGE_LBA_MASK, ATA_RANGE_LENGTH_GET(*pu64Range)));
4313
4314 /*
4315 * Check if we got interrupted. We don't need to set status variables
4316 * because the request was aborted.
4317 */
4318 if (rc != VERR_INTERRUPTED)
4319 ataR3CmdError(pCtl, s, ID_ERR);
4320 }
4321
4322 return false;
4323}
4324
4325
4326static void ataR3ParseCmd(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3, uint8_t cmd)
4327{
4328# ifdef DEBUG
4329 Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, s->iLUN, cmd, ATACmdText(cmd)));
4330# else /* !DEBUG */
4331 Log(("%s: LUN#%d CMD=%#04x\n", __FUNCTION__, s->iLUN, cmd));
4332# endif /* !DEBUG */
4333 s->fLBA48 = false;
4334 s->fDMA = false;
4335 if (cmd == ATA_IDLE_IMMEDIATE)
4336 {
4337 /* Detect Linux timeout recovery, first tries IDLE IMMEDIATE (which
4338 * would overwrite the failing command unfortunately), then RESET. */
4339 int32_t uCmdWait = -1;
4340 uint64_t uNow = RTTimeNanoTS();
4341 if (s->u64CmdTS)
4342 uCmdWait = (uNow - s->u64CmdTS) / 1000;
4343 LogRel(("PIIX3 ATA: LUN#%d: IDLE IMMEDIATE, CmdIf=%#04x (%d usec ago)\n",
4344 s->iLUN, s->uATARegCommand, uCmdWait));
4345 }
4346 s->uATARegCommand = cmd;
4347 switch (cmd)
4348 {
4349 case ATA_IDENTIFY_DEVICE:
4350 if (pDevR3->pDrvMedia && !s->fATAPI)
4351 ataR3StartTransfer(pDevIns, pCtl, s, 512, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_NULL, ATAFN_SS_IDENTIFY, false);
4352 else
4353 {
4354 if (s->fATAPI)
4355 ataR3SetSignature(s);
4356 ataR3CmdError(pCtl, s, ABRT_ERR);
4357 ataUnsetStatus(pCtl, s, ATA_STAT_READY);
4358 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4359 }
4360 break;
4361 case ATA_RECALIBRATE:
4362 if (s->fATAPI)
4363 goto abort_cmd;
4364 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_RECALIBRATE, false);
4365 break;
4366 case ATA_INITIALIZE_DEVICE_PARAMETERS:
4367 if (s->fATAPI)
4368 goto abort_cmd;
4369 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_INITIALIZE_DEVICE_PARAMETERS, false);
4370 break;
4371 case ATA_SET_MULTIPLE_MODE:
4372 if ( s->uATARegNSector != 0
4373 && ( s->uATARegNSector > ATA_MAX_MULT_SECTORS
4374 || (s->uATARegNSector & (s->uATARegNSector - 1)) != 0))
4375 {
4376 ataR3CmdError(pCtl, s, ABRT_ERR);
4377 }
4378 else
4379 {
4380 Log2(("%s: set multi sector count to %d\n", __FUNCTION__, s->uATARegNSector));
4381 s->cMultSectors = s->uATARegNSector;
4382 ataR3CmdOK(pCtl, s, 0);
4383 }
4384 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4385 break;
4386 case ATA_READ_VERIFY_SECTORS_EXT:
4387 s->fLBA48 = true;
4388 RT_FALL_THRU();
4389 case ATA_READ_VERIFY_SECTORS:
4390 case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES:
4391 /* do sector number check ? */
4392 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4393 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4394 break;
4395 case ATA_READ_SECTORS_EXT:
4396 s->fLBA48 = true;
4397 RT_FALL_THRU();
4398 case ATA_READ_SECTORS:
4399 case ATA_READ_SECTORS_WITHOUT_RETRIES:
4400 if (!pDevR3->pDrvMedia || s->fATAPI)
4401 goto abort_cmd;
4402 s->cSectorsPerIRQ = 1;
4403 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
4404 break;
4405 case ATA_WRITE_SECTORS_EXT:
4406 s->fLBA48 = true;
4407 RT_FALL_THRU();
4408 case ATA_WRITE_SECTORS:
4409 case ATA_WRITE_SECTORS_WITHOUT_RETRIES:
4410 if (!pDevR3->pDrvMedia || s->fATAPI)
4411 goto abort_cmd;
4412 s->cSectorsPerIRQ = 1;
4413 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
4414 break;
4415 case ATA_READ_MULTIPLE_EXT:
4416 s->fLBA48 = true;
4417 RT_FALL_THRU();
4418 case ATA_READ_MULTIPLE:
4419 if (!pDevR3->pDrvMedia || !s->cMultSectors || s->fATAPI)
4420 goto abort_cmd;
4421 s->cSectorsPerIRQ = s->cMultSectors;
4422 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
4423 break;
4424 case ATA_WRITE_MULTIPLE_EXT:
4425 s->fLBA48 = true;
4426 RT_FALL_THRU();
4427 case ATA_WRITE_MULTIPLE:
4428 if (!pDevR3->pDrvMedia || !s->cMultSectors || s->fATAPI)
4429 goto abort_cmd;
4430 s->cSectorsPerIRQ = s->cMultSectors;
4431 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
4432 break;
4433 case ATA_READ_DMA_EXT:
4434 s->fLBA48 = true;
4435 RT_FALL_THRU();
4436 case ATA_READ_DMA:
4437 case ATA_READ_DMA_WITHOUT_RETRIES:
4438 if (!pDevR3->pDrvMedia || s->fATAPI)
4439 goto abort_cmd;
4440 s->cSectorsPerIRQ = ATA_MAX_MULT_SECTORS;
4441 s->fDMA = true;
4442 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
4443 break;
4444 case ATA_WRITE_DMA_EXT:
4445 s->fLBA48 = true;
4446 RT_FALL_THRU();
4447 case ATA_WRITE_DMA:
4448 case ATA_WRITE_DMA_WITHOUT_RETRIES:
4449 if (!pDevR3->pDrvMedia || s->fATAPI)
4450 goto abort_cmd;
4451 s->cSectorsPerIRQ = ATA_MAX_MULT_SECTORS;
4452 s->fDMA = true;
4453 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
4454 break;
4455 case ATA_READ_NATIVE_MAX_ADDRESS_EXT:
4456 if (!pDevR3->pDrvMedia || s->fATAPI)
4457 goto abort_cmd;
4458 s->fLBA48 = true;
4459 ataR3SetSector(s, s->cTotalSectors - 1);
4460 ataR3CmdOK(pCtl, s, 0);
4461 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4462 break;
4463 case ATA_SEEK: /* Used by the SCO OpenServer. Command is marked as obsolete */
4464 ataR3CmdOK(pCtl, s, 0);
4465 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4466 break;
4467 case ATA_READ_NATIVE_MAX_ADDRESS:
4468 if (!pDevR3->pDrvMedia || s->fATAPI)
4469 goto abort_cmd;
4470 ataR3SetSector(s, RT_MIN(s->cTotalSectors, 1 << 28) - 1);
4471 ataR3CmdOK(pCtl, s, 0);
4472 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4473 break;
4474 case ATA_CHECK_POWER_MODE:
4475 s->uATARegNSector = 0xff; /* drive active or idle */
4476 ataR3CmdOK(pCtl, s, 0);
4477 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4478 break;
4479 case ATA_SET_FEATURES:
4480 Log2(("%s: feature=%#x\n", __FUNCTION__, s->uATARegFeature));
4481 if (!pDevR3->pDrvMedia)
4482 goto abort_cmd;
4483 switch (s->uATARegFeature)
4484 {
4485 case 0x02: /* write cache enable */
4486 Log2(("%s: write cache enable\n", __FUNCTION__));
4487 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4488 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4489 break;
4490 case 0xaa: /* read look-ahead enable */
4491 Log2(("%s: read look-ahead enable\n", __FUNCTION__));
4492 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4493 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4494 break;
4495 case 0x55: /* read look-ahead disable */
4496 Log2(("%s: read look-ahead disable\n", __FUNCTION__));
4497 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4498 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4499 break;
4500 case 0xcc: /* reverting to power-on defaults enable */
4501 Log2(("%s: revert to power-on defaults enable\n", __FUNCTION__));
4502 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4503 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4504 break;
4505 case 0x66: /* reverting to power-on defaults disable */
4506 Log2(("%s: revert to power-on defaults disable\n", __FUNCTION__));
4507 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4508 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4509 break;
4510 case 0x82: /* write cache disable */
4511 Log2(("%s: write cache disable\n", __FUNCTION__));
4512 /* As per the ATA/ATAPI-6 specs, a write cache disable
4513 * command MUST flush the write buffers to disc. */
4514 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_FLUSH, false);
4515 break;
4516 case 0x03: { /* set transfer mode */
4517 Log2(("%s: transfer mode %#04x\n", __FUNCTION__, s->uATARegNSector));
4518 switch (s->uATARegNSector & 0xf8)
4519 {
4520 case 0x00: /* PIO default */
4521 case 0x08: /* PIO mode */
4522 break;
4523 case ATA_MODE_MDMA: /* MDMA mode */
4524 s->uATATransferMode = (s->uATARegNSector & 0xf8) | RT_MIN(s->uATARegNSector & 0x07, ATA_MDMA_MODE_MAX);
4525 break;
4526 case ATA_MODE_UDMA: /* UDMA mode */
4527 s->uATATransferMode = (s->uATARegNSector & 0xf8) | RT_MIN(s->uATARegNSector & 0x07, ATA_UDMA_MODE_MAX);
4528 break;
4529 default:
4530 goto abort_cmd;
4531 }
4532 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4533 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4534 break;
4535 }
4536 default:
4537 goto abort_cmd;
4538 }
4539 /*
4540 * OS/2 workarond:
4541 * The OS/2 IDE driver from MCP2 appears to rely on the feature register being
4542 * reset here. According to the specification, this is a driver bug as the register
4543 * contents are undefined after the call. This means we can just as well reset it.
4544 */
4545 s->uATARegFeature = 0;
4546 break;
4547 case ATA_FLUSH_CACHE_EXT:
4548 case ATA_FLUSH_CACHE:
4549 if (!pDevR3->pDrvMedia || s->fATAPI)
4550 goto abort_cmd;
4551 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_FLUSH, false);
4552 break;
4553 case ATA_STANDBY_IMMEDIATE:
4554 ataR3CmdOK(pCtl, s, 0);
4555 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4556 break;
4557 case ATA_IDLE_IMMEDIATE:
4558 LogRel(("PIIX3 ATA: LUN#%d: aborting current command\n", s->iLUN));
4559 ataR3AbortCurrentCommand(pDevIns, pCtl, s, false);
4560 break;
4561 case ATA_SLEEP:
4562 ataR3CmdOK(pCtl, s, 0);
4563 ataHCSetIRQ(pDevIns, pCtl, s);
4564 break;
4565 /* ATAPI commands */
4566 case ATA_IDENTIFY_PACKET_DEVICE:
4567 if (s->fATAPI)
4568 ataR3StartTransfer(pDevIns, pCtl, s, 512, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_NULL, ATAFN_SS_ATAPI_IDENTIFY, false);
4569 else
4570 {
4571 ataR3CmdError(pCtl, s, ABRT_ERR);
4572 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4573 }
4574 break;
4575 case ATA_EXECUTE_DEVICE_DIAGNOSTIC:
4576 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC, false);
4577 break;
4578 case ATA_DEVICE_RESET:
4579 if (!s->fATAPI)
4580 goto abort_cmd;
4581 LogRel(("PIIX3 ATA: LUN#%d: performing device RESET\n", s->iLUN));
4582 ataR3AbortCurrentCommand(pDevIns, pCtl, s, true);
4583 break;
4584 case ATA_PACKET:
4585 if (!s->fATAPI)
4586 goto abort_cmd;
4587 /* overlapping commands not supported */
4588 if (s->uATARegFeature & 0x02)
4589 goto abort_cmd;
4590 ataR3StartTransfer(pDevIns, pCtl, s, ATAPI_PACKET_SIZE, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_PACKET, ATAFN_SS_PACKET, false);
4591 break;
4592 case ATA_DATA_SET_MANAGEMENT:
4593 if (!pDevR3->pDrvMedia || !pDevR3->pDrvMedia->pfnDiscard)
4594 goto abort_cmd;
4595 if ( !(s->uATARegFeature & UINT8_C(0x01))
4596 || (s->uATARegFeature & ~UINT8_C(0x01)))
4597 goto abort_cmd;
4598 s->fDMA = true;
4599 ataR3StartTransfer(pDevIns, pCtl, s, (s->uATARegNSectorHOB << 8 | s->uATARegNSector) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_NULL, ATAFN_SS_TRIM, false);
4600 break;
4601 default:
4602 abort_cmd:
4603 ataR3CmdError(pCtl, s, ABRT_ERR);
4604 if (s->fATAPI)
4605 ataUnsetStatus(pCtl, s, ATA_STAT_READY);
4606 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4607 break;
4608 }
4609}
4610
4611# endif /* IN_RING3 */
4612#endif /* IN_RING0 || IN_RING3 */
4613
4614/*
4615 * Note: There are four distinct cases of port I/O handling depending on
4616 * which devices (if any) are attached to an IDE channel:
4617 *
4618 * 1) No device attached. No response to writes or reads (i.e. reads return
4619 * all bits set).
4620 *
4621 * 2) Both devices attached. Reads and writes are processed normally.
4622 *
4623 * 3) Device 0 only. If device 0 is selected, normal behavior applies. But
4624 * if Device 1 is selected, writes are still directed to Device 0 (except
4625 * commands are not executed), reads from control/command registers are
4626 * directed to Device 0, but status/alt status reads return 0. If Device 1
4627 * is a PACKET device, all reads return 0. See ATAPI-6 clause 9.16.1 and
4628 * Table 18 in clause 7.1.
4629 *
4630 * 4) Device 1 only - non-standard(!). Device 1 can't tell if Device 0 is
4631 * present or not and behaves the same. That means if Device 0 is selected,
4632 * Device 1 responds to writes (except commands are not executed) but does
4633 * not respond to reads. If Device 1 selected, normal behavior applies.
4634 * See ATAPI-6 clause 9.16.2 and Table 15 in clause 7.1.
4635 */
4636
4637static VBOXSTRICTRC ataIOPortWriteU8(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t addr, uint32_t val, uintptr_t iCtl)
4638{
4639 RT_NOREF(iCtl);
4640 Log2(("%s: LUN#%d write addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN, addr, val));
4641 addr &= 7;
4642 switch (addr)
4643 {
4644 case 0:
4645 break;
4646 case 1: /* feature register */
4647 /* NOTE: data is written to the two drives */
4648 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4649 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4650 pCtl->aIfs[0].uATARegFeatureHOB = pCtl->aIfs[0].uATARegFeature;
4651 pCtl->aIfs[1].uATARegFeatureHOB = pCtl->aIfs[1].uATARegFeature;
4652 pCtl->aIfs[0].uATARegFeature = val;
4653 pCtl->aIfs[1].uATARegFeature = val;
4654 break;
4655 case 2: /* sector count */
4656 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4657 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4658 pCtl->aIfs[0].uATARegNSectorHOB = pCtl->aIfs[0].uATARegNSector;
4659 pCtl->aIfs[1].uATARegNSectorHOB = pCtl->aIfs[1].uATARegNSector;
4660 pCtl->aIfs[0].uATARegNSector = val;
4661 pCtl->aIfs[1].uATARegNSector = val;
4662 break;
4663 case 3: /* sector number */
4664 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4665 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4666 pCtl->aIfs[0].uATARegSectorHOB = pCtl->aIfs[0].uATARegSector;
4667 pCtl->aIfs[1].uATARegSectorHOB = pCtl->aIfs[1].uATARegSector;
4668 pCtl->aIfs[0].uATARegSector = val;
4669 pCtl->aIfs[1].uATARegSector = val;
4670 break;
4671 case 4: /* cylinder low */
4672 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4673 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4674 pCtl->aIfs[0].uATARegLCylHOB = pCtl->aIfs[0].uATARegLCyl;
4675 pCtl->aIfs[1].uATARegLCylHOB = pCtl->aIfs[1].uATARegLCyl;
4676 pCtl->aIfs[0].uATARegLCyl = val;
4677 pCtl->aIfs[1].uATARegLCyl = val;
4678 break;
4679 case 5: /* cylinder high */
4680 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4681 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4682 pCtl->aIfs[0].uATARegHCylHOB = pCtl->aIfs[0].uATARegHCyl;
4683 pCtl->aIfs[1].uATARegHCylHOB = pCtl->aIfs[1].uATARegHCyl;
4684 pCtl->aIfs[0].uATARegHCyl = val;
4685 pCtl->aIfs[1].uATARegHCyl = val;
4686 break;
4687 case 6: /* drive/head */
4688 pCtl->aIfs[0].uATARegSelect = (val & ~0x10) | 0xa0;
4689 pCtl->aIfs[1].uATARegSelect = (val | 0x10) | 0xa0;
4690 if (((val >> 4) & ATA_SELECTED_IF_MASK) != pCtl->iSelectedIf)
4691 {
4692 /* select another drive */
4693 uintptr_t const iSelectedIf = (val >> 4) & ATA_SELECTED_IF_MASK;
4694 pCtl->iSelectedIf = (uint8_t)iSelectedIf;
4695 /* The IRQ line is multiplexed between the two drives, so
4696 * update the state when switching to another drive. Only need
4697 * to update interrupt line if it is enabled and there is a
4698 * state change. */
4699 if ( !(pCtl->aIfs[iSelectedIf].uATARegDevCtl & ATA_DEVCTL_DISABLE_IRQ)
4700 && pCtl->aIfs[iSelectedIf].fIrqPending != pCtl->aIfs[iSelectedIf ^ 1].fIrqPending)
4701 {
4702 if (pCtl->aIfs[iSelectedIf].fIrqPending)
4703 {
4704 Log2(("%s: LUN#%d asserting IRQ (drive select change)\n", __FUNCTION__, pCtl->aIfs[iSelectedIf].iLUN));
4705 /* The BMDMA unit unconditionally sets BM_STATUS_INT if
4706 * the interrupt line is asserted. It monitors the line
4707 * for a rising edge. */
4708 pCtl->BmDma.u8Status |= BM_STATUS_INT;
4709 if (pCtl->irq == 16)
4710 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
4711 else
4712 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 1);
4713 }
4714 else
4715 {
4716 Log2(("%s: LUN#%d deasserting IRQ (drive select change)\n", __FUNCTION__, pCtl->aIfs[iSelectedIf].iLUN));
4717 if (pCtl->irq == 16)
4718 PDMDevHlpPCISetIrq(pDevIns, 0, 0);
4719 else
4720 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 0);
4721 }
4722 }
4723 }
4724 break;
4725 default:
4726 case 7: /* command */
4727 {
4728 /* ignore commands to non-existent device */
4729 uintptr_t iSelectedIf = pCtl->iSelectedIf & ATA_SELECTED_IF_MASK;
4730 PATADEVSTATE pDev = &pCtl->aIfs[iSelectedIf];
4731 if (iSelectedIf && !pDev->fPresent) /** @todo r=bird the iSelectedIf test here looks bogus... explain. */
4732 break;
4733#ifndef IN_RING3
4734 /* Don't do anything complicated in GC */
4735 return VINF_IOM_R3_IOPORT_WRITE;
4736#else /* IN_RING3 */
4737 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
4738 ataUnsetIRQ(pDevIns, pCtl, &pCtl->aIfs[iSelectedIf]);
4739 ataR3ParseCmd(pDevIns, pCtl, &pCtl->aIfs[iSelectedIf], &pThisCC->aCts[iCtl].aIfs[iSelectedIf], val);
4740 break;
4741#endif /* !IN_RING3 */
4742 }
4743 }
4744 return VINF_SUCCESS;
4745}
4746
4747
4748static VBOXSTRICTRC ataIOPortReadU8(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t addr, uint32_t *pu32)
4749{
4750 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
4751 uint32_t val;
4752 bool fHOB;
4753
4754 /* Check if the guest is reading from a non-existent device. */
4755 if (RT_LIKELY(s->fPresent))
4756 { /* likely */ }
4757 else
4758 {
4759 if (pCtl->iSelectedIf) /* Device 1 selected, Device 0 responding for it. */
4760 {
4761 Assert(pCtl->aIfs[0].fPresent);
4762
4763 /* When an ATAPI device 0 responds for non-present device 1, it generally
4764 * returns zeros on reads. The Error register is an exception. See clause 7.1,
4765 * table 16 in ATA-6 specification.
4766 */
4767 if (((addr & 7) != 1) && pCtl->aIfs[0].fATAPI)
4768 {
4769 Log2(("%s: addr=%#x, val=0: LUN#%d not attached/LUN#%d ATAPI\n", __FUNCTION__, addr, s->iLUN, pCtl->aIfs[0].iLUN));
4770 *pu32 = 0;
4771 return VINF_SUCCESS;
4772 }
4773 /* Else handle normally. */
4774 }
4775 else /* Device 0 selected (but not present). */
4776 {
4777 /* Because device 1 has no way to tell if there is device 0, the behavior is the same
4778 * as for an empty bus; see comments in ataIOPortReadEmptyBus(). Note that EFI (TianoCore)
4779 * relies on this behavior when detecting devices.
4780 */
4781 *pu32 = ATA_EMPTY_BUS_DATA;
4782 Log2(("%s: addr=%#x: LUN#%d not attached, val=%#02x\n", __FUNCTION__, addr, s->iLUN, *pu32));
4783 return VINF_SUCCESS;
4784 }
4785 }
4786
4787 fHOB = !!(s->uATARegDevCtl & (1 << 7));
4788 switch (addr & 7)
4789 {
4790 case 0: /* data register */
4791 val = 0xff;
4792 break;
4793 case 1: /* error register */
4794 /* The ATA specification is very terse when it comes to specifying
4795 * the precise effects of reading back the error/feature register.
4796 * The error register (read-only) shares the register number with
4797 * the feature register (write-only), so it seems that it's not
4798 * necessary to support the usual HOB readback here. */
4799 if (!s->fPresent)
4800 val = 0;
4801 else
4802 val = s->uATARegError;
4803 break;
4804 case 2: /* sector count */
4805 if (fHOB)
4806 val = s->uATARegNSectorHOB;
4807 else
4808 val = s->uATARegNSector;
4809 break;
4810 case 3: /* sector number */
4811 if (fHOB)
4812 val = s->uATARegSectorHOB;
4813 else
4814 val = s->uATARegSector;
4815 break;
4816 case 4: /* cylinder low */
4817 if (fHOB)
4818 val = s->uATARegLCylHOB;
4819 else
4820 val = s->uATARegLCyl;
4821 break;
4822 case 5: /* cylinder high */
4823 if (fHOB)
4824 val = s->uATARegHCylHOB;
4825 else
4826 val = s->uATARegHCyl;
4827 break;
4828 case 6: /* drive/head */
4829 /* This register must always work as long as there is at least
4830 * one drive attached to the controller. It is common between
4831 * both drives anyway (completely identical content). */
4832 if (!pCtl->aIfs[0].fPresent && !pCtl->aIfs[1].fPresent)
4833 val = 0;
4834 else
4835 val = s->uATARegSelect;
4836 break;
4837 default:
4838 case 7: /* primary status */
4839 {
4840 if (!s->fPresent)
4841 val = 0;
4842 else
4843 val = s->uATARegStatus;
4844
4845 /* Give the async I/O thread an opportunity to make progress,
4846 * don't let it starve by guests polling frequently. EMT has a
4847 * lower priority than the async I/O thread, but sometimes the
4848 * host OS doesn't care. With some guests we are only allowed to
4849 * be busy for about 5 milliseconds in some situations. Note that
4850 * this is no guarantee for any other VBox thread getting
4851 * scheduled, so this just lowers the CPU load a bit when drives
4852 * are busy. It cannot help with timing problems. */
4853 if (val & ATA_STAT_BUSY)
4854 {
4855#ifdef IN_RING3
4856 /* @bugref{1960}: Don't yield all the time, unless it's a reset (can be tricky). */
4857 bool fYield = (s->cBusyStatusHackR3++ & s->cBusyStatusHackR3Rate) == 0
4858 || pCtl->fReset;
4859
4860 ataR3LockLeave(pDevIns, pCtl);
4861
4862 /*
4863 * The thread might be stuck in an I/O operation due to a high I/O
4864 * load on the host (see @bugref{3301}). To perform the reset
4865 * successfully we interrupt the operation by sending a signal to
4866 * the thread if the thread didn't responded in 10ms.
4867 *
4868 * This works only on POSIX hosts (Windows has a CancelSynchronousIo
4869 * function which does the same but it was introduced with Vista) but
4870 * so far this hang was only observed on Linux and Mac OS X.
4871 *
4872 * This is a workaround and needs to be solved properly.
4873 */
4874 if (pCtl->fReset)
4875 {
4876 uint64_t u64ResetTimeStop = RTTimeMilliTS();
4877 if (u64ResetTimeStop - pCtl->u64ResetTime >= 10)
4878 {
4879 LogRel(("PIIX3 ATA LUN#%d: Async I/O thread probably stuck in operation, interrupting\n", s->iLUN));
4880 pCtl->u64ResetTime = u64ResetTimeStop;
4881# ifndef RT_OS_WINDOWS /* We've got this API on windows, but it doesn't necessarily interrupt I/O. */
4882 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
4883 PATACONTROLLERR3 pCtlR3 = &RT_SAFE_SUBSCRIPT(pThisCC->aCts, pCtl->iCtl);
4884 RTThreadPoke(pCtlR3->hAsyncIOThread);
4885# endif
4886 Assert(fYield);
4887 }
4888 }
4889
4890 if (fYield)
4891 {
4892 STAM_REL_PROFILE_ADV_START(&s->StatStatusYields, a);
4893 RTThreadYield();
4894 STAM_REL_PROFILE_ADV_STOP(&s->StatStatusYields, a);
4895 }
4896 ASMNopPause();
4897
4898 ataR3LockEnter(pDevIns, pCtl);
4899
4900 val = s->uATARegStatus;
4901#else /* !IN_RING3 */
4902 /* Cannot yield CPU in raw-mode and ring-0 context. And switching
4903 * to host context for each and every busy status is too costly,
4904 * especially on SMP systems where we don't gain much by
4905 * yielding the CPU to someone else. */
4906 if ((s->cBusyStatusHackRZ++ & s->cBusyStatusHackRZRate) == 1)
4907 {
4908 s->cBusyStatusHackR3 = 0; /* Forces a yield. */
4909 return VINF_IOM_R3_IOPORT_READ;
4910 }
4911#endif /* !IN_RING3 */
4912 }
4913 else
4914 {
4915 s->cBusyStatusHackRZ = 0;
4916 s->cBusyStatusHackR3 = 0;
4917 }
4918 ataUnsetIRQ(pDevIns, pCtl, s);
4919 break;
4920 }
4921 }
4922 Log2(("%s: LUN#%d addr=%#x val=%#04x\n", __FUNCTION__, s->iLUN, addr, val));
4923 *pu32 = val;
4924 return VINF_SUCCESS;
4925}
4926
4927
4928/*
4929 * Read the Alternate status register. Does not affect interrupts.
4930 */
4931static uint32_t ataStatusRead(PATACONTROLLER pCtl, uint32_t uIoPortForLog)
4932{
4933 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
4934 uint32_t val;
4935 RT_NOREF(uIoPortForLog);
4936
4937 Assert(pCtl->aIfs[0].fPresent || pCtl->aIfs[1].fPresent); /* Channel must not be empty. */
4938 if (pCtl->iSelectedIf == 1 && !s->fPresent)
4939 val = 0; /* Device 1 selected, Device 0 responding for it. */
4940 else
4941 val = s->uATARegStatus;
4942 Log2(("%s: LUN#%d read addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN, uIoPortForLog, val));
4943 return val;
4944}
4945
4946static int ataControlWrite(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t val, uint32_t uIoPortForLog)
4947{
4948 RT_NOREF(uIoPortForLog);
4949#ifndef IN_RING3
4950 if ((val ^ pCtl->aIfs[0].uATARegDevCtl) & ATA_DEVCTL_RESET)
4951 return VINF_IOM_R3_IOPORT_WRITE; /* The RESET stuff is too complicated for RC+R0. */
4952#endif /* !IN_RING3 */
4953
4954 Log2(("%s: LUN#%d write addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN, uIoPortForLog, val));
4955 /* RESET is common for both drives attached to a controller. */
4956 if ( !(pCtl->aIfs[0].uATARegDevCtl & ATA_DEVCTL_RESET)
4957 && (val & ATA_DEVCTL_RESET))
4958 {
4959#ifdef IN_RING3
4960 /* Software RESET low to high */
4961 int32_t uCmdWait0 = -1;
4962 int32_t uCmdWait1 = -1;
4963 uint64_t uNow = RTTimeNanoTS();
4964 if (pCtl->aIfs[0].u64CmdTS)
4965 uCmdWait0 = (uNow - pCtl->aIfs[0].u64CmdTS) / 1000;
4966 if (pCtl->aIfs[1].u64CmdTS)
4967 uCmdWait1 = (uNow - pCtl->aIfs[1].u64CmdTS) / 1000;
4968 LogRel(("PIIX3 ATA: Ctl#%d: RESET, DevSel=%d AIOIf=%d CmdIf0=%#04x (%d usec ago) CmdIf1=%#04x (%d usec ago)\n",
4969 pCtl->iCtl, pCtl->iSelectedIf, pCtl->iAIOIf,
4970 pCtl->aIfs[0].uATARegCommand, uCmdWait0,
4971 pCtl->aIfs[1].uATARegCommand, uCmdWait1));
4972 pCtl->fReset = true;
4973 /* Everything must be done after the reset flag is set, otherwise
4974 * there are unavoidable races with the currently executing request
4975 * (which might just finish in the mean time). */
4976 pCtl->fChainedTransfer = false;
4977 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
4978 {
4979 ataR3ResetDevice(pDevIns, pCtl, &pCtl->aIfs[i]);
4980 /* The following cannot be done using ataSetStatusValue() since the
4981 * reset flag is already set, which suppresses all status changes. */
4982 pCtl->aIfs[i].uATARegStatus = ATA_STAT_BUSY | ATA_STAT_SEEK;
4983 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, pCtl->aIfs[i].iLUN, pCtl->aIfs[i].uATARegStatus));
4984 pCtl->aIfs[i].uATARegError = 0x01;
4985 }
4986 pCtl->iSelectedIf = 0;
4987 ataR3AsyncIOClearRequests(pDevIns, pCtl);
4988 Log2(("%s: Ctl#%d: message to async I/O thread, resetA\n", __FUNCTION__, pCtl->iCtl));
4989 if (val & ATA_DEVCTL_HOB)
4990 {
4991 val &= ~ATA_DEVCTL_HOB;
4992 Log2(("%s: ignored setting HOB\n", __FUNCTION__));
4993 }
4994
4995 /* Save the timestamp we started the reset. */
4996 pCtl->u64ResetTime = RTTimeMilliTS();
4997
4998 /* Issue the reset request now. */
4999 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataResetARequest);
5000#else /* !IN_RING3 */
5001 AssertMsgFailed(("RESET handling is too complicated for GC\n"));
5002#endif /* IN_RING3 */
5003 }
5004 else if ( (pCtl->aIfs[0].uATARegDevCtl & ATA_DEVCTL_RESET)
5005 && !(val & ATA_DEVCTL_RESET))
5006 {
5007#ifdef IN_RING3
5008 /* Software RESET high to low */
5009 Log(("%s: deasserting RESET\n", __FUNCTION__));
5010 Log2(("%s: Ctl#%d: message to async I/O thread, resetC\n", __FUNCTION__, pCtl->iCtl));
5011 if (val & ATA_DEVCTL_HOB)
5012 {
5013 val &= ~ATA_DEVCTL_HOB;
5014 Log2(("%s: ignored setting HOB\n", __FUNCTION__));
5015 }
5016 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataResetCRequest);
5017#else /* !IN_RING3 */
5018 AssertMsgFailed(("RESET handling is too complicated for GC\n"));
5019#endif /* IN_RING3 */
5020 }
5021
5022 /* Change of interrupt disable flag. Update interrupt line if interrupt
5023 * is pending on the current interface. */
5024 if ( ((val ^ pCtl->aIfs[0].uATARegDevCtl) & ATA_DEVCTL_DISABLE_IRQ)
5025 && pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].fIrqPending)
5026 {
5027 if (!(val & ATA_DEVCTL_DISABLE_IRQ))
5028 {
5029 Log2(("%s: LUN#%d asserting IRQ (interrupt disable change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN));
5030 /* The BMDMA unit unconditionally sets BM_STATUS_INT if the
5031 * interrupt line is asserted. It monitors the line for a rising
5032 * edge. */
5033 pCtl->BmDma.u8Status |= BM_STATUS_INT;
5034 if (pCtl->irq == 16)
5035 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
5036 else
5037 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 1);
5038 }
5039 else
5040 {
5041 Log2(("%s: LUN#%d deasserting IRQ (interrupt disable change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN));
5042 if (pCtl->irq == 16)
5043 PDMDevHlpPCISetIrq(pDevIns, 0, 0);
5044 else
5045 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 0);
5046 }
5047 }
5048
5049 if (val & ATA_DEVCTL_HOB)
5050 Log2(("%s: set HOB\n", __FUNCTION__));
5051
5052 pCtl->aIfs[0].uATARegDevCtl = val;
5053 pCtl->aIfs[1].uATARegDevCtl = val;
5054
5055 return VINF_SUCCESS;
5056}
5057
5058#if defined(IN_RING0) || defined(IN_RING3)
5059
5060static void ataHCPIOTransfer(PPDMDEVINS pDevIns, PATACONTROLLER pCtl)
5061{
5062 PATADEVSTATE s;
5063
5064 s = &pCtl->aIfs[pCtl->iAIOIf & ATA_SELECTED_IF_MASK];
5065 Log3(("%s: if=%p\n", __FUNCTION__, s));
5066
5067 if (s->cbTotalTransfer && s->iIOBufferCur > s->iIOBufferEnd)
5068 {
5069# ifdef IN_RING3
5070 LogRel(("PIIX3 ATA: LUN#%d: %s data in the middle of a PIO transfer - VERY SLOW\n",
5071 s->iLUN, s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE ? "loading" : "storing"));
5072 /* Any guest OS that triggers this case has a pathetic ATA driver.
5073 * In a real system it would block the CPU via IORDY, here we do it
5074 * very similarly by not continuing with the current instruction
5075 * until the transfer to/from the storage medium is completed. */
5076 uint8_t const iSourceSink = s->iSourceSink;
5077 if ( iSourceSink != ATAFN_SS_NULL
5078 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
5079 {
5080 bool fRedo;
5081 uint8_t status = s->uATARegStatus;
5082 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
5083 PATADEVSTATER3 pDevR3 = &RT_SAFE_SUBSCRIPT(RT_SAFE_SUBSCRIPT(pThisCC->aCts, pCtl->iCtl).aIfs, s->iDev);
5084
5085 ataSetStatusValue(pCtl, s, ATA_STAT_BUSY);
5086 Log2(("%s: calling source/sink function\n", __FUNCTION__));
5087 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
5088 pCtl->fRedo = fRedo;
5089 if (RT_UNLIKELY(fRedo))
5090 return;
5091 ataSetStatusValue(pCtl, s, status);
5092 s->iIOBufferCur = 0;
5093 s->iIOBufferEnd = s->cbElementaryTransfer;
5094 }
5095 else
5096 Assert(iSourceSink == ATAFN_SS_NULL);
5097# else
5098 AssertReleaseFailed();
5099# endif
5100 }
5101 if (s->cbTotalTransfer)
5102 {
5103 if (s->fATAPITransfer)
5104 ataHCPIOTransferLimitATAPI(s);
5105
5106 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
5107 s->cbElementaryTransfer = s->cbTotalTransfer;
5108
5109 Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
5110 __FUNCTION__, s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE ? "T2I" : "I2T",
5111 s->cbTotalTransfer, s->cbElementaryTransfer,
5112 s->iIOBufferCur, s->iIOBufferEnd));
5113 ataHCPIOTransferStart(pCtl, s, s->iIOBufferCur, s->cbElementaryTransfer);
5114 s->cbTotalTransfer -= s->cbElementaryTransfer;
5115 s->iIOBufferCur += s->cbElementaryTransfer;
5116
5117 if (s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
5118 s->cbElementaryTransfer = s->cbTotalTransfer;
5119 }
5120 else
5121 ataHCPIOTransferStop(pDevIns, pCtl, s);
5122}
5123
5124
5125DECLINLINE(void) ataHCPIOTransferFinish(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
5126{
5127 /* Do not interfere with RESET processing if the PIO transfer finishes
5128 * while the RESET line is asserted. */
5129 if (pCtl->fReset)
5130 {
5131 Log2(("%s: Ctl#%d: suppressed continuing PIO transfer as RESET is active\n", __FUNCTION__, pCtl->iCtl));
5132 return;
5133 }
5134
5135 if ( s->uTxDir == PDMMEDIATXDIR_TO_DEVICE
5136 || ( s->iSourceSink != ATAFN_SS_NULL
5137 && s->iIOBufferCur >= s->iIOBufferEnd))
5138 {
5139 /* Need to continue the transfer in the async I/O thread. This is
5140 * the case for write operations or generally for not yet finished
5141 * transfers (some data might need to be read). */
5142 ataSetStatus(pCtl, s, ATA_STAT_BUSY);
5143 ataUnsetStatus(pCtl, s, ATA_STAT_READY | ATA_STAT_DRQ);
5144
5145 Log2(("%s: Ctl#%d: message to async I/O thread, continuing PIO transfer\n", __FUNCTION__, pCtl->iCtl));
5146 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataPIORequest);
5147 }
5148 else
5149 {
5150 /* Either everything finished (though some data might still be pending)
5151 * or some data is pending before the next read is due. */
5152
5153 /* Continue a previously started transfer. */
5154 ataUnsetStatus(pCtl, s, ATA_STAT_DRQ);
5155 ataSetStatus(pCtl, s, ATA_STAT_READY);
5156
5157 if (s->cbTotalTransfer)
5158 {
5159 /* There is more to transfer, happens usually for large ATAPI
5160 * reads - the protocol limits the chunk size to 65534 bytes. */
5161 ataHCPIOTransfer(pDevIns, pCtl);
5162 ataHCSetIRQ(pDevIns, pCtl, s);
5163 }
5164 else
5165 {
5166 Log2(("%s: Ctl#%d: skipping message to async I/O thread, ending PIO transfer\n", __FUNCTION__, pCtl->iCtl));
5167 /* Finish PIO transfer. */
5168 ataHCPIOTransfer(pDevIns, pCtl);
5169 Assert(!pCtl->fRedo);
5170 }
5171 }
5172}
5173
5174#endif /* IN_RING0 || IN_RING3 */
5175
5176/**
5177 * Fallback for ataCopyPioData124 that handles unaligned and out of bounds cases.
5178 *
5179 * @param pIf The device interface to work with.
5180 * @param pbDst The destination buffer.
5181 * @param pbSrc The source buffer.
5182 * @param offStart The start offset (iIOBufferPIODataStart).
5183 * @param cbCopy The number of bytes to copy, either 1, 2 or 4 bytes.
5184 */
5185DECL_NO_INLINE(static, void) ataCopyPioData124Slow(PATADEVSTATE pIf, uint8_t *pbDst, const uint8_t *pbSrc,
5186 uint32_t offStart, uint32_t cbCopy)
5187{
5188 uint32_t const offNext = offStart + cbCopy;
5189 uint32_t const cbIOBuffer = RT_MIN(pIf->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE);
5190
5191 if (offStart + cbCopy > cbIOBuffer)
5192 {
5193 Log(("%s: cbCopy=%#x offStart=%#x cbIOBuffer=%#x offNext=%#x (iIOBufferPIODataEnd=%#x)\n",
5194 __FUNCTION__, cbCopy, offStart, cbIOBuffer, offNext, pIf->iIOBufferPIODataEnd));
5195 if (offStart < cbIOBuffer)
5196 cbCopy = cbIOBuffer - offStart;
5197 else
5198 cbCopy = 0;
5199 }
5200
5201 switch (cbCopy)
5202 {
5203 case 4: pbDst[3] = pbSrc[3]; RT_FALL_THRU();
5204 case 3: pbDst[2] = pbSrc[2]; RT_FALL_THRU();
5205 case 2: pbDst[1] = pbSrc[1]; RT_FALL_THRU();
5206 case 1: pbDst[0] = pbSrc[0]; RT_FALL_THRU();
5207 case 0: break;
5208 default: AssertFailed(); /* impossible */
5209 }
5210
5211 pIf->iIOBufferPIODataStart = offNext;
5212
5213}
5214
5215
5216/**
5217 * Work for ataDataWrite & ataDataRead that copies data without using memcpy.
5218 *
5219 * This also updates pIf->iIOBufferPIODataStart.
5220 *
5221 * The two buffers are either stack (32-bit aligned) or somewhere within
5222 * pIf->abIOBuffer.
5223 *
5224 * @param pIf The device interface to work with.
5225 * @param pbDst The destination buffer.
5226 * @param pbSrc The source buffer.
5227 * @param offStart The start offset (iIOBufferPIODataStart).
5228 * @param cbCopy The number of bytes to copy, either 1, 2 or 4 bytes.
5229 */
5230DECLINLINE(void) ataCopyPioData124(PATADEVSTATE pIf, uint8_t *pbDst, const uint8_t *pbSrc, uint32_t offStart, uint32_t cbCopy)
5231{
5232 /*
5233 * Quick bounds checking can be done by checking that the abIOBuffer offset
5234 * (iIOBufferPIODataStart) is aligned at the transfer size (which is ASSUMED
5235 * to be 1, 2 or 4). However, since we're paranoid and don't currently
5236 * trust iIOBufferPIODataEnd to be within bounds, we current check against the
5237 * IO buffer size too.
5238 */
5239 Assert(cbCopy == 1 || cbCopy == 2 || cbCopy == 4);
5240 if (RT_LIKELY( !(offStart & (cbCopy - 1))
5241 && offStart + cbCopy <= RT_MIN(pIf->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE)))
5242 {
5243 switch (cbCopy)
5244 {
5245 case 4: *(uint32_t *)pbDst = *(uint32_t const *)pbSrc; break;
5246 case 2: *(uint16_t *)pbDst = *(uint16_t const *)pbSrc; break;
5247 case 1: *pbDst = *pbSrc; break;
5248 }
5249 pIf->iIOBufferPIODataStart = offStart + cbCopy;
5250 }
5251 else
5252 ataCopyPioData124Slow(pIf, pbDst, pbSrc, offStart, cbCopy);
5253}
5254
5255
5256/**
5257 * @callback_method_impl{FNIOMIOPORTNEWOUT,
5258 * Port I/O Handler for primary port range OUT operations.}
5259 * @note offPort is an absolute port number!
5260 */
5261static DECLCALLBACK(VBOXSTRICTRC)
5262ataIOPortWrite1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
5263{
5264 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5265 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5266 RT_NOREF(offPort);
5267
5268 Assert((uintptr_t)pvUser < 2);
5269 Assert(offPort == pCtl->IOPortBase1);
5270 Assert(cb == 2 || cb == 4); /* Writes to the data port may be 16-bit or 32-bit. */
5271
5272 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
5273 if (rc == VINF_SUCCESS)
5274 {
5275 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5276 uint32_t const iIOBufferPIODataStart = RT_MIN(s->iIOBufferPIODataStart, sizeof(s->abIOBuffer));
5277 uint32_t const iIOBufferPIODataEnd = RT_MIN(s->iIOBufferPIODataEnd, sizeof(s->abIOBuffer));
5278
5279 if (iIOBufferPIODataStart < iIOBufferPIODataEnd)
5280 {
5281 Assert(s->uTxDir == PDMMEDIATXDIR_TO_DEVICE);
5282 uint8_t *pbDst = &s->abIOBuffer[iIOBufferPIODataStart];
5283 uint8_t const *pbSrc = (uint8_t const *)&u32;
5284
5285#ifdef IN_RC
5286 /* Raw-mode: The ataHCPIOTransfer following the last transfer unit
5287 requires I/O thread signalling, we must go to ring-3 for that. */
5288 if (iIOBufferPIODataStart + cb < iIOBufferPIODataEnd)
5289 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5290 else
5291 rc = VINF_IOM_R3_IOPORT_WRITE;
5292
5293#elif defined(IN_RING0)
5294 /* Ring-0: We can do I/O thread signalling here, however for paranoid reasons
5295 triggered by a special case in ataHCPIOTransferFinish, we take extra care here. */
5296 if (iIOBufferPIODataStart + cb < iIOBufferPIODataEnd)
5297 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5298 else if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE) /* paranoia */
5299 {
5300 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5301 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5302 }
5303 else
5304 {
5305 Log(("%s: Unexpected\n", __FUNCTION__));
5306 rc = VINF_IOM_R3_IOPORT_WRITE;
5307 }
5308
5309#else /* IN_RING 3*/
5310 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5311 if (s->iIOBufferPIODataStart >= iIOBufferPIODataEnd)
5312 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5313#endif /* IN_RING 3*/
5314 }
5315 else
5316 Log2(("%s: DUMMY data\n", __FUNCTION__));
5317
5318 Log3(("%s: addr=%#x val=%.*Rhxs rc=%d\n", __FUNCTION__, offPort + pCtl->IOPortBase1, cb, &u32, VBOXSTRICTRC_VAL(rc)));
5319 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5320 }
5321 else
5322 Log3(("%s: addr=%#x -> %d\n", __FUNCTION__, offPort + pCtl->IOPortBase1, VBOXSTRICTRC_VAL(rc)));
5323 return rc;
5324}
5325
5326
5327/**
5328 * @callback_method_impl{FNIOMIOPORTNEWIN,
5329 * Port I/O Handler for primary port range IN operations.}
5330 * @note offPort is an absolute port number!
5331 */
5332static DECLCALLBACK(VBOXSTRICTRC)
5333ataIOPortRead1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
5334{
5335 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5336 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5337 RT_NOREF(offPort);
5338
5339 Assert((uintptr_t)pvUser < 2);
5340 Assert(offPort == pCtl->IOPortBase1);
5341
5342 /* Reads from the data register may be 16-bit or 32-bit. Byte accesses are
5343 upgraded to word. */
5344 Assert(cb == 1 || cb == 2 || cb == 4);
5345 uint32_t cbActual = cb != 1 ? cb : 2;
5346 *pu32 = 0;
5347
5348 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
5349 if (rc == VINF_SUCCESS)
5350 {
5351 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5352
5353 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd)
5354 {
5355 AssertMsg(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE, ("%#x\n", s->uTxDir));
5356 uint32_t const iIOBufferPIODataStart = RT_MIN(s->iIOBufferPIODataStart, sizeof(s->abIOBuffer));
5357 uint32_t const iIOBufferPIODataEnd = RT_MIN(s->iIOBufferPIODataEnd, sizeof(s->abIOBuffer));
5358 uint8_t const *pbSrc = &s->abIOBuffer[iIOBufferPIODataStart];
5359 uint8_t *pbDst = (uint8_t *)pu32;
5360
5361#ifdef IN_RC
5362 /* All but the last transfer unit is simple enough for RC, but
5363 * sending a request to the async IO thread is too complicated. */
5364 if (iIOBufferPIODataStart + cbActual < iIOBufferPIODataEnd)
5365 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5366 else
5367 rc = VINF_IOM_R3_IOPORT_READ;
5368
5369#elif defined(IN_RING0)
5370 /* Ring-0: We can do I/O thread signalling here. However there is one
5371 case in ataHCPIOTransfer that does a LogRel and would (but not from
5372 here) call directly into the driver code. We detect that odd case
5373 here cand return to ring-3 to handle it. */
5374 if (iIOBufferPIODataStart + cbActual < iIOBufferPIODataEnd)
5375 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5376 else if ( s->cbTotalTransfer == 0
5377 || s->iSourceSink != ATAFN_SS_NULL
5378 || s->iIOBufferCur <= s->iIOBufferEnd)
5379 {
5380 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5381 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5382 }
5383 else
5384 {
5385 Log(("%s: Unexpected\n",__FUNCTION__));
5386 rc = VINF_IOM_R3_IOPORT_READ;
5387 }
5388
5389#else /* IN_RING3 */
5390 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5391 if (s->iIOBufferPIODataStart >= iIOBufferPIODataEnd)
5392 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5393#endif /* IN_RING3 */
5394
5395 /* Just to be on the safe side (caller takes care of this, really). */
5396 if (cb == 1)
5397 *pu32 &= 0xff;
5398 }
5399 else
5400 {
5401 Log2(("%s: DUMMY data\n", __FUNCTION__));
5402 memset(pu32, 0xff, cb);
5403 }
5404 Log3(("%s: addr=%#x val=%.*Rhxs rc=%d\n", __FUNCTION__, offPort, cb, pu32, VBOXSTRICTRC_VAL(rc)));
5405
5406 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5407 }
5408 else
5409 Log3(("%s: addr=%#x -> %d\n", __FUNCTION__, offPort, VBOXSTRICTRC_VAL(rc)));
5410
5411 return rc;
5412}
5413
5414
5415/**
5416 * @callback_method_impl{FNIOMIOPORTNEWINSTRING,
5417 * Port I/O Handler for primary port range IN string operations.}
5418 * @note offPort is an absolute port number!
5419 */
5420static DECLCALLBACK(VBOXSTRICTRC)
5421ataIOPortReadStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint8_t *pbDst, uint32_t *pcTransfers, unsigned cb)
5422{
5423 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5424 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5425 RT_NOREF(offPort);
5426
5427 Assert((uintptr_t)pvUser < 2);
5428 Assert(offPort == pCtl->IOPortBase1);
5429 Assert(*pcTransfers > 0);
5430
5431 VBOXSTRICTRC rc;
5432 if (cb == 2 || cb == 4)
5433 {
5434 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
5435 if (rc == VINF_SUCCESS)
5436 {
5437 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5438
5439 uint32_t const offStart = s->iIOBufferPIODataStart;
5440 uint32_t const offEnd = s->iIOBufferPIODataEnd;
5441 if (offStart < offEnd)
5442 {
5443 /*
5444 * Figure how much we can copy. Usually it's the same as the request.
5445 * The last transfer unit cannot be handled in RC, as it involves
5446 * thread communication. In R0 we let the non-string callback handle it,
5447 * and ditto for overflows/dummy data.
5448 */
5449 uint32_t cAvailable = (offEnd - offStart) / cb;
5450#ifndef IN_RING3
5451 if (cAvailable > 0)
5452 cAvailable--;
5453#endif
5454 uint32_t const cRequested = *pcTransfers;
5455 if (cAvailable > cRequested)
5456 cAvailable = cRequested;
5457 uint32_t const cbTransfer = cAvailable * cb;
5458 uint32_t const offEndThisXfer = offStart + cbTransfer;
5459 if ( offEndThisXfer <= RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE)
5460 && offStart < RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE) /* paranoia */
5461 && cbTransfer > 0)
5462 {
5463 /*
5464 * Do the transfer.
5465 */
5466 uint8_t const *pbSrc = &s->abIOBuffer[offStart];
5467 memcpy(pbDst, pbSrc, cbTransfer);
5468 Log3(("%s: addr=%#x cb=%#x cbTransfer=%#x val=%.*Rhxd\n",
5469 __FUNCTION__, offPort, cb, cbTransfer, cbTransfer, pbSrc));
5470 s->iIOBufferPIODataStart = offEndThisXfer;
5471#ifdef IN_RING3
5472 if (offEndThisXfer >= offEnd)
5473 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5474#endif
5475 *pcTransfers = cRequested - cAvailable;
5476 }
5477 else
5478 Log2(("ataIOPortReadStr1Data: DUMMY/Overflow!\n"));
5479 }
5480 else
5481 {
5482 /*
5483 * Dummy read (shouldn't happen) return 0xff like the non-string handler.
5484 */
5485 Log2(("ataIOPortReadStr1Data: DUMMY data (%#x bytes)\n", *pcTransfers * cb));
5486 memset(pbDst, 0xff, *pcTransfers * cb);
5487 *pcTransfers = 0;
5488 }
5489
5490 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5491 }
5492 }
5493 /*
5494 * Let the non-string I/O callback handle 1 byte reads.
5495 */
5496 else
5497 {
5498 Log2(("ataIOPortReadStr1Data: 1 byte read (%#x transfers)\n", *pcTransfers));
5499 AssertFailed();
5500 rc = VINF_SUCCESS;
5501 }
5502 return rc;
5503}
5504
5505
5506/**
5507 * @callback_method_impl{FNIOMIOPORTNEWOUTSTRING,
5508 * Port I/O Handler for primary port range OUT string operations.}
5509 * @note offPort is an absolute port number!
5510 */
5511static DECLCALLBACK(VBOXSTRICTRC)
5512ataIOPortWriteStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb)
5513{
5514 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5515 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5516 RT_NOREF(offPort);
5517
5518 Assert((uintptr_t)pvUser < 2);
5519 Assert(offPort == pCtl->IOPortBase1);
5520 Assert(*pcTransfers > 0);
5521
5522 VBOXSTRICTRC rc;
5523 if (cb == 2 || cb == 4)
5524 {
5525 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
5526 if (rc == VINF_SUCCESS)
5527 {
5528 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5529
5530 uint32_t const offStart = s->iIOBufferPIODataStart;
5531 uint32_t const offEnd = s->iIOBufferPIODataEnd;
5532 if (offStart < offEnd)
5533 {
5534 /*
5535 * Figure how much we can copy. Usually it's the same as the request.
5536 * The last transfer unit cannot be handled in RC, as it involves
5537 * thread communication. In R0 we let the non-string callback handle it,
5538 * and ditto for overflows/dummy data.
5539 */
5540 uint32_t cAvailable = (offEnd - offStart) / cb;
5541#ifndef IN_RING3
5542 if (cAvailable)
5543 cAvailable--;
5544#endif
5545 uint32_t const cRequested = *pcTransfers;
5546 if (cAvailable > cRequested)
5547 cAvailable = cRequested;
5548 uint32_t const cbTransfer = cAvailable * cb;
5549 uint32_t const offEndThisXfer = offStart + cbTransfer;
5550 if ( offEndThisXfer <= RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE)
5551 && offStart < RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE) /* paranoia */
5552 && cbTransfer > 0)
5553 {
5554 /*
5555 * Do the transfer.
5556 */
5557 void *pvDst = &s->abIOBuffer[offStart];
5558 memcpy(pvDst, pbSrc, cbTransfer);
5559 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, offPort + pCtl->IOPortBase1, cbTransfer, pvDst));
5560 s->iIOBufferPIODataStart = offEndThisXfer;
5561#ifdef IN_RING3
5562 if (offEndThisXfer >= offEnd)
5563 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5564#endif
5565 *pcTransfers = cRequested - cAvailable;
5566 }
5567 else
5568 Log2(("ataIOPortWriteStr1Data: DUMMY/Overflow!\n"));
5569 }
5570 else
5571 {
5572 Log2(("ataIOPortWriteStr1Data: DUMMY data (%#x bytes)\n", *pcTransfers * cb));
5573 *pcTransfers = 0;
5574 }
5575
5576 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5577 }
5578 }
5579 /*
5580 * Let the non-string I/O callback handle 1 byte reads.
5581 */
5582 else
5583 {
5584 Log2(("ataIOPortWriteStr1Data: 1 byte write (%#x transfers)\n", *pcTransfers));
5585 AssertFailed();
5586 rc = VINF_SUCCESS;
5587 }
5588
5589 return rc;
5590}
5591
5592
5593#ifdef IN_RING3
5594
5595static void ataR3DMATransferStop(PATADEVSTATE s)
5596{
5597 s->cbTotalTransfer = 0;
5598 s->cbElementaryTransfer = 0;
5599 s->iBeginTransfer = ATAFN_BT_NULL;
5600 s->iSourceSink = ATAFN_SS_NULL;
5601}
5602
5603
5604/**
5605 * Perform the entire DMA transfer in one go (unless a source/sink operation
5606 * has to be redone or a RESET comes in between). Unlike the PIO counterpart
5607 * this function cannot handle empty transfers.
5608 *
5609 * @param pDevIns The device instance.
5610 * @param pCtl Controller for which to perform the transfer, shared bits.
5611 * @param pCtlR3 The ring-3 controller state.
5612 */
5613static void ataR3DMATransfer(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATACONTROLLERR3 pCtlR3)
5614{
5615 uint8_t const iAIOIf = pCtl->iAIOIf & ATA_SELECTED_IF_MASK;
5616 PATADEVSTATE s = &pCtl->aIfs[iAIOIf];
5617 PATADEVSTATER3 pDevR3 = &pCtlR3->aIfs[iAIOIf];
5618 bool fRedo;
5619 RTGCPHYS32 GCPhysDesc;
5620 uint32_t cbTotalTransfer, cbElementaryTransfer;
5621 uint32_t iIOBufferCur, iIOBufferEnd;
5622 PDMMEDIATXDIR uTxDir;
5623 bool fLastDesc = false;
5624
5625 Assert(sizeof(BMDMADesc) == 8);
5626
5627 fRedo = pCtl->fRedo;
5628 if (RT_LIKELY(!fRedo))
5629 Assert(s->cbTotalTransfer);
5630 uTxDir = (PDMMEDIATXDIR)s->uTxDir;
5631 cbTotalTransfer = s->cbTotalTransfer;
5632 cbElementaryTransfer = RT_MIN(s->cbElementaryTransfer, sizeof(s->abIOBuffer));
5633 iIOBufferEnd = RT_MIN(s->iIOBufferEnd, sizeof(s->abIOBuffer));
5634 iIOBufferCur = RT_MIN(RT_MIN(s->iIOBufferCur, sizeof(s->abIOBuffer)), iIOBufferEnd);
5635
5636 /* The DMA loop is designed to hold the lock only when absolutely
5637 * necessary. This avoids long freezes should the guest access the
5638 * ATA registers etc. for some reason. */
5639 ataR3LockLeave(pDevIns, pCtl);
5640
5641 Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
5642 __FUNCTION__, uTxDir == PDMMEDIATXDIR_FROM_DEVICE ? "T2I" : "I2T",
5643 cbTotalTransfer, cbElementaryTransfer,
5644 iIOBufferCur, iIOBufferEnd));
5645 for (GCPhysDesc = pCtl->GCPhysFirstDMADesc;
5646 GCPhysDesc <= pCtl->GCPhysLastDMADesc;
5647 GCPhysDesc += sizeof(BMDMADesc))
5648 {
5649 BMDMADesc DMADesc;
5650 RTGCPHYS32 GCPhysBuffer;
5651 uint32_t cbBuffer;
5652
5653 if (RT_UNLIKELY(fRedo))
5654 {
5655 GCPhysBuffer = pCtl->GCPhysRedoDMABuffer;
5656 cbBuffer = pCtl->cbRedoDMABuffer;
5657 fLastDesc = pCtl->fRedoDMALastDesc;
5658 DMADesc.GCPhysBuffer = DMADesc.cbBuffer = 0; /* Shut up MSC. */
5659 }
5660 else
5661 {
5662 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysDesc, &DMADesc, sizeof(BMDMADesc));
5663 GCPhysBuffer = RT_LE2H_U32(DMADesc.GCPhysBuffer);
5664 cbBuffer = RT_LE2H_U32(DMADesc.cbBuffer);
5665 fLastDesc = RT_BOOL(cbBuffer & UINT32_C(0x80000000));
5666 cbBuffer &= 0xfffe;
5667 if (cbBuffer == 0)
5668 cbBuffer = 0x10000;
5669 if (cbBuffer > cbTotalTransfer)
5670 cbBuffer = cbTotalTransfer;
5671 }
5672
5673 while (RT_UNLIKELY(fRedo) || (cbBuffer && cbTotalTransfer))
5674 {
5675 if (RT_LIKELY(!fRedo))
5676 {
5677 uint32_t cbXfer = RT_MIN(RT_MIN(cbBuffer, iIOBufferEnd - iIOBufferCur),
5678 sizeof(s->abIOBuffer) - RT_MIN(iIOBufferCur, sizeof(s->abIOBuffer)));
5679 Log2(("%s: DMA desc %#010x: addr=%#010x size=%#010x orig_size=%#010x\n", __FUNCTION__,
5680 (int)GCPhysDesc, GCPhysBuffer, cbBuffer, RT_LE2H_U32(DMADesc.cbBuffer) & 0xfffe));
5681
5682 if (uTxDir == PDMMEDIATXDIR_FROM_DEVICE)
5683 PDMDevHlpPCIPhysWriteUser(pDevIns, GCPhysBuffer, &s->abIOBuffer[iIOBufferCur], cbXfer);
5684 else
5685 PDMDevHlpPCIPhysReadUser(pDevIns, GCPhysBuffer, &s->abIOBuffer[iIOBufferCur], cbXfer);
5686
5687 iIOBufferCur += cbXfer;
5688 cbTotalTransfer -= cbXfer;
5689 cbBuffer -= cbXfer;
5690 GCPhysBuffer += cbXfer;
5691 }
5692 if ( iIOBufferCur == iIOBufferEnd
5693 && (uTxDir == PDMMEDIATXDIR_TO_DEVICE || cbTotalTransfer))
5694 {
5695 if (uTxDir == PDMMEDIATXDIR_FROM_DEVICE && cbElementaryTransfer > cbTotalTransfer)
5696 cbElementaryTransfer = cbTotalTransfer;
5697
5698 ataR3LockEnter(pDevIns, pCtl);
5699
5700 /* The RESET handler could have cleared the DMA transfer
5701 * state (since we didn't hold the lock until just now
5702 * the guest can continue in parallel). If so, the state
5703 * is already set up so the loop is exited immediately. */
5704 uint8_t const iSourceSink = s->iSourceSink;
5705 if ( iSourceSink != ATAFN_SS_NULL
5706 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
5707 {
5708 s->iIOBufferCur = iIOBufferCur;
5709 s->iIOBufferEnd = iIOBufferEnd;
5710 s->cbElementaryTransfer = cbElementaryTransfer;
5711 s->cbTotalTransfer = cbTotalTransfer;
5712 Log2(("%s: calling source/sink function\n", __FUNCTION__));
5713 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
5714 if (RT_UNLIKELY(fRedo))
5715 {
5716 pCtl->GCPhysFirstDMADesc = GCPhysDesc;
5717 pCtl->GCPhysRedoDMABuffer = GCPhysBuffer;
5718 pCtl->cbRedoDMABuffer = cbBuffer;
5719 pCtl->fRedoDMALastDesc = fLastDesc;
5720 }
5721 else
5722 {
5723 cbTotalTransfer = s->cbTotalTransfer;
5724 cbElementaryTransfer = s->cbElementaryTransfer;
5725
5726 if (uTxDir == PDMMEDIATXDIR_TO_DEVICE && cbElementaryTransfer > cbTotalTransfer)
5727 cbElementaryTransfer = cbTotalTransfer;
5728 iIOBufferCur = 0;
5729 iIOBufferEnd = RT_MIN(cbElementaryTransfer, sizeof(s->abIOBuffer));
5730 }
5731 pCtl->fRedo = fRedo;
5732 }
5733 else
5734 {
5735 /* This forces the loop to exit immediately. */
5736 Assert(iSourceSink == ATAFN_SS_NULL);
5737 GCPhysDesc = pCtl->GCPhysLastDMADesc + 1;
5738 }
5739
5740 ataR3LockLeave(pDevIns, pCtl);
5741 if (RT_UNLIKELY(fRedo))
5742 break;
5743 }
5744 }
5745
5746 if (RT_UNLIKELY(fRedo))
5747 break;
5748
5749 /* end of transfer */
5750 if (!cbTotalTransfer || fLastDesc)
5751 break;
5752
5753 ataR3LockEnter(pDevIns, pCtl);
5754
5755 if (!(pCtl->BmDma.u8Cmd & BM_CMD_START) || pCtl->fReset)
5756 {
5757 LogRel(("PIIX3 ATA: Ctl#%d: ABORT DMA%s\n", pCtl->iCtl, pCtl->fReset ? " due to RESET" : ""));
5758 if (!pCtl->fReset)
5759 ataR3DMATransferStop(s);
5760 /* This forces the loop to exit immediately. */
5761 GCPhysDesc = pCtl->GCPhysLastDMADesc + 1;
5762 }
5763
5764 ataR3LockLeave(pDevIns, pCtl);
5765 }
5766
5767 ataR3LockEnter(pDevIns, pCtl);
5768 if (RT_UNLIKELY(fRedo))
5769 return;
5770
5771 if (fLastDesc)
5772 pCtl->BmDma.u8Status &= ~BM_STATUS_DMAING;
5773 s->cbTotalTransfer = cbTotalTransfer;
5774 s->cbElementaryTransfer = cbElementaryTransfer;
5775 s->iIOBufferCur = iIOBufferCur;
5776 s->iIOBufferEnd = iIOBufferEnd;
5777}
5778
5779/**
5780 * Signal PDM that we're idle (if we actually are).
5781 *
5782 * @param pDevIns The device instance.
5783 * @param pCtl The shared controller state.
5784 * @param pCtlR3 The ring-3 controller state.
5785 */
5786static void ataR3AsyncSignalIdle(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATACONTROLLERR3 pCtlR3)
5787{
5788 /*
5789 * Take the lock here and recheck the idle indicator to avoid
5790 * unnecessary work and racing ataR3WaitForAsyncIOIsIdle.
5791 */
5792 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
5793 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
5794
5795 if ( pCtlR3->fSignalIdle
5796 && ataR3AsyncIOIsIdle(pDevIns, pCtl, false /*fStrict*/))
5797 {
5798 PDMDevHlpAsyncNotificationCompleted(pDevIns);
5799 RTThreadUserSignal(pCtlR3->hAsyncIOThread); /* for ataR3Construct/ataR3ResetCommon. */
5800 }
5801
5802 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
5803 AssertRC(rc);
5804}
5805
5806/**
5807 * Async I/O thread for an interface.
5808 *
5809 * Once upon a time this was readable code with several loops and a different
5810 * semaphore for each purpose. But then came the "how can one save the state in
5811 * the middle of a PIO transfer" question. The solution was to use an ASM,
5812 * which is what's there now.
5813 */
5814static DECLCALLBACK(int) ataR3AsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)
5815{
5816 PATACONTROLLERR3 const pCtlR3 = (PATACONTROLLERR3)pvUser;
5817 PPDMDEVINSR3 const pDevIns = pCtlR3->pDevIns;
5818 PATASTATE const pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5819 PATASTATER3 const pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
5820 uintptr_t const iCtl = pCtlR3 - &pThisCC->aCts[0];
5821 PATACONTROLLER const pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, iCtl);
5822 int rc = VINF_SUCCESS;
5823 uint64_t u64TS = 0; /* shut up gcc */
5824 uint64_t uWait;
5825 const ATARequest *pReq;
5826 RT_NOREF(hThreadSelf);
5827 Assert(pCtl->iCtl == pCtlR3->iCtl);
5828
5829 pReq = NULL;
5830 pCtl->fChainedTransfer = false;
5831 while (!pCtlR3->fShutdown)
5832 {
5833 /* Keep this thread from doing anything as long as EMT is suspended. */
5834 while (pCtl->fRedoIdle)
5835 {
5836 if (pCtlR3->fSignalIdle)
5837 ataR3AsyncSignalIdle(pDevIns, pCtl, pCtlR3);
5838 rc = RTSemEventWait(pCtlR3->hSuspendIOSem, RT_INDEFINITE_WAIT);
5839 /* Continue if we got a signal by RTThreadPoke().
5840 * We will get notified if there is a request to process.
5841 */
5842 if (RT_UNLIKELY(rc == VERR_INTERRUPTED))
5843 continue;
5844 if (RT_FAILURE(rc) || pCtlR3->fShutdown)
5845 break;
5846
5847 pCtl->fRedoIdle = false;
5848 }
5849
5850 /* Wait for work. */
5851 while (pReq == NULL)
5852 {
5853 if (pCtlR3->fSignalIdle)
5854 ataR3AsyncSignalIdle(pDevIns, pCtl, pCtlR3);
5855 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pCtl->hAsyncIOSem, RT_INDEFINITE_WAIT);
5856 /* Continue if we got a signal by RTThreadPoke().
5857 * We will get notified if there is a request to process.
5858 */
5859 if (RT_UNLIKELY(rc == VERR_INTERRUPTED))
5860 continue;
5861 if (RT_FAILURE(rc) || RT_UNLIKELY(pCtlR3->fShutdown))
5862 break;
5863
5864 pReq = ataR3AsyncIOGetCurrentRequest(pDevIns, pCtl);
5865 }
5866
5867 if (RT_FAILURE(rc) || pCtlR3->fShutdown)
5868 break;
5869
5870 if (pReq == NULL)
5871 continue;
5872
5873 ATAAIO ReqType = pReq->ReqType;
5874
5875 Log2(("%s: Ctl#%d: state=%d, req=%d\n", __FUNCTION__, pCtl->iCtl, pCtl->uAsyncIOState, ReqType));
5876 if (pCtl->uAsyncIOState != ReqType)
5877 {
5878 /* The new state is not the state that was expected by the normal
5879 * state changes. This is either a RESET/ABORT or there's something
5880 * really strange going on. */
5881 if ( (pCtl->uAsyncIOState == ATA_AIO_PIO || pCtl->uAsyncIOState == ATA_AIO_DMA)
5882 && (ReqType == ATA_AIO_PIO || ReqType == ATA_AIO_DMA))
5883 {
5884 /* Incorrect sequence of PIO/DMA states. Dump request queue. */
5885 ataR3AsyncIODumpRequests(pDevIns, pCtl);
5886 }
5887 AssertReleaseMsg( ReqType == ATA_AIO_RESET_ASSERTED
5888 || ReqType == ATA_AIO_RESET_CLEARED
5889 || ReqType == ATA_AIO_ABORT
5890 || pCtl->uAsyncIOState == ReqType,
5891 ("I/O state inconsistent: state=%d request=%d\n", pCtl->uAsyncIOState, ReqType));
5892 }
5893
5894 /* Do our work. */
5895 ataR3LockEnter(pDevIns, pCtl);
5896
5897 if (pCtl->uAsyncIOState == ATA_AIO_NEW && !pCtl->fChainedTransfer)
5898 {
5899 u64TS = RTTimeNanoTS();
5900#if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
5901 STAM_PROFILE_ADV_START(&pCtl->StatAsyncTime, a);
5902#endif
5903 }
5904
5905 switch (ReqType)
5906 {
5907 case ATA_AIO_NEW:
5908 {
5909 uint8_t const iIf = pReq->u.t.iIf & ATA_SELECTED_IF_MASK;
5910 pCtl->iAIOIf = iIf;
5911 PATADEVSTATE s = &pCtl->aIfs[iIf];
5912 PATADEVSTATER3 pDevR3 = &pCtlR3->aIfs[iIf];
5913
5914 s->cbTotalTransfer = pReq->u.t.cbTotalTransfer;
5915 s->uTxDir = pReq->u.t.uTxDir;
5916 s->iBeginTransfer = pReq->u.t.iBeginTransfer;
5917 s->iSourceSink = pReq->u.t.iSourceSink;
5918 s->iIOBufferEnd = 0;
5919 s->u64CmdTS = u64TS;
5920
5921 if (s->fATAPI)
5922 {
5923 if (pCtl->fChainedTransfer)
5924 {
5925 /* Only count the actual transfers, not the PIO
5926 * transfer of the ATAPI command bytes. */
5927 if (s->fDMA)
5928 STAM_REL_COUNTER_INC(&s->StatATAPIDMA);
5929 else
5930 STAM_REL_COUNTER_INC(&s->StatATAPIPIO);
5931 }
5932 }
5933 else
5934 {
5935 if (s->fDMA)
5936 STAM_REL_COUNTER_INC(&s->StatATADMA);
5937 else
5938 STAM_REL_COUNTER_INC(&s->StatATAPIO);
5939 }
5940
5941 pCtl->fChainedTransfer = false;
5942
5943 uint8_t const iBeginTransfer = s->iBeginTransfer;
5944 if ( iBeginTransfer != ATAFN_BT_NULL
5945 && iBeginTransfer < RT_ELEMENTS(g_apfnBeginTransFuncs))
5946 {
5947 Log2(("%s: Ctl#%d: calling begin transfer function\n", __FUNCTION__, pCtl->iCtl));
5948 g_apfnBeginTransFuncs[iBeginTransfer](pCtl, s);
5949 s->iBeginTransfer = ATAFN_BT_NULL;
5950 if (s->uTxDir != PDMMEDIATXDIR_FROM_DEVICE)
5951 s->iIOBufferEnd = s->cbElementaryTransfer;
5952 }
5953 else
5954 {
5955 Assert(iBeginTransfer == ATAFN_BT_NULL);
5956 s->cbElementaryTransfer = s->cbTotalTransfer;
5957 s->iIOBufferEnd = s->cbTotalTransfer;
5958 }
5959 s->iIOBufferCur = 0;
5960
5961 if (s->uTxDir != PDMMEDIATXDIR_TO_DEVICE)
5962 {
5963 uint8_t const iSourceSink = s->iSourceSink;
5964 if ( iSourceSink != ATAFN_SS_NULL
5965 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
5966 {
5967 bool fRedo;
5968 Log2(("%s: Ctl#%d: calling source/sink function\n", __FUNCTION__, pCtl->iCtl));
5969 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
5970 pCtl->fRedo = fRedo;
5971 if (RT_UNLIKELY(fRedo && !pCtl->fReset))
5972 {
5973 /* Operation failed at the initial transfer, restart
5974 * everything from scratch by resending the current
5975 * request. Occurs very rarely, not worth optimizing. */
5976 LogRel(("%s: Ctl#%d: redo entire operation\n", __FUNCTION__, pCtl->iCtl));
5977 ataHCAsyncIOPutRequest(pDevIns, pCtl, pReq);
5978 break;
5979 }
5980 }
5981 else
5982 {
5983 Assert(iSourceSink == ATAFN_SS_NULL);
5984 ataR3CmdOK(pCtl, s, 0);
5985 }
5986 s->iIOBufferEnd = s->cbElementaryTransfer;
5987
5988 }
5989
5990 /* Do not go into the transfer phase if RESET is asserted.
5991 * The CritSect is released while waiting for the host OS
5992 * to finish the I/O, thus RESET is possible here. Most
5993 * important: do not change uAsyncIOState. */
5994 if (pCtl->fReset)
5995 break;
5996
5997 if (s->fDMA)
5998 {
5999 if (s->cbTotalTransfer)
6000 {
6001 ataSetStatus(pCtl, s, ATA_STAT_DRQ);
6002
6003 pCtl->uAsyncIOState = ATA_AIO_DMA;
6004 /* If BMDMA is already started, do the transfer now. */
6005 if (pCtl->BmDma.u8Cmd & BM_CMD_START)
6006 {
6007 Log2(("%s: Ctl#%d: message to async I/O thread, continuing DMA transfer immediately\n", __FUNCTION__, pCtl->iCtl));
6008 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataDMARequest);
6009 }
6010 }
6011 else
6012 {
6013 Assert(s->uTxDir == PDMMEDIATXDIR_NONE); /* Any transfer which has an initial transfer size of 0 must be marked as such. */
6014 /* Finish DMA transfer. */
6015 ataR3DMATransferStop(s);
6016 ataHCSetIRQ(pDevIns, pCtl, s);
6017 pCtl->uAsyncIOState = ATA_AIO_NEW;
6018 }
6019 }
6020 else
6021 {
6022 if (s->cbTotalTransfer)
6023 {
6024 ataHCPIOTransfer(pDevIns, pCtl);
6025 Assert(!pCtl->fRedo);
6026 if (s->fATAPITransfer || s->uTxDir != PDMMEDIATXDIR_TO_DEVICE)
6027 ataHCSetIRQ(pDevIns, pCtl, s);
6028
6029 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
6030 {
6031 /* Write operations and not yet finished transfers
6032 * must be completed in the async I/O thread. */
6033 pCtl->uAsyncIOState = ATA_AIO_PIO;
6034 }
6035 else
6036 {
6037 /* Finished read operation can be handled inline
6038 * in the end of PIO transfer handling code. Linux
6039 * depends on this, as it waits only briefly for
6040 * devices to become ready after incoming data
6041 * transfer. Cannot find anything in the ATA spec
6042 * that backs this assumption, but as all kernels
6043 * are affected (though most of the time it does
6044 * not cause any harm) this must work. */
6045 pCtl->uAsyncIOState = ATA_AIO_NEW;
6046 }
6047 }
6048 else
6049 {
6050 Assert(s->uTxDir == PDMMEDIATXDIR_NONE); /* Any transfer which has an initial transfer size of 0 must be marked as such. */
6051 /* Finish PIO transfer. */
6052 ataHCPIOTransfer(pDevIns, pCtl);
6053 Assert(!pCtl->fRedo);
6054 if (!s->fATAPITransfer)
6055 ataHCSetIRQ(pDevIns, pCtl, s);
6056 pCtl->uAsyncIOState = ATA_AIO_NEW;
6057 }
6058 }
6059 break;
6060 }
6061
6062 case ATA_AIO_DMA:
6063 {
6064 BMDMAState *bm = &pCtl->BmDma;
6065 PATADEVSTATE s = &pCtl->aIfs[pCtl->iAIOIf & ATA_SELECTED_IF_MASK];
6066 ATAFNSS iOriginalSourceSink = (ATAFNSS)s->iSourceSink; /* Used by the hack below, but gets reset by then. */
6067
6068 if (s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE)
6069 AssertRelease(bm->u8Cmd & BM_CMD_WRITE);
6070 else
6071 AssertRelease(!(bm->u8Cmd & BM_CMD_WRITE));
6072
6073 if (RT_LIKELY(!pCtl->fRedo))
6074 {
6075 /* The specs say that the descriptor table must not cross a
6076 * 4K boundary. */
6077 pCtl->GCPhysFirstDMADesc = bm->GCPhysAddr;
6078 pCtl->GCPhysLastDMADesc = RT_ALIGN_32(bm->GCPhysAddr + 1, _4K) - sizeof(BMDMADesc);
6079 }
6080 ataR3DMATransfer(pDevIns, pCtl, pCtlR3);
6081
6082 if (RT_UNLIKELY(pCtl->fRedo && !pCtl->fReset))
6083 {
6084 LogRel(("PIIX3 ATA: Ctl#%d: redo DMA operation\n", pCtl->iCtl));
6085 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataDMARequest);
6086 break;
6087 }
6088
6089 /* The infamous delay IRQ hack. */
6090 if ( iOriginalSourceSink == ATAFN_SS_WRITE_SECTORS
6091 && s->cbTotalTransfer == 0
6092 && pCtl->msDelayIRQ)
6093 {
6094 /* Delay IRQ for writing. Required to get the Win2K
6095 * installation work reliably (otherwise it crashes,
6096 * usually during component install). So far no better
6097 * solution has been found. */
6098 Log(("%s: delay IRQ hack\n", __FUNCTION__));
6099 ataR3LockLeave(pDevIns, pCtl);
6100 RTThreadSleep(pCtl->msDelayIRQ);
6101 ataR3LockEnter(pDevIns, pCtl);
6102 }
6103
6104 ataUnsetStatus(pCtl, s, ATA_STAT_DRQ);
6105 Assert(!pCtl->fChainedTransfer);
6106 Assert(s->iSourceSink == ATAFN_SS_NULL);
6107 if (s->fATAPITransfer)
6108 {
6109 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
6110 Log2(("%s: Ctl#%d: interrupt reason %#04x\n", __FUNCTION__, pCtl->iCtl, s->uATARegNSector));
6111 s->fATAPITransfer = false;
6112 }
6113 ataHCSetIRQ(pDevIns, pCtl, s);
6114 pCtl->uAsyncIOState = ATA_AIO_NEW;
6115 break;
6116 }
6117
6118 case ATA_AIO_PIO:
6119 {
6120 uint8_t const iIf = pCtl->iAIOIf & ATA_SELECTED_IF_MASK;
6121 pCtl->iAIOIf = iIf;
6122 PATADEVSTATE s = &pCtl->aIfs[iIf];
6123 PATADEVSTATER3 pDevR3 = &pCtlR3->aIfs[iIf];
6124
6125 uint8_t const iSourceSink = s->iSourceSink;
6126 if ( iSourceSink != ATAFN_SS_NULL
6127 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
6128 {
6129 bool fRedo;
6130 Log2(("%s: Ctl#%d: calling source/sink function\n", __FUNCTION__, pCtl->iCtl));
6131 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
6132 pCtl->fRedo = fRedo;
6133 if (RT_UNLIKELY(fRedo && !pCtl->fReset))
6134 {
6135 LogRel(("PIIX3 ATA: Ctl#%d: redo PIO operation\n", pCtl->iCtl));
6136 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataPIORequest);
6137 break;
6138 }
6139 s->iIOBufferCur = 0;
6140 s->iIOBufferEnd = s->cbElementaryTransfer;
6141 }
6142 else
6143 {
6144 /* Continue a previously started transfer. */
6145 Assert(iSourceSink == ATAFN_SS_NULL);
6146 ataUnsetStatus(pCtl, s, ATA_STAT_BUSY);
6147 ataSetStatus(pCtl, s, ATA_STAT_READY);
6148 }
6149
6150 /* It is possible that the drives on this controller get RESET
6151 * during the above call to the source/sink function. If that's
6152 * the case, don't restart the transfer and don't finish it the
6153 * usual way. RESET handling took care of all that already.
6154 * Most important: do not change uAsyncIOState. */
6155 if (pCtl->fReset)
6156 break;
6157
6158 if (s->cbTotalTransfer)
6159 {
6160 ataHCPIOTransfer(pDevIns, pCtl);
6161 ataHCSetIRQ(pDevIns, pCtl, s);
6162
6163 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
6164 {
6165 /* Write operations and not yet finished transfers
6166 * must be completed in the async I/O thread. */
6167 pCtl->uAsyncIOState = ATA_AIO_PIO;
6168 }
6169 else
6170 {
6171 /* Finished read operation can be handled inline
6172 * in the end of PIO transfer handling code. Linux
6173 * depends on this, as it waits only briefly for
6174 * devices to become ready after incoming data
6175 * transfer. Cannot find anything in the ATA spec
6176 * that backs this assumption, but as all kernels
6177 * are affected (though most of the time it does
6178 * not cause any harm) this must work. */
6179 pCtl->uAsyncIOState = ATA_AIO_NEW;
6180 }
6181 }
6182 else
6183 {
6184 /* The infamous delay IRQ hack. */
6185 if (RT_UNLIKELY(pCtl->msDelayIRQ))
6186 {
6187 /* Various antique guests have buggy disk drivers silently
6188 * assuming that disk operations take a relatively long time.
6189 * Work around such bugs by holding off interrupts a bit.
6190 */
6191 Log(("%s: delay IRQ hack (PIO)\n", __FUNCTION__));
6192 ataR3LockLeave(pDevIns, pCtl);
6193 RTThreadSleep(pCtl->msDelayIRQ);
6194 ataR3LockEnter(pDevIns, pCtl);
6195 }
6196
6197 /* Finish PIO transfer. */
6198 ataHCPIOTransfer(pDevIns, pCtl);
6199 if ( !pCtl->fChainedTransfer
6200 && !s->fATAPITransfer
6201 && s->uTxDir != PDMMEDIATXDIR_FROM_DEVICE)
6202 {
6203 ataHCSetIRQ(pDevIns, pCtl, s);
6204 }
6205 pCtl->uAsyncIOState = ATA_AIO_NEW;
6206 }
6207 break;
6208 }
6209
6210 case ATA_AIO_RESET_ASSERTED:
6211 pCtl->uAsyncIOState = ATA_AIO_RESET_CLEARED;
6212 ataHCPIOTransferStop(pDevIns, pCtl, &pCtl->aIfs[0]);
6213 ataHCPIOTransferStop(pDevIns, pCtl, &pCtl->aIfs[1]);
6214 /* Do not change the DMA registers, they are not affected by the
6215 * ATA controller reset logic. It should be sufficient to issue a
6216 * new command, which is now possible as the state is cleared. */
6217 break;
6218
6219 case ATA_AIO_RESET_CLEARED:
6220 pCtl->uAsyncIOState = ATA_AIO_NEW;
6221 pCtl->fReset = false;
6222 /* Ensure that half-completed transfers are not redone. A reset
6223 * cancels the entire transfer, so continuing is wrong. */
6224 pCtl->fRedo = false;
6225 pCtl->fRedoDMALastDesc = false;
6226 LogRel(("PIIX3 ATA: Ctl#%d: finished processing RESET\n", pCtl->iCtl));
6227 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
6228 {
6229 ataR3SetSignature(&pCtl->aIfs[i]);
6230 if (pCtl->aIfs[i].fATAPI)
6231 ataSetStatusValue(pCtl, &pCtl->aIfs[i], 0); /* NOTE: READY is _not_ set */
6232 else
6233 ataSetStatusValue(pCtl, &pCtl->aIfs[i], ATA_STAT_READY | ATA_STAT_SEEK);
6234 }
6235 break;
6236
6237 case ATA_AIO_ABORT:
6238 {
6239 /* Abort the current command no matter what. There cannot be
6240 * any command activity on the other drive otherwise using
6241 * one thread per controller wouldn't work at all. */
6242 PATADEVSTATE s = &pCtl->aIfs[pReq->u.a.iIf & ATA_SELECTED_IF_MASK];
6243
6244 pCtl->uAsyncIOState = ATA_AIO_NEW;
6245 /* Do not change the DMA registers, they are not affected by the
6246 * ATA controller reset logic. It should be sufficient to issue a
6247 * new command, which is now possible as the state is cleared. */
6248 if (pReq->u.a.fResetDrive)
6249 {
6250 ataR3ResetDevice(pDevIns, pCtl, s);
6251 ataR3DeviceDiag(pCtl, s);
6252 }
6253 else
6254 {
6255 /* Stop any pending DMA transfer. */
6256 s->fDMA = false;
6257 ataHCPIOTransferStop(pDevIns, pCtl, s);
6258 ataUnsetStatus(pCtl, s, ATA_STAT_BUSY | ATA_STAT_DRQ | ATA_STAT_SEEK | ATA_STAT_ERR);
6259 ataSetStatus(pCtl, s, ATA_STAT_READY);
6260 ataHCSetIRQ(pDevIns, pCtl, s);
6261 }
6262 break;
6263 }
6264
6265 default:
6266 AssertMsgFailed(("Undefined async I/O state %d\n", pCtl->uAsyncIOState));
6267 }
6268
6269 ataR3AsyncIORemoveCurrentRequest(pDevIns, pCtl, ReqType);
6270 pReq = ataR3AsyncIOGetCurrentRequest(pDevIns, pCtl);
6271
6272 if (pCtl->uAsyncIOState == ATA_AIO_NEW && !pCtl->fChainedTransfer)
6273 {
6274# if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
6275 STAM_PROFILE_ADV_STOP(&pCtl->StatAsyncTime, a);
6276# endif
6277
6278 u64TS = RTTimeNanoTS() - u64TS;
6279 uWait = u64TS / 1000;
6280 uintptr_t const iAIOIf = pCtl->iAIOIf & ATA_SELECTED_IF_MASK;
6281 Log(("%s: Ctl#%d: LUN#%d finished I/O transaction in %d microseconds\n",
6282 __FUNCTION__, pCtl->iCtl, pCtl->aIfs[iAIOIf].iLUN, (uint32_t)(uWait)));
6283 /* Mark command as finished. */
6284 pCtl->aIfs[iAIOIf].u64CmdTS = 0;
6285
6286 /*
6287 * Release logging of command execution times depends on the
6288 * command type. ATAPI commands often take longer (due to CD/DVD
6289 * spin up time etc.) so the threshold is different.
6290 */
6291 if (pCtl->aIfs[iAIOIf].uATARegCommand != ATA_PACKET)
6292 {
6293 if (uWait > 8 * 1000 * 1000)
6294 {
6295 /*
6296 * Command took longer than 8 seconds. This is close
6297 * enough or over the guest's command timeout, so place
6298 * an entry in the release log to allow tracking such
6299 * timing errors (which are often caused by the host).
6300 */
6301 LogRel(("PIIX3 ATA: execution time for ATA command %#04x was %d seconds\n",
6302 pCtl->aIfs[iAIOIf].uATARegCommand, uWait / (1000 * 1000)));
6303 }
6304 }
6305 else
6306 {
6307 if (uWait > 20 * 1000 * 1000)
6308 {
6309 /*
6310 * Command took longer than 20 seconds. This is close
6311 * enough or over the guest's command timeout, so place
6312 * an entry in the release log to allow tracking such
6313 * timing errors (which are often caused by the host).
6314 */
6315 LogRel(("PIIX3 ATA: execution time for ATAPI command %#04x was %d seconds\n",
6316 pCtl->aIfs[iAIOIf].abATAPICmd[0], uWait / (1000 * 1000)));
6317 }
6318 }
6319
6320# if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
6321 if (uWait < pCtl->StatAsyncMinWait || !pCtl->StatAsyncMinWait)
6322 pCtl->StatAsyncMinWait = uWait;
6323 if (uWait > pCtl->StatAsyncMaxWait)
6324 pCtl->StatAsyncMaxWait = uWait;
6325
6326 STAM_COUNTER_ADD(&pCtl->StatAsyncTimeUS, uWait);
6327 STAM_COUNTER_INC(&pCtl->StatAsyncOps);
6328# endif /* DEBUG || VBOX_WITH_STATISTICS */
6329 }
6330
6331 ataR3LockLeave(pDevIns, pCtl);
6332 }
6333
6334 /* Signal the ultimate idleness. */
6335 RTThreadUserSignal(pCtlR3->hAsyncIOThread);
6336 if (pCtlR3->fSignalIdle)
6337 PDMDevHlpAsyncNotificationCompleted(pDevIns);
6338
6339 /* Cleanup the state. */
6340 /* Do not destroy request lock yet, still needed for proper shutdown. */
6341 pCtlR3->fShutdown = false;
6342
6343 Log2(("%s: Ctl#%d: return %Rrc\n", __FUNCTION__, pCtl->iCtl, rc));
6344 return rc;
6345}
6346
6347#endif /* IN_RING3 */
6348
6349static uint32_t ataBMDMACmdReadB(PATACONTROLLER pCtl, uint32_t addr)
6350{
6351 uint32_t val = pCtl->BmDma.u8Cmd;
6352 RT_NOREF(addr);
6353 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6354 return val;
6355}
6356
6357
6358static void ataBMDMACmdWriteB(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6359{
6360 RT_NOREF(pDevIns, addr);
6361 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6362 if (!(val & BM_CMD_START))
6363 {
6364 pCtl->BmDma.u8Status &= ~BM_STATUS_DMAING;
6365 pCtl->BmDma.u8Cmd = val & (BM_CMD_START | BM_CMD_WRITE);
6366 }
6367 else
6368 {
6369#ifndef IN_RC
6370 /* Check whether the guest OS wants to change DMA direction in
6371 * mid-flight. Not allowed, according to the PIIX3 specs. */
6372 Assert(!(pCtl->BmDma.u8Status & BM_STATUS_DMAING) || !((val ^ pCtl->BmDma.u8Cmd) & 0x04));
6373 uint8_t uOldBmDmaStatus = pCtl->BmDma.u8Status;
6374 pCtl->BmDma.u8Status |= BM_STATUS_DMAING;
6375 pCtl->BmDma.u8Cmd = val & (BM_CMD_START | BM_CMD_WRITE);
6376
6377 /* Do not continue DMA transfers while the RESET line is asserted. */
6378 if (pCtl->fReset)
6379 {
6380 Log2(("%s: Ctl#%d: suppressed continuing DMA transfer as RESET is active\n", __FUNCTION__, pCtl->iCtl));
6381 return;
6382 }
6383
6384 /* Do not start DMA transfers if there's a PIO transfer going on,
6385 * or if there is already a transfer started on this controller. */
6386 if ( !pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].fDMA
6387 || (uOldBmDmaStatus & BM_STATUS_DMAING))
6388 return;
6389
6390 if (pCtl->aIfs[pCtl->iAIOIf & ATA_SELECTED_IF_MASK].uATARegStatus & ATA_STAT_DRQ)
6391 {
6392 Log2(("%s: Ctl#%d: message to async I/O thread, continuing DMA transfer\n", __FUNCTION__, pCtl->iCtl));
6393 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataDMARequest);
6394 }
6395#else /* !IN_RING3 */
6396 AssertMsgFailed(("DMA START handling is too complicated for RC\n"));
6397#endif /* IN_RING3 */
6398 }
6399}
6400
6401static uint32_t ataBMDMAStatusReadB(PATACONTROLLER pCtl, uint32_t addr)
6402{
6403 uint32_t val = pCtl->BmDma.u8Status;
6404 RT_NOREF(addr);
6405 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6406 return val;
6407}
6408
6409static void ataBMDMAStatusWriteB(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6410{
6411 RT_NOREF(addr);
6412 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6413 pCtl->BmDma.u8Status = (val & (BM_STATUS_D0DMA | BM_STATUS_D1DMA))
6414 | (pCtl->BmDma.u8Status & BM_STATUS_DMAING)
6415 | (pCtl->BmDma.u8Status & ~val & (BM_STATUS_ERROR | BM_STATUS_INT));
6416}
6417
6418static uint32_t ataBMDMAAddrReadL(PATACONTROLLER pCtl, uint32_t addr)
6419{
6420 uint32_t val = (uint32_t)pCtl->BmDma.GCPhysAddr;
6421 RT_NOREF(addr);
6422 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6423 return val;
6424}
6425
6426static void ataBMDMAAddrWriteL(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6427{
6428 RT_NOREF(addr);
6429 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6430 pCtl->BmDma.GCPhysAddr = val & ~3;
6431}
6432
6433static void ataBMDMAAddrWriteLowWord(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6434{
6435 RT_NOREF(addr);
6436 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6437 pCtl->BmDma.GCPhysAddr = (pCtl->BmDma.GCPhysAddr & 0xFFFF0000) | RT_LOWORD(val & ~3);
6438
6439}
6440
6441static void ataBMDMAAddrWriteHighWord(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6442{
6443 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6444 RT_NOREF(addr);
6445 pCtl->BmDma.GCPhysAddr = (RT_LOWORD(val) << 16) | RT_LOWORD(pCtl->BmDma.GCPhysAddr);
6446}
6447
6448/** Helper for ataBMDMAIOPortRead and ataBMDMAIOPortWrite. */
6449#define VAL(port, size) ( ((port) & BM_DMA_CTL_IOPORTS_MASK) | ((size) << BM_DMA_CTL_IOPORTS_SHIFT) )
6450
6451/**
6452 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6453 * Port I/O Handler for bus-master DMA IN operations - both controllers.}
6454 */
6455static DECLCALLBACK(VBOXSTRICTRC)
6456ataBMDMAIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6457{
6458 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6459 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (offPort >> BM_DMA_CTL_IOPORTS_SHIFT));
6460 RT_NOREF(pvUser);
6461
6462 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
6463 if (rc == VINF_SUCCESS)
6464 {
6465 switch (VAL(offPort, cb))
6466 {
6467 case VAL(0, 1): *pu32 = ataBMDMACmdReadB(pCtl, offPort); break;
6468 case VAL(0, 2): *pu32 = ataBMDMACmdReadB(pCtl, offPort); break;
6469 case VAL(2, 1): *pu32 = ataBMDMAStatusReadB(pCtl, offPort); break;
6470 case VAL(2, 2): *pu32 = ataBMDMAStatusReadB(pCtl, offPort); break;
6471 case VAL(4, 4): *pu32 = ataBMDMAAddrReadL(pCtl, offPort); break;
6472 case VAL(0, 4):
6473 /* The SCO OpenServer tries to read 4 bytes starting from offset 0. */
6474 *pu32 = ataBMDMACmdReadB(pCtl, offPort) | (ataBMDMAStatusReadB(pCtl, offPort) << 16);
6475 break;
6476 default:
6477 ASSERT_GUEST_MSG_FAILED(("Unsupported read from port %x size=%d\n", offPort, cb));
6478 rc = VERR_IOM_IOPORT_UNUSED;
6479 break;
6480 }
6481 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6482 }
6483 return rc;
6484}
6485
6486/**
6487 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6488 * Port I/O Handler for bus-master DMA OUT operations - both controllers.}
6489 */
6490static DECLCALLBACK(VBOXSTRICTRC)
6491ataBMDMAIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6492{
6493 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6494 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (offPort >> BM_DMA_CTL_IOPORTS_SHIFT));
6495 RT_NOREF(pvUser);
6496
6497 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
6498 if (rc == VINF_SUCCESS)
6499 {
6500 switch (VAL(offPort, cb))
6501 {
6502 case VAL(0, 1):
6503#ifdef IN_RC
6504 if (u32 & BM_CMD_START)
6505 {
6506 rc = VINF_IOM_R3_IOPORT_WRITE;
6507 break;
6508 }
6509#endif
6510 ataBMDMACmdWriteB(pDevIns, pCtl, offPort, u32);
6511 break;
6512 case VAL(2, 1): ataBMDMAStatusWriteB(pCtl, offPort, u32); break;
6513 case VAL(4, 4): ataBMDMAAddrWriteL(pCtl, offPort, u32); break;
6514 case VAL(4, 2): ataBMDMAAddrWriteLowWord(pCtl, offPort, u32); break;
6515 case VAL(6, 2): ataBMDMAAddrWriteHighWord(pCtl, offPort, u32); break;
6516 default:
6517 ASSERT_GUEST_MSG_FAILED(("Unsupported write to port %x size=%d val=%x\n", offPort, cb, u32));
6518 break;
6519 }
6520 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6521 }
6522 return rc;
6523}
6524
6525#undef VAL
6526
6527#ifdef IN_RING3
6528
6529/* -=-=-=-=-=- ATASTATE::IBase -=-=-=-=-=- */
6530
6531/**
6532 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
6533 */
6534static DECLCALLBACK(void *) ataR3Status_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
6535{
6536 PATASTATER3 pThisCC = RT_FROM_MEMBER(pInterface, ATASTATER3, IBase);
6537 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase);
6538 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThisCC->ILeds);
6539 return NULL;
6540}
6541
6542
6543/* -=-=-=-=-=- ATASTATE::ILeds -=-=-=-=-=- */
6544
6545/**
6546 * Gets the pointer to the status LED of a unit.
6547 *
6548 * @returns VBox status code.
6549 * @param pInterface Pointer to the interface structure containing the called function pointer.
6550 * @param iLUN The unit which status LED we desire.
6551 * @param ppLed Where to store the LED pointer.
6552 */
6553static DECLCALLBACK(int) ataR3Status_QueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
6554{
6555 if (iLUN < 4)
6556 {
6557 PATASTATER3 pThisCC = RT_FROM_MEMBER(pInterface, ATASTATER3, ILeds);
6558 PATASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PATASTATE);
6559 switch (iLUN)
6560 {
6561 case 0: *ppLed = &pThis->aCts[0].aIfs[0].Led; break;
6562 case 1: *ppLed = &pThis->aCts[0].aIfs[1].Led; break;
6563 case 2: *ppLed = &pThis->aCts[1].aIfs[0].Led; break;
6564 case 3: *ppLed = &pThis->aCts[1].aIfs[1].Led; break;
6565 }
6566 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
6567 return VINF_SUCCESS;
6568 }
6569 return VERR_PDM_LUN_NOT_FOUND;
6570}
6571
6572
6573/* -=-=-=-=-=- ATADEVSTATE::IBase -=-=-=-=-=- */
6574
6575/**
6576 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
6577 */
6578static DECLCALLBACK(void *) ataR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
6579{
6580 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IBase);
6581 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pIfR3->IBase);
6582 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pIfR3->IPort);
6583 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pIfR3->IMountNotify);
6584 return NULL;
6585}
6586
6587
6588/* -=-=-=-=-=- ATADEVSTATE::IPort -=-=-=-=-=- */
6589
6590/**
6591 * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation}
6592 */
6593static DECLCALLBACK(int) ataR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
6594 uint32_t *piInstance, uint32_t *piLUN)
6595{
6596 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IPort);
6597 PPDMDEVINS pDevIns = pIfR3->pDevIns;
6598
6599 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
6600 AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
6601 AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
6602
6603 *ppcszController = pDevIns->pReg->szName;
6604 *piInstance = pDevIns->iInstance;
6605 *piLUN = pIfR3->iLUN;
6606
6607 return VINF_SUCCESS;
6608}
6609
6610#endif /* IN_RING3 */
6611
6612/* -=-=-=-=-=- Wrappers -=-=-=-=-=- */
6613
6614
6615/**
6616 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6617 * Port I/O Handler for OUT operations on unpopulated IDE channels.}
6618 * @note offPort is an absolute port number!
6619 */
6620static DECLCALLBACK(VBOXSTRICTRC)
6621ataIOPortWriteEmptyBus(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6622{
6623 RT_NOREF(pDevIns, pvUser, offPort, u32, cb);
6624
6625#ifdef VBOX_STRICT
6626 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6627 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6628 Assert((uintptr_t)pvUser < 2);
6629 Assert(!pCtl->aIfs[0].fPresent && !pCtl->aIfs[1].fPresent);
6630#endif
6631
6632 /* This is simply a black hole, writes on unpopulated IDE channels elicit no response. */
6633 LogFunc(("Empty bus: Ignoring write to port %x val=%x size=%d\n", offPort, u32, cb));
6634 return VINF_SUCCESS;
6635}
6636
6637
6638/**
6639 * @callback_method_impl{FNIOMIOPORTNEWIN,
6640 * Port I/O Handler for IN operations on unpopulated IDE channels.}
6641 * @note offPort is an absolute port number!
6642 */
6643static DECLCALLBACK(VBOXSTRICTRC)
6644ataIOPortReadEmptyBus(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6645{
6646 RT_NOREF(pDevIns, offPort, pvUser);
6647
6648#ifdef VBOX_STRICT
6649 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6650 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6651 Assert((uintptr_t)pvUser < 2);
6652 Assert(cb <= 4);
6653 Assert(!pCtl->aIfs[0].fPresent && !pCtl->aIfs[1].fPresent);
6654#endif
6655
6656 /*
6657 * Reads on unpopulated IDE channels behave in a unique way. Newer ATA specifications
6658 * mandate that the host must have a pull-down resistor on signal DD7. As a consequence,
6659 * bit 7 is always read as zero. This greatly aids in ATA device detection because
6660 * the empty bus does not look to the host like a permanently busy drive, and no long
6661 * timeouts (on the order of 30 seconds) are needed.
6662 *
6663 * The response is entirely static and does not require any locking or other fancy
6664 * stuff. Breaking it out simplifies the I/O handling for non-empty IDE channels which
6665 * is quite complicated enough already.
6666 */
6667 *pu32 = ATA_EMPTY_BUS_DATA_32 >> ((4 - cb) * 8);
6668 LogFunc(("Empty bus: port %x val=%x size=%d\n", offPort, *pu32, cb));
6669 return VINF_SUCCESS;
6670}
6671
6672
6673/**
6674 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6675 * Port I/O Handler for primary port range OUT operations.}
6676 * @note offPort is an absolute port number!
6677 */
6678static DECLCALLBACK(VBOXSTRICTRC)
6679ataIOPortWrite1Other(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6680{
6681 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6682 uintptr_t iCtl = (uintptr_t)pvUser % RT_ELEMENTS(pThis->aCts);
6683 PATACONTROLLER pCtl = &pThis->aCts[iCtl];
6684
6685 Assert((uintptr_t)pvUser < 2);
6686
6687 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
6688 if (rc == VINF_SUCCESS)
6689 {
6690 /* Writes to the other command block ports should be 8-bit only. If they
6691 * are not, the high bits are simply discarded. Undocumented, but observed
6692 * on a real PIIX4 system.
6693 */
6694 if (cb > 1)
6695 Log(("ataIOPortWrite1: suspect write to port %x val=%x size=%d\n", offPort, u32, cb));
6696
6697 rc = ataIOPortWriteU8(pDevIns, pCtl, offPort, u32, iCtl);
6698
6699 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6700 }
6701 return rc;
6702}
6703
6704
6705/**
6706 * @callback_method_impl{FNIOMIOPORTNEWIN,
6707 * Port I/O Handler for primary port range IN operations.}
6708 * @note offPort is an absolute port number!
6709 */
6710static DECLCALLBACK(VBOXSTRICTRC)
6711ataIOPortRead1Other(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6712{
6713 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6714 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6715
6716 Assert((uintptr_t)pvUser < 2);
6717
6718 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
6719 if (rc == VINF_SUCCESS)
6720 {
6721 /* Reads from the other command block registers should be 8-bit only.
6722 * If they are not, the low byte is propagated to the high bits.
6723 * Undocumented, but observed on a real PIIX4 system.
6724 */
6725 rc = ataIOPortReadU8(pDevIns, pCtl, offPort, pu32);
6726 if (cb > 1)
6727 {
6728 uint32_t pad;
6729
6730 /* Replicate the 8-bit result into the upper three bytes. */
6731 pad = *pu32 & 0xff;
6732 pad = pad | (pad << 8);
6733 pad = pad | (pad << 16);
6734 *pu32 = pad;
6735 Log(("ataIOPortRead1: suspect read from port %x size=%d\n", offPort, cb));
6736 }
6737 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6738 }
6739 return rc;
6740}
6741
6742
6743/**
6744 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6745 * Port I/O Handler for secondary port range OUT operations.}
6746 * @note offPort is an absolute port number!
6747 */
6748static DECLCALLBACK(VBOXSTRICTRC)
6749ataIOPortWrite2(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6750{
6751 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6752 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6753 int rc;
6754
6755 Assert((uintptr_t)pvUser < 2);
6756
6757 if (cb == 1)
6758 {
6759 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
6760 if (rc == VINF_SUCCESS)
6761 {
6762 rc = ataControlWrite(pDevIns, pCtl, u32, offPort);
6763 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6764 }
6765 }
6766 else
6767 {
6768 Log(("ataIOPortWrite2: ignoring write to port %x+%x size=%d!\n", offPort, pCtl->IOPortBase2, cb));
6769 rc = VINF_SUCCESS;
6770 }
6771 return rc;
6772}
6773
6774
6775/**
6776 * @callback_method_impl{FNIOMIOPORTNEWIN,
6777 * Port I/O Handler for secondary port range IN operations.}
6778 * @note offPort is an absolute port number!
6779 */
6780static DECLCALLBACK(VBOXSTRICTRC)
6781ataIOPortRead2(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6782{
6783 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6784 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6785 int rc;
6786
6787 Assert((uintptr_t)pvUser < 2);
6788
6789 if (cb == 1)
6790 {
6791 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
6792 if (rc == VINF_SUCCESS)
6793 {
6794 *pu32 = ataStatusRead(pCtl, offPort);
6795 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6796 }
6797 }
6798 else
6799 {
6800 Log(("ataIOPortRead2: ignoring read from port %x+%x size=%d!\n", offPort, pCtl->IOPortBase2, cb));
6801 rc = VERR_IOM_IOPORT_UNUSED;
6802 }
6803 return rc;
6804}
6805
6806#ifdef IN_RING3
6807
6808/**
6809 * Detach notification.
6810 *
6811 * The DVD drive has been unplugged.
6812 *
6813 * @param pDevIns The device instance.
6814 * @param iLUN The logical unit which is being detached.
6815 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
6816 */
6817static DECLCALLBACK(void) ataR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
6818{
6819 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6820 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
6821 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
6822 ("PIIX3IDE: Device does not support hotplugging\n")); RT_NOREF(fFlags);
6823
6824 /*
6825 * Locate the controller and stuff.
6826 */
6827 unsigned iController = iLUN / RT_ELEMENTS(pThis->aCts[0].aIfs);
6828 AssertReleaseMsg(iController < RT_ELEMENTS(pThis->aCts), ("iController=%d iLUN=%d\n", iController, iLUN));
6829 PATACONTROLLER pCtl = &pThis->aCts[iController];
6830 PATACONTROLLERR3 pCtlR3 = &pThisCC->aCts[iController];
6831
6832 unsigned iInterface = iLUN % RT_ELEMENTS(pThis->aCts[0].aIfs);
6833 PATADEVSTATE pIf = &pCtl->aIfs[iInterface];
6834 PATADEVSTATER3 pIfR3 = &pCtlR3->aIfs[iInterface];
6835
6836 /*
6837 * Zero some important members.
6838 */
6839 pIfR3->pDrvBase = NULL;
6840 pIfR3->pDrvMedia = NULL;
6841 pIfR3->pDrvMount = NULL;
6842 pIf->fPresent = false;
6843
6844 /*
6845 * In case there was a medium inserted.
6846 */
6847 ataR3MediumRemoved(pIf);
6848}
6849
6850
6851/**
6852 * Configure a LUN.
6853 *
6854 * @returns VBox status code.
6855 * @param pIf The ATA unit state, shared bits.
6856 * @param pIfR3 The ATA unit state, ring-3 bits.
6857 */
6858static int ataR3ConfigLun(PATADEVSTATE pIf, PATADEVSTATER3 pIfR3)
6859{
6860 /*
6861 * Query Block, Bios and Mount interfaces.
6862 */
6863 pIfR3->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pIfR3->pDrvBase, PDMIMEDIA);
6864 if (!pIfR3->pDrvMedia)
6865 {
6866 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pIf->iLUN));
6867 return VERR_PDM_MISSING_INTERFACE;
6868 }
6869
6870 pIfR3->pDrvMount = PDMIBASE_QUERY_INTERFACE(pIfR3->pDrvBase, PDMIMOUNT);
6871 pIf->fPresent = true;
6872
6873 /*
6874 * Validate type.
6875 */
6876 PDMMEDIATYPE enmType = pIfR3->pDrvMedia->pfnGetType(pIfR3->pDrvMedia);
6877 if ( enmType != PDMMEDIATYPE_CDROM
6878 && enmType != PDMMEDIATYPE_DVD
6879 && enmType != PDMMEDIATYPE_HARD_DISK)
6880 {
6881 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd-rom. enmType=%d\n", pIf->iLUN, enmType));
6882 return VERR_PDM_UNSUPPORTED_BLOCK_TYPE;
6883 }
6884 if ( ( enmType == PDMMEDIATYPE_DVD
6885 || enmType == PDMMEDIATYPE_CDROM)
6886 && !pIfR3->pDrvMount)
6887 {
6888 AssertMsgFailed(("Internal error: cdrom without a mountable interface, WTF???!\n"));
6889 return VERR_INTERNAL_ERROR;
6890 }
6891 pIf->fATAPI = enmType == PDMMEDIATYPE_DVD || enmType == PDMMEDIATYPE_CDROM;
6892 pIf->fATAPIPassthrough = pIf->fATAPI && pIfR3->pDrvMedia->pfnSendCmd != NULL;
6893
6894 /*
6895 * Allocate I/O buffer.
6896 */
6897 if (pIf->fATAPI)
6898 pIf->cbSector = 2048; /* Not required for ATAPI, one medium can have multiple sector sizes. */
6899 else
6900 {
6901 pIf->cbSector = pIfR3->pDrvMedia->pfnGetSectorSize(pIfR3->pDrvMedia);
6902 AssertLogRelMsgReturn(pIf->cbSector > 0 && pIf->cbSector <= ATA_MAX_SECTOR_SIZE,
6903 ("Unsupported sector size on LUN#%u: %#x (%d)\n", pIf->iLUN, pIf->cbSector, pIf->cbSector),
6904 VERR_OUT_OF_RANGE);
6905 }
6906
6907 if (pIf->cbIOBuffer)
6908 {
6909 /* Buffer is (probably) already allocated. Validate the fields,
6910 * because memory corruption can also overwrite pIf->cbIOBuffer. */
6911 if (pIf->fATAPI)
6912 AssertLogRelReturn(pIf->cbIOBuffer == _128K, VERR_BUFFER_OVERFLOW);
6913 else
6914 AssertLogRelReturn(pIf->cbIOBuffer == ATA_MAX_MULT_SECTORS * pIf->cbSector, VERR_BUFFER_OVERFLOW);
6915 }
6916 else
6917 {
6918 if (pIf->fATAPI)
6919 pIf->cbIOBuffer = _128K;
6920 else
6921 pIf->cbIOBuffer = ATA_MAX_MULT_SECTORS * pIf->cbSector;
6922 }
6923 AssertCompile(_128K <= ATA_MAX_IO_BUFFER_SIZE);
6924 AssertCompileSize(pIf->abIOBuffer, ATA_MAX_IO_BUFFER_SIZE);
6925 AssertLogRelMsgReturn(pIf->cbIOBuffer <= ATA_MAX_IO_BUFFER_SIZE,
6926 ("LUN#%u: cbIOBuffer=%#x (%u)\n", pIf->iLUN, pIf->cbIOBuffer, pIf->cbIOBuffer),
6927 VERR_BUFFER_OVERFLOW);
6928
6929 /*
6930 * Init geometry (only for non-CD/DVD media).
6931 */
6932 int rc = VINF_SUCCESS;
6933 uint32_t cRegions = pIfR3->pDrvMedia->pfnGetRegionCount(pIfR3->pDrvMedia);
6934 pIf->cTotalSectors = 0;
6935 for (uint32_t i = 0; i < cRegions; i++)
6936 {
6937 uint64_t cBlocks = 0;
6938 rc = pIfR3->pDrvMedia->pfnQueryRegionProperties(pIfR3->pDrvMedia, i, NULL, &cBlocks, NULL, NULL);
6939 AssertRC(rc);
6940 pIf->cTotalSectors += cBlocks;
6941 }
6942
6943 if (pIf->fATAPI)
6944 {
6945 pIf->PCHSGeometry.cCylinders = 0; /* dummy */
6946 pIf->PCHSGeometry.cHeads = 0; /* dummy */
6947 pIf->PCHSGeometry.cSectors = 0; /* dummy */
6948 LogRel(("PIIX3 ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n",
6949 pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled")));
6950 }
6951 else
6952 {
6953 rc = pIfR3->pDrvMedia->pfnBiosGetPCHSGeometry(pIfR3->pDrvMedia, &pIf->PCHSGeometry);
6954 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED)
6955 {
6956 pIf->PCHSGeometry.cCylinders = 0;
6957 pIf->PCHSGeometry.cHeads = 16; /*??*/
6958 pIf->PCHSGeometry.cSectors = 63; /*??*/
6959 }
6960 else if (rc == VERR_PDM_GEOMETRY_NOT_SET)
6961 {
6962 pIf->PCHSGeometry.cCylinders = 0; /* autodetect marker */
6963 rc = VINF_SUCCESS;
6964 }
6965 AssertRC(rc);
6966
6967 if ( pIf->PCHSGeometry.cCylinders == 0
6968 || pIf->PCHSGeometry.cHeads == 0
6969 || pIf->PCHSGeometry.cSectors == 0
6970 )
6971 {
6972 uint64_t cCylinders = pIf->cTotalSectors / (16 * 63);
6973 pIf->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
6974 pIf->PCHSGeometry.cHeads = 16;
6975 pIf->PCHSGeometry.cSectors = 63;
6976 /* Set the disk geometry information. Ignore errors. */
6977 pIfR3->pDrvMedia->pfnBiosSetPCHSGeometry(pIfR3->pDrvMedia, &pIf->PCHSGeometry);
6978 rc = VINF_SUCCESS;
6979 }
6980 LogRel(("PIIX3 ATA: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n",
6981 pIf->iLUN, pIf->PCHSGeometry.cCylinders, pIf->PCHSGeometry.cHeads, pIf->PCHSGeometry.cSectors,
6982 pIf->cTotalSectors));
6983
6984 if (pIfR3->pDrvMedia->pfnDiscard)
6985 LogRel(("PIIX3 ATA: LUN#%d: TRIM enabled\n", pIf->iLUN));
6986 }
6987 /* Initialize the translated geometry. */
6988 pIf->XCHSGeometry = pIf->PCHSGeometry;
6989
6990 /*
6991 * Check if SMP system to adjust the agressiveness of the busy yield hack (@bugref{1960}).
6992 *
6993 * The hack is an ancient (2006?) one for dealing with UNI CPU systems where EMT
6994 * would potentially monopolise the CPU and starve I/O threads. It causes the EMT to
6995 * yield it's timeslice if the guest polls the status register during I/O. On modern
6996 * multicore and multithreaded systems, yielding EMT too often may have adverse
6997 * effects (slow grub) so we aim at avoiding repeating the yield there too often.
6998 */
6999 RTCPUID cCpus = RTMpGetOnlineCount();
7000 if (cCpus <= 1)
7001 {
7002 pIf->cBusyStatusHackR3Rate = 1;
7003 pIf->cBusyStatusHackRZRate = 7;
7004 }
7005 else if (cCpus <= 2)
7006 {
7007 pIf->cBusyStatusHackR3Rate = 3;
7008 pIf->cBusyStatusHackRZRate = 15;
7009 }
7010 else if (cCpus <= 4)
7011 {
7012 pIf->cBusyStatusHackR3Rate = 15;
7013 pIf->cBusyStatusHackRZRate = 31;
7014 }
7015 else
7016 {
7017 pIf->cBusyStatusHackR3Rate = 127;
7018 pIf->cBusyStatusHackRZRate = 127;
7019 }
7020
7021 return rc;
7022}
7023
7024
7025/**
7026 * Attach command.
7027 *
7028 * This is called when we change block driver for the DVD drive.
7029 *
7030 * @returns VBox status code.
7031 * @param pDevIns The device instance.
7032 * @param iLUN The logical unit which is being detached.
7033 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
7034 */
7035static DECLCALLBACK(int) ataR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
7036{
7037 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7038 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7039
7040 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
7041 ("PIIX3IDE: Device does not support hotplugging\n"),
7042 VERR_INVALID_PARAMETER);
7043
7044 /*
7045 * Locate the controller and stuff.
7046 */
7047 unsigned const iController = iLUN / RT_ELEMENTS(pThis->aCts[0].aIfs);
7048 AssertReleaseMsg(iController < RT_ELEMENTS(pThis->aCts), ("iController=%d iLUN=%d\n", iController, iLUN));
7049 PATACONTROLLER pCtl = &pThis->aCts[iController];
7050 PATACONTROLLERR3 pCtlR3 = &pThisCC->aCts[iController];
7051
7052 unsigned const iInterface = iLUN % RT_ELEMENTS(pThis->aCts[0].aIfs);
7053 PATADEVSTATE pIf = &pCtl->aIfs[iInterface];
7054 PATADEVSTATER3 pIfR3 = &pCtlR3->aIfs[iInterface];
7055
7056 /* the usual paranoia */
7057 AssertRelease(!pIfR3->pDrvBase);
7058 AssertRelease(!pIfR3->pDrvMedia);
7059 Assert(pIf->iLUN == iLUN);
7060
7061 /*
7062 * Try attach the block device and get the interfaces,
7063 * required as well as optional.
7064 */
7065 int rc = PDMDevHlpDriverAttach(pDevIns, pIf->iLUN, &pIfR3->IBase, &pIfR3->pDrvBase, NULL);
7066 if (RT_SUCCESS(rc))
7067 {
7068 rc = ataR3ConfigLun(pIf, pIfR3);
7069 /*
7070 * In case there is a medium inserted.
7071 */
7072 ataR3MediumInserted(pIf);
7073 ataR3MediumTypeSet(pIf, ATA_MEDIA_TYPE_UNKNOWN);
7074 }
7075 else
7076 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", pIf->iLUN, rc));
7077
7078 if (RT_FAILURE(rc))
7079 {
7080 pIfR3->pDrvBase = NULL;
7081 pIfR3->pDrvMedia = NULL;
7082 pIfR3->pDrvMount = NULL;
7083 pIf->fPresent = false;
7084 }
7085 return rc;
7086}
7087
7088
7089/**
7090 * Resume notification.
7091 *
7092 * @returns VBox status code.
7093 * @param pDevIns The device instance data.
7094 */
7095static DECLCALLBACK(void) ataR3Resume(PPDMDEVINS pDevIns)
7096{
7097 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7098 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7099
7100 Log(("%s:\n", __FUNCTION__));
7101 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7102 {
7103 if (pThis->aCts[i].fRedo && pThis->aCts[i].fRedoIdle)
7104 {
7105 int rc = RTSemEventSignal(pThisCC->aCts[i].hSuspendIOSem);
7106 AssertRC(rc);
7107 }
7108 }
7109 return;
7110}
7111
7112
7113/**
7114 * Checks if all (both) the async I/O threads have quiesced.
7115 *
7116 * @returns true on success.
7117 * @returns false when one or more threads is still processing.
7118 * @param pDevIns Pointer to the PDM device instance.
7119 */
7120static bool ataR3AllAsyncIOIsIdle(PPDMDEVINS pDevIns)
7121{
7122 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7123 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7124
7125 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7126 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7127 {
7128 bool fRc = ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/);
7129 if (!fRc)
7130 {
7131 /* Make it signal PDM & itself when its done */
7132 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].AsyncIORequestLock, VERR_IGNORED);
7133 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].AsyncIORequestLock, rcLock);
7134
7135 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, true);
7136
7137 PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].AsyncIORequestLock);
7138
7139 fRc = ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/);
7140 if (!fRc)
7141 {
7142#if 0 /** @todo Need to do some time tracking here... */
7143 LogRel(("PIIX3 ATA: Ctl#%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",
7144 i, pThis->aCts[i].iSelectedIf, pThis->aCts[i].iAIOIf,
7145 pThis->aCts[i].aIfs[0].uATARegCommand, pThis->aCts[i].aIfs[1].uATARegCommand));
7146#endif
7147 return false;
7148 }
7149 }
7150 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, false);
7151 }
7152 return true;
7153}
7154
7155/**
7156 * Prepare state save and load operation.
7157 *
7158 * @returns VBox status code.
7159 * @param pDevIns Device instance of the device which registered the data unit.
7160 * @param pSSM SSM operation handle.
7161 */
7162static DECLCALLBACK(int) ataR3SaveLoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
7163{
7164 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7165 RT_NOREF(pSSM);
7166
7167 /* sanity - the suspend notification will wait on the async stuff. */
7168 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7169 AssertLogRelMsgReturn(ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/),
7170 ("i=%u\n", i),
7171 VERR_SSM_IDE_ASYNC_TIMEOUT);
7172 return VINF_SUCCESS;
7173}
7174
7175/**
7176 * @copydoc FNSSMDEVLIVEEXEC
7177 */
7178static DECLCALLBACK(int) ataR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
7179{
7180 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7181 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7182 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7183 RT_NOREF(uPass);
7184
7185 pHlp->pfnSSMPutU8(pSSM, (uint8_t)pThis->enmChipset);
7186 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7187 {
7188 pHlp->pfnSSMPutBool(pSSM, true); /* For controller enabled / disabled. */
7189 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7190 {
7191 pHlp->pfnSSMPutBool(pSSM, pThisCC->aCts[i].aIfs[j].pDrvBase != NULL);
7192 pHlp->pfnSSMPutStrZ(pSSM, pThis->aCts[i].aIfs[j].szSerialNumber);
7193 pHlp->pfnSSMPutStrZ(pSSM, pThis->aCts[i].aIfs[j].szFirmwareRevision);
7194 pHlp->pfnSSMPutStrZ(pSSM, pThis->aCts[i].aIfs[j].szModelNumber);
7195 }
7196 }
7197
7198 return VINF_SSM_DONT_CALL_AGAIN;
7199}
7200
7201/**
7202 * @copydoc FNSSMDEVSAVEEXEC
7203 */
7204static DECLCALLBACK(int) ataR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
7205{
7206 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7207 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7208
7209 ataR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
7210
7211 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7212 {
7213 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].iSelectedIf);
7214 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].iAIOIf);
7215 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].uAsyncIOState);
7216 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fChainedTransfer);
7217 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fReset);
7218 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fRedo);
7219 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fRedoIdle);
7220 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fRedoDMALastDesc);
7221 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].BmDma, sizeof(pThis->aCts[i].BmDma));
7222 pHlp->pfnSSMPutGCPhys32(pSSM, pThis->aCts[i].GCPhysFirstDMADesc);
7223 pHlp->pfnSSMPutGCPhys32(pSSM, pThis->aCts[i].GCPhysLastDMADesc);
7224 pHlp->pfnSSMPutGCPhys32(pSSM, pThis->aCts[i].GCPhysRedoDMABuffer);
7225 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].cbRedoDMABuffer);
7226
7227 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7228 {
7229 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fLBA48);
7230 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fATAPI);
7231 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fIrqPending);
7232 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].cMultSectors);
7233 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cCylinders);
7234 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cHeads);
7235 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cSectors);
7236 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cSectorsPerIRQ);
7237 pHlp->pfnSSMPutU64(pSSM, pThis->aCts[i].aIfs[j].cTotalSectors);
7238 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegFeature);
7239 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegFeatureHOB);
7240 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegError);
7241 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegNSector);
7242 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegNSectorHOB);
7243 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegSector);
7244 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegSectorHOB);
7245 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegLCyl);
7246 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegLCylHOB);
7247 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegHCyl);
7248 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegHCylHOB);
7249 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegSelect);
7250 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegStatus);
7251 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegCommand);
7252 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegDevCtl);
7253 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATATransferMode);
7254 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uTxDir);
7255 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].iBeginTransfer);
7256 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].iSourceSink);
7257 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fDMA);
7258 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fATAPITransfer);
7259 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbTotalTransfer);
7260 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbElementaryTransfer);
7261 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferCur);
7262 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferEnd);
7263 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferPIODataStart);
7264 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferPIODataEnd);
7265 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iATAPILBA);
7266 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbATAPISector);
7267 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].aIfs[j].abATAPICmd, sizeof(pThis->aCts[i].aIfs[j].abATAPICmd));
7268 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].aIfs[j].abATAPISense, sizeof(pThis->aCts[i].aIfs[j].abATAPISense));
7269 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].cNotifiedMediaChange);
7270 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].MediaEventStatus);
7271 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].aIfs[j].Led, sizeof(pThis->aCts[i].aIfs[j].Led));
7272 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbIOBuffer);
7273 if (pThis->aCts[i].aIfs[j].cbIOBuffer)
7274 pHlp->pfnSSMPutMem(pSSM, pThis->aCts[i].aIfs[j].abIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer);
7275 }
7276 }
7277
7278 return pHlp->pfnSSMPutU32(pSSM, UINT32_MAX); /* sanity/terminator */
7279}
7280
7281/**
7282 * Converts the LUN number into a message string.
7283 */
7284static const char *ataR3StringifyLun(unsigned iLun)
7285{
7286 switch (iLun)
7287 {
7288 case 0: return "primary master";
7289 case 1: return "primary slave";
7290 case 2: return "secondary master";
7291 case 3: return "secondary slave";
7292 default: AssertFailedReturn("unknown lun");
7293 }
7294}
7295
7296/**
7297 * FNSSMDEVLOADEXEC
7298 */
7299static DECLCALLBACK(int) ataR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
7300{
7301 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7302 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7303 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7304 int rc;
7305 uint32_t u32;
7306
7307 if ( uVersion != ATA_SAVED_STATE_VERSION
7308 && uVersion != ATA_SAVED_STATE_VERSION_VBOX_30
7309 && uVersion != ATA_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE
7310 && uVersion != ATA_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS
7311 && uVersion != ATA_SAVED_STATE_VERSION_WITH_BOOL_TYPE)
7312 {
7313 AssertMsgFailed(("uVersion=%d\n", uVersion));
7314 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
7315 }
7316
7317 /*
7318 * Verify the configuration.
7319 */
7320 if (uVersion > ATA_SAVED_STATE_VERSION_VBOX_30)
7321 {
7322 uint8_t u8Type;
7323 rc = pHlp->pfnSSMGetU8(pSSM, &u8Type);
7324 AssertRCReturn(rc, rc);
7325 if ((CHIPSET)u8Type != pThis->enmChipset)
7326 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch: enmChipset - saved=%u config=%u"), u8Type, pThis->enmChipset);
7327
7328 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7329 {
7330 bool fEnabled;
7331 rc = pHlp->pfnSSMGetBool(pSSM, &fEnabled);
7332 AssertRCReturn(rc, rc);
7333 if (!fEnabled)
7334 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Ctr#%u onfig mismatch: fEnabled != true"), i);
7335
7336 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7337 {
7338 ATADEVSTATE const *pIf = &pThis->aCts[i].aIfs[j];
7339 ATADEVSTATER3 const *pIfR3 = &pThisCC->aCts[i].aIfs[j];
7340
7341 bool fInUse;
7342 rc = pHlp->pfnSSMGetBool(pSSM, &fInUse);
7343 AssertRCReturn(rc, rc);
7344 if (fInUse != (pIfR3->pDrvBase != NULL))
7345 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS,
7346 N_("The %s VM is missing a %s device. Please make sure the source and target VMs have compatible storage configurations"),
7347 fInUse ? "target" : "source", ataR3StringifyLun(pIf->iLUN) );
7348
7349 char szSerialNumber[ATA_SERIAL_NUMBER_LENGTH+1];
7350 rc = pHlp->pfnSSMGetStrZ(pSSM, szSerialNumber, sizeof(szSerialNumber));
7351 AssertRCReturn(rc, rc);
7352 if (strcmp(szSerialNumber, pIf->szSerialNumber))
7353 LogRel(("PIIX3 ATA: LUN#%u config mismatch: Serial number - saved='%s' config='%s'\n",
7354 pIf->iLUN, szSerialNumber, pIf->szSerialNumber));
7355
7356 char szFirmwareRevision[ATA_FIRMWARE_REVISION_LENGTH+1];
7357 rc = pHlp->pfnSSMGetStrZ(pSSM, szFirmwareRevision, sizeof(szFirmwareRevision));
7358 AssertRCReturn(rc, rc);
7359 if (strcmp(szFirmwareRevision, pIf->szFirmwareRevision))
7360 LogRel(("PIIX3 ATA: LUN#%u config mismatch: Firmware revision - saved='%s' config='%s'\n",
7361 pIf->iLUN, szFirmwareRevision, pIf->szFirmwareRevision));
7362
7363 char szModelNumber[ATA_MODEL_NUMBER_LENGTH+1];
7364 rc = pHlp->pfnSSMGetStrZ(pSSM, szModelNumber, sizeof(szModelNumber));
7365 AssertRCReturn(rc, rc);
7366 if (strcmp(szModelNumber, pIf->szModelNumber))
7367 LogRel(("PIIX3 ATA: LUN#%u config mismatch: Model number - saved='%s' config='%s'\n",
7368 pIf->iLUN, szModelNumber, pIf->szModelNumber));
7369 }
7370 }
7371 }
7372 if (uPass != SSM_PASS_FINAL)
7373 return VINF_SUCCESS;
7374
7375 /*
7376 * Restore valid parts of the ATASTATE structure
7377 */
7378 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7379 {
7380 /* integrity check */
7381 if (!ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false))
7382 {
7383 AssertMsgFailed(("Async I/O for controller %d is active\n", i));
7384 return VERR_INTERNAL_ERROR_4;
7385 }
7386
7387 rc = pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].iSelectedIf);
7388 AssertRCReturn(rc, rc);
7389 AssertLogRelMsgStmt(pThis->aCts[i].iSelectedIf == (pThis->aCts[i].iSelectedIf & ATA_SELECTED_IF_MASK),
7390 ("iSelectedIf = %d\n", pThis->aCts[i].iSelectedIf),
7391 pThis->aCts[i].iSelectedIf &= ATA_SELECTED_IF_MASK);
7392 rc = pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].iAIOIf);
7393 AssertRCReturn(rc, rc);
7394 AssertLogRelMsgStmt(pThis->aCts[i].iAIOIf == (pThis->aCts[i].iAIOIf & ATA_SELECTED_IF_MASK),
7395 ("iAIOIf = %d\n", pThis->aCts[i].iAIOIf),
7396 pThis->aCts[i].iAIOIf &= ATA_SELECTED_IF_MASK);
7397 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].uAsyncIOState);
7398 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fChainedTransfer);
7399 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fReset);
7400 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fRedo);
7401 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fRedoIdle);
7402 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fRedoDMALastDesc);
7403 pHlp->pfnSSMGetMem(pSSM, &pThis->aCts[i].BmDma, sizeof(pThis->aCts[i].BmDma));
7404 pHlp->pfnSSMGetGCPhys32(pSSM, &pThis->aCts[i].GCPhysFirstDMADesc);
7405 pHlp->pfnSSMGetGCPhys32(pSSM, &pThis->aCts[i].GCPhysLastDMADesc);
7406 pHlp->pfnSSMGetGCPhys32(pSSM, &pThis->aCts[i].GCPhysRedoDMABuffer);
7407 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].cbRedoDMABuffer);
7408
7409 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7410 {
7411 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fLBA48);
7412 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fATAPI);
7413 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fIrqPending);
7414 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].cMultSectors);
7415 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cCylinders);
7416 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cHeads);
7417 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cSectors);
7418 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cSectorsPerIRQ);
7419 pHlp->pfnSSMGetU64(pSSM, &pThis->aCts[i].aIfs[j].cTotalSectors);
7420 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegFeature);
7421 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegFeatureHOB);
7422 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegError);
7423 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegNSector);
7424 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegNSectorHOB);
7425 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegSector);
7426 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegSectorHOB);
7427 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegLCyl);
7428 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegLCylHOB);
7429 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegHCyl);
7430 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegHCylHOB);
7431 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegSelect);
7432 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegStatus);
7433 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegCommand);
7434 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegDevCtl);
7435 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATATransferMode);
7436 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uTxDir);
7437 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].iBeginTransfer);
7438 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].iSourceSink);
7439 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fDMA);
7440 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fATAPITransfer);
7441 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cbTotalTransfer);
7442 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cbElementaryTransfer);
7443 /* NB: cbPIOTransferLimit could be saved/restored but it's sufficient
7444 * to re-calculate it here, with a tiny risk that it could be
7445 * unnecessarily low for the current transfer only. Could be changed
7446 * when changing the saved state in the future.
7447 */
7448 pThis->aCts[i].aIfs[j].cbPIOTransferLimit = (pThis->aCts[i].aIfs[j].uATARegHCyl << 8) | pThis->aCts[i].aIfs[j].uATARegLCyl;
7449 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferCur);
7450 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferEnd);
7451 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferPIODataStart);
7452 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferPIODataEnd);
7453 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iATAPILBA);
7454 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cbATAPISector);
7455 pHlp->pfnSSMGetMem(pSSM, &pThis->aCts[i].aIfs[j].abATAPICmd, sizeof(pThis->aCts[i].aIfs[j].abATAPICmd));
7456 if (uVersion > ATA_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE)
7457 pHlp->pfnSSMGetMem(pSSM, pThis->aCts[i].aIfs[j].abATAPISense, sizeof(pThis->aCts[i].aIfs[j].abATAPISense));
7458 else
7459 {
7460 uint8_t uATAPISenseKey, uATAPIASC;
7461 memset(pThis->aCts[i].aIfs[j].abATAPISense, '\0', sizeof(pThis->aCts[i].aIfs[j].abATAPISense));
7462 pThis->aCts[i].aIfs[j].abATAPISense[0] = 0x70 | (1 << 7);
7463 pThis->aCts[i].aIfs[j].abATAPISense[7] = 10;
7464 pHlp->pfnSSMGetU8(pSSM, &uATAPISenseKey);
7465 pHlp->pfnSSMGetU8(pSSM, &uATAPIASC);
7466 pThis->aCts[i].aIfs[j].abATAPISense[2] = uATAPISenseKey & 0x0f;
7467 pThis->aCts[i].aIfs[j].abATAPISense[12] = uATAPIASC;
7468 }
7469 /** @todo triple-check this hack after passthrough is working */
7470 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].cNotifiedMediaChange);
7471 if (uVersion > ATA_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
7472 pHlp->pfnSSMGetU32V(pSSM, &pThis->aCts[i].aIfs[j].MediaEventStatus);
7473 else
7474 pThis->aCts[i].aIfs[j].MediaEventStatus = ATA_EVENT_STATUS_UNCHANGED;
7475 pHlp->pfnSSMGetMem(pSSM, &pThis->aCts[i].aIfs[j].Led, sizeof(pThis->aCts[i].aIfs[j].Led));
7476
7477 uint32_t cbIOBuffer = 0;
7478 rc = pHlp->pfnSSMGetU32(pSSM, &cbIOBuffer);
7479 AssertRCReturn(rc, rc);
7480
7481 if (cbIOBuffer)
7482 {
7483 if (cbIOBuffer <= sizeof(pThis->aCts[i].aIfs[j].abIOBuffer))
7484 {
7485 if (pThis->aCts[i].aIfs[j].cbIOBuffer != cbIOBuffer)
7486 LogRel(("ATA: %u/%u: Restoring cbIOBuffer=%u; constructor set up %u!\n", i, j, cbIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer));
7487 pThis->aCts[i].aIfs[j].cbIOBuffer = cbIOBuffer;
7488 pHlp->pfnSSMGetMem(pSSM, pThis->aCts[i].aIfs[j].abIOBuffer, cbIOBuffer);
7489 }
7490 else
7491 {
7492 LogRel(("ATA: %u/%u: Restoring cbIOBuffer=%u, only prepared %u!\n", i, j, cbIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer));
7493 if (pHlp->pfnSSMHandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
7494 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS,
7495 N_("ATA: %u/%u: Restoring cbIOBuffer=%u, only prepared %u"),
7496 i, j, cbIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer);
7497
7498 /* skip the buffer if we're loading for the debugger / animator. */
7499 pHlp->pfnSSMSkip(pSSM, cbIOBuffer);
7500 }
7501 }
7502 else
7503 AssertLogRelMsgStmt(pThis->aCts[i].aIfs[j].cbIOBuffer == 0,
7504 ("ATA: %u/%u: cbIOBuffer=%u restoring zero!\n", i, j, pThis->aCts[i].aIfs[j].cbIOBuffer),
7505 pThis->aCts[i].aIfs[j].cbIOBuffer = 0);
7506 }
7507 }
7508 if (uVersion <= ATA_SAVED_STATE_VERSION_VBOX_30)
7509 PDMDEVHLP_SSM_GET_ENUM8_RET(pHlp, pSSM, pThis->enmChipset, CHIPSET);
7510
7511 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
7512 if (RT_FAILURE(rc))
7513 return rc;
7514 if (u32 != ~0U)
7515 {
7516 AssertMsgFailed(("u32=%#x expected ~0\n", u32));
7517 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
7518 return rc;
7519 }
7520
7521 return VINF_SUCCESS;
7522}
7523
7524
7525/**
7526 * Callback employed by ataSuspend and ataR3PowerOff.
7527 *
7528 * @returns true if we've quiesced, false if we're still working.
7529 * @param pDevIns The device instance.
7530 */
7531static DECLCALLBACK(bool) ataR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)
7532{
7533 return ataR3AllAsyncIOIsIdle(pDevIns);
7534}
7535
7536
7537/**
7538 * Common worker for ataSuspend and ataR3PowerOff.
7539 */
7540static void ataR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
7541{
7542 if (!ataR3AllAsyncIOIsIdle(pDevIns))
7543 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncSuspendOrPowerOffDone);
7544}
7545
7546
7547/**
7548 * Power Off notification.
7549 *
7550 * @returns VBox status code.
7551 * @param pDevIns The device instance data.
7552 */
7553static DECLCALLBACK(void) ataR3PowerOff(PPDMDEVINS pDevIns)
7554{
7555 Log(("%s:\n", __FUNCTION__));
7556 ataR3SuspendOrPowerOff(pDevIns);
7557}
7558
7559
7560/**
7561 * Suspend notification.
7562 *
7563 * @returns VBox status code.
7564 * @param pDevIns The device instance data.
7565 */
7566static DECLCALLBACK(void) ataR3Suspend(PPDMDEVINS pDevIns)
7567{
7568 Log(("%s:\n", __FUNCTION__));
7569 ataR3SuspendOrPowerOff(pDevIns);
7570}
7571
7572
7573/**
7574 * Callback employed by ataR3Reset.
7575 *
7576 * @returns true if we've quiesced, false if we're still working.
7577 * @param pDevIns The device instance.
7578 */
7579static DECLCALLBACK(bool) ataR3IsAsyncResetDone(PPDMDEVINS pDevIns)
7580{
7581 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7582
7583 if (!ataR3AllAsyncIOIsIdle(pDevIns))
7584 return false;
7585
7586 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7587 {
7588 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].lock, VERR_INTERNAL_ERROR);
7589 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].lock, rcLock);
7590
7591 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7592 ataR3ResetDevice(pDevIns, &pThis->aCts[i], &pThis->aCts[i].aIfs[j]);
7593
7594 PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].lock);
7595 }
7596 return true;
7597}
7598
7599
7600/**
7601 * Common reset worker for ataR3Reset and ataR3Construct.
7602 *
7603 * @returns VBox status code.
7604 * @param pDevIns The device instance data.
7605 * @param fConstruct Indicates who is calling.
7606 */
7607static int ataR3ResetCommon(PPDMDEVINS pDevIns, bool fConstruct)
7608{
7609 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7610 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7611
7612 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7613 {
7614 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].lock, VERR_INTERNAL_ERROR);
7615 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].lock, rcLock);
7616
7617 pThis->aCts[i].iSelectedIf = 0;
7618 pThis->aCts[i].iAIOIf = 0;
7619 pThis->aCts[i].BmDma.u8Cmd = 0;
7620 /* Report that both drives present on the bus are in DMA mode. This
7621 * pretends that there is a BIOS that has set it up. Normal reset
7622 * default is 0x00. */
7623 pThis->aCts[i].BmDma.u8Status = (pThisCC->aCts[i].aIfs[0].pDrvBase != NULL ? BM_STATUS_D0DMA : 0)
7624 | (pThisCC->aCts[i].aIfs[1].pDrvBase != NULL ? BM_STATUS_D1DMA : 0);
7625 pThis->aCts[i].BmDma.GCPhysAddr = 0;
7626
7627 pThis->aCts[i].fReset = true;
7628 pThis->aCts[i].fRedo = false;
7629 pThis->aCts[i].fRedoIdle = false;
7630 ataR3AsyncIOClearRequests(pDevIns, &pThis->aCts[i]);
7631 Log2(("%s: Ctl#%d: message to async I/O thread, reset controller\n", __FUNCTION__, i));
7632 ataHCAsyncIOPutRequest(pDevIns, &pThis->aCts[i], &g_ataResetARequest);
7633 ataHCAsyncIOPutRequest(pDevIns, &pThis->aCts[i], &g_ataResetCRequest);
7634
7635 PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].lock);
7636 }
7637
7638 int rcRet = VINF_SUCCESS;
7639 if (!fConstruct)
7640 {
7641 /*
7642 * Setup asynchronous notification completion if the requests haven't
7643 * completed yet.
7644 */
7645 if (!ataR3IsAsyncResetDone(pDevIns))
7646 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncResetDone);
7647 }
7648 else
7649 {
7650 /*
7651 * Wait for the requests for complete.
7652 *
7653 * Would be real nice if we could do it all from EMT(0) and not
7654 * involve the worker threads, then we could dispense with all the
7655 * waiting and semaphore ping-pong here...
7656 */
7657 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7658 {
7659 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7660 {
7661 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].AsyncIORequestLock, VERR_IGNORED);
7662 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].AsyncIORequestLock, rc);
7663
7664 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, true);
7665 rc = RTThreadUserReset(pThisCC->aCts[i].hAsyncIOThread);
7666 AssertRC(rc);
7667
7668 rc = PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].AsyncIORequestLock);
7669 AssertRC(rc);
7670
7671 if (!ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/))
7672 {
7673 rc = RTThreadUserWait(pThisCC->aCts[i].hAsyncIOThread, 30*1000 /*ms*/);
7674 if (RT_FAILURE(rc))
7675 rc = RTThreadUserWait(pThisCC->aCts[i].hAsyncIOThread, 1000 /*ms*/);
7676 if (RT_FAILURE(rc))
7677 {
7678 AssertRC(rc);
7679 rcRet = rc;
7680 }
7681 }
7682 }
7683 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, false);
7684 }
7685 if (RT_SUCCESS(rcRet))
7686 {
7687 rcRet = ataR3IsAsyncResetDone(pDevIns) ? VINF_SUCCESS : VERR_INTERNAL_ERROR;
7688 AssertRC(rcRet);
7689 }
7690 }
7691 return rcRet;
7692}
7693
7694/**
7695 * Reset notification.
7696 *
7697 * @param pDevIns The device instance data.
7698 */
7699static DECLCALLBACK(void) ataR3Reset(PPDMDEVINS pDevIns)
7700{
7701 ataR3ResetCommon(pDevIns, false /*fConstruct*/);
7702}
7703
7704/**
7705 * Destroy a driver instance.
7706 *
7707 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
7708 * resources can be freed correctly.
7709 *
7710 * @param pDevIns The device instance data.
7711 */
7712static DECLCALLBACK(int) ataR3Destruct(PPDMDEVINS pDevIns)
7713{
7714 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
7715 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7716 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7717 int rc;
7718
7719 Log(("ataR3Destruct\n"));
7720
7721 /*
7722 * Tell the async I/O threads to terminate.
7723 */
7724 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7725 {
7726 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7727 {
7728 ASMAtomicWriteU32(&pThisCC->aCts[i].fShutdown, true);
7729 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aCts[i].hAsyncIOSem);
7730 AssertRC(rc);
7731 rc = RTSemEventSignal(pThisCC->aCts[i].hSuspendIOSem);
7732 AssertRC(rc);
7733 }
7734 }
7735
7736 /*
7737 * Wait for the threads to terminate before destroying their resources.
7738 */
7739 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7740 {
7741 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7742 {
7743 rc = RTThreadWait(pThisCC->aCts[i].hAsyncIOThread, 30000 /* 30 s*/, NULL);
7744 if (RT_SUCCESS(rc))
7745 pThisCC->aCts[i].hAsyncIOThread = NIL_RTTHREAD;
7746 else
7747 LogRel(("PIIX3 ATA Dtor: Ctl#%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x rc=%Rrc\n",
7748 i, pThis->aCts[i].iSelectedIf, pThis->aCts[i].iAIOIf,
7749 pThis->aCts[i].aIfs[0].uATARegCommand, pThis->aCts[i].aIfs[1].uATARegCommand, rc));
7750 }
7751 }
7752
7753 /*
7754 * Free resources.
7755 */
7756 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7757 {
7758 if (PDMDevHlpCritSectIsInitialized(pDevIns, &pThis->aCts[i].AsyncIORequestLock))
7759 PDMDevHlpCritSectDelete(pDevIns, &pThis->aCts[i].AsyncIORequestLock);
7760 if (pThis->aCts[i].hAsyncIOSem != NIL_SUPSEMEVENT)
7761 {
7762 PDMDevHlpSUPSemEventClose(pDevIns, pThis->aCts[i].hAsyncIOSem);
7763 pThis->aCts[i].hAsyncIOSem = NIL_SUPSEMEVENT;
7764 }
7765 if (pThisCC->aCts[i].hSuspendIOSem != NIL_RTSEMEVENT)
7766 {
7767 RTSemEventDestroy(pThisCC->aCts[i].hSuspendIOSem);
7768 pThisCC->aCts[i].hSuspendIOSem = NIL_RTSEMEVENT;
7769 }
7770
7771 /* try one final time */
7772 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7773 {
7774 rc = RTThreadWait(pThisCC->aCts[i].hAsyncIOThread, 1 /*ms*/, NULL);
7775 if (RT_SUCCESS(rc))
7776 {
7777 pThisCC->aCts[i].hAsyncIOThread = NIL_RTTHREAD;
7778 LogRel(("PIIX3 ATA Dtor: Ctl#%u actually completed.\n", i));
7779 }
7780 }
7781
7782 for (uint32_t iIf = 0; iIf < RT_ELEMENTS(pThis->aCts[i].aIfs); iIf++)
7783 {
7784 if (pThisCC->aCts[i].aIfs[iIf].pTrackList)
7785 {
7786 ATAPIPassthroughTrackListDestroy(pThisCC->aCts[i].aIfs[iIf].pTrackList);
7787 pThisCC->aCts[i].aIfs[iIf].pTrackList = NULL;
7788 }
7789 }
7790 }
7791
7792 return VINF_SUCCESS;
7793}
7794
7795/**
7796 * Convert config value to DEVPCBIOSBOOT.
7797 *
7798 * @returns VBox status code.
7799 * @param pDevIns The device instance data.
7800 * @param pCfg Configuration handle.
7801 * @param penmChipset Where to store the chipset type.
7802 */
7803static int ataR3ControllerFromCfg(PPDMDEVINS pDevIns, PCFGMNODE pCfg, CHIPSET *penmChipset)
7804{
7805 char szType[20];
7806
7807 int rc = pDevIns->pHlpR3->pfnCFGMQueryStringDef(pCfg, "Type", &szType[0], sizeof(szType), "PIIX4");
7808 if (RT_FAILURE(rc))
7809 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
7810 N_("Configuration error: Querying \"Type\" as a string failed"));
7811 if (!strcmp(szType, "PIIX3"))
7812 *penmChipset = CHIPSET_PIIX3;
7813 else if (!strcmp(szType, "PIIX4"))
7814 *penmChipset = CHIPSET_PIIX4;
7815 else if (!strcmp(szType, "ICH6"))
7816 *penmChipset = CHIPSET_ICH6;
7817 else
7818 {
7819 PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
7820 N_("Configuration error: The \"Type\" value \"%s\" is unknown"),
7821 szType);
7822 rc = VERR_INTERNAL_ERROR;
7823 }
7824 return rc;
7825}
7826
7827/**
7828 * @interface_method_impl{PDMDEVREG,pfnConstruct}
7829 */
7830static DECLCALLBACK(int) ataR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
7831{
7832 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
7833 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7834 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
7835 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7836 PPDMIBASE pBase;
7837 int rc;
7838 uint32_t msDelayIRQ;
7839
7840 Assert(iInstance == 0);
7841
7842 /*
7843 * Initialize NIL handle values (for the destructor).
7844 */
7845 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7846 {
7847 pThis->aCts[i].iCtl = i;
7848 pThis->aCts[i].hAsyncIOSem = NIL_SUPSEMEVENT;
7849 pThis->aCts[i].hIoPorts1First = NIL_IOMIOPORTHANDLE;
7850 pThis->aCts[i].hIoPorts1Other = NIL_IOMIOPORTHANDLE;
7851 pThis->aCts[i].hIoPorts2 = NIL_IOMIOPORTHANDLE;
7852 pThis->aCts[i].hIoPortsEmpty1 = NIL_IOMIOPORTHANDLE;
7853 pThis->aCts[i].hIoPortsEmpty2 = NIL_IOMIOPORTHANDLE;
7854
7855 pThisCC->aCts[i].iCtl = i;
7856 pThisCC->aCts[i].hSuspendIOSem = NIL_RTSEMEVENT;
7857 pThisCC->aCts[i].hAsyncIOThread = NIL_RTTHREAD;
7858 }
7859
7860 /*
7861 * Validate and read configuration.
7862 */
7863 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQDelay|Type", "PrimaryMaster|PrimarySlave|SecondaryMaster|SecondarySlave");
7864
7865 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "IRQDelay", &msDelayIRQ, 0);
7866 if (RT_FAILURE(rc))
7867 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 configuration error: failed to read IRQDelay as integer"));
7868 Log(("%s: msDelayIRQ=%d\n", __FUNCTION__, msDelayIRQ));
7869 Assert(msDelayIRQ < 50);
7870
7871 CHIPSET enmChipset = CHIPSET_PIIX3;
7872 rc = ataR3ControllerFromCfg(pDevIns, pCfg, &enmChipset);
7873 if (RT_FAILURE(rc))
7874 return rc;
7875 pThis->enmChipset = enmChipset;
7876
7877 /*
7878 * Initialize data (most of it anyway).
7879 */
7880 /* Status LUN. */
7881 pThisCC->IBase.pfnQueryInterface = ataR3Status_QueryInterface;
7882 pThisCC->ILeds.pfnQueryStatusLed = ataR3Status_QueryStatusLed;
7883
7884 /* PCI configuration space. */
7885 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
7886 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
7887 PDMPciDevSetVendorId(pPciDev, 0x8086); /* Intel */
7888
7889 /*
7890 * When adding more IDE chipsets, don't forget to update pci_bios_init_device()
7891 * as it explicitly checks for PCI id for IDE controllers.
7892 */
7893 switch (enmChipset)
7894 {
7895 case CHIPSET_ICH6:
7896 PDMPciDevSetDeviceId(pPciDev, 0x269e); /* ICH6 IDE */
7897 /** @todo do we need it? Do we need anything else? */
7898 PDMPciDevSetByte(pPciDev, 0x48, 0x00); /* UDMACTL */
7899 PDMPciDevSetByte(pPciDev, 0x4A, 0x00); /* UDMATIM */
7900 PDMPciDevSetByte(pPciDev, 0x4B, 0x00);
7901 {
7902 /*
7903 * See www.intel.com/Assets/PDF/manual/298600.pdf p. 30
7904 * Report
7905 * WR_Ping-Pong_EN: must be set
7906 * PCR0, PCR1: 80-pin primary cable reporting for both disks
7907 * SCR0, SCR1: 80-pin secondary cable reporting for both disks
7908 */
7909 uint16_t u16Config = (1<<10) | (1<<7) | (1<<6) | (1<<5) | (1<<4);
7910 PDMPciDevSetByte(pPciDev, 0x54, u16Config & 0xff);
7911 PDMPciDevSetByte(pPciDev, 0x55, u16Config >> 8);
7912 }
7913 break;
7914 case CHIPSET_PIIX4:
7915 PDMPciDevSetDeviceId(pPciDev, 0x7111); /* PIIX4 IDE */
7916 PDMPciDevSetRevisionId(pPciDev, 0x01); /* PIIX4E */
7917 PDMPciDevSetByte(pPciDev, 0x48, 0x00); /* UDMACTL */
7918 PDMPciDevSetByte(pPciDev, 0x4A, 0x00); /* UDMATIM */
7919 PDMPciDevSetByte(pPciDev, 0x4B, 0x00);
7920 break;
7921 case CHIPSET_PIIX3:
7922 PDMPciDevSetDeviceId(pPciDev, 0x7010); /* PIIX3 IDE */
7923 break;
7924 default:
7925 AssertMsgFailed(("Unsupported IDE chipset type: %d\n", enmChipset));
7926 }
7927
7928 /** @todo
7929 * This is the job of the BIOS / EFI!
7930 *
7931 * The same is done in DevPCI.cpp / pci_bios_init_device() but there is no
7932 * corresponding function in DevPciIch9.cpp. The EFI has corresponding code
7933 * in OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c: NotifyDev() but this
7934 * function assumes that the IDE controller is located at PCI 00:01.1 which
7935 * is not true if the ICH9 chipset is used.
7936 */
7937 PDMPciDevSetWord(pPciDev, 0x40, 0x8000); /* enable IDE0 */
7938 PDMPciDevSetWord(pPciDev, 0x42, 0x8000); /* enable IDE1 */
7939
7940 PDMPciDevSetCommand( pPciDev, PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS | PCI_COMMAND_BUSMASTER);
7941 PDMPciDevSetClassProg( pPciDev, 0x8a); /* programming interface = PCI_IDE bus-master is supported */
7942 PDMPciDevSetClassSub( pPciDev, 0x01); /* class_sub = PCI_IDE */
7943 PDMPciDevSetClassBase( pPciDev, 0x01); /* class_base = PCI_mass_storage */
7944 PDMPciDevSetHeaderType(pPciDev, 0x00);
7945
7946 pThisCC->pDevIns = pDevIns;
7947 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7948 {
7949 pThisCC->aCts[i].pDevIns = pDevIns;
7950 pThisCC->aCts[i].iCtl = i;
7951 pThis->aCts[i].iCtl = i;
7952 pThis->aCts[i].msDelayIRQ = msDelayIRQ;
7953 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7954 {
7955 PATADEVSTATE pIf = &pThis->aCts[i].aIfs[j];
7956 PATADEVSTATER3 pIfR3 = &pThisCC->aCts[i].aIfs[j];
7957
7958 pIfR3->iLUN = pIf->iLUN = i * RT_ELEMENTS(pThis->aCts) + j;
7959 pIfR3->iCtl = pIf->iCtl = i;
7960 pIfR3->iDev = pIf->iDev = j;
7961 pIfR3->pDevIns = pDevIns;
7962 pIfR3->IBase.pfnQueryInterface = ataR3QueryInterface;
7963 pIfR3->IMountNotify.pfnMountNotify = ataR3MountNotify;
7964 pIfR3->IMountNotify.pfnUnmountNotify = ataR3UnmountNotify;
7965 pIfR3->IPort.pfnQueryDeviceLocation = ataR3QueryDeviceLocation;
7966 pIf->Led.u32Magic = PDMLED_MAGIC;
7967 }
7968 }
7969
7970 Assert(RT_ELEMENTS(pThis->aCts) == 2);
7971 pThis->aCts[0].irq = 14;
7972 pThis->aCts[0].IOPortBase1 = 0x1f0;
7973 pThis->aCts[0].IOPortBase2 = 0x3f6;
7974 pThis->aCts[1].irq = 15;
7975 pThis->aCts[1].IOPortBase1 = 0x170;
7976 pThis->aCts[1].IOPortBase2 = 0x376;
7977
7978 /*
7979 * Set the default critical section to NOP as we lock on controller level.
7980 */
7981 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
7982 AssertRCReturn(rc, rc);
7983
7984 /*
7985 * Register the PCI device.
7986 */
7987 rc = PDMDevHlpPCIRegisterEx(pDevIns, pPciDev, PDMPCIDEVREG_F_NOT_MANDATORY_NO, 1 /*uPciDevNo*/, 1 /*uPciDevFn*/, "piix3ide");
7988 if (RT_FAILURE(rc))
7989 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register PCI device"));
7990
7991 /* Region #4: I/O ports for the two bus-master DMA controllers. */
7992 rc = PDMDevHlpPCIIORegionCreateIo(pDevIns, 4 /*iPciRegion*/, 0x10 /*cPorts*/,
7993 ataBMDMAIOPortWrite, ataBMDMAIOPortRead, NULL /*pvUser*/, "ATA Bus Master DMA",
7994 NULL /*paExtDescs*/, &pThis->hIoPortsBmDma);
7995 AssertRCReturn(rc, rc);
7996
7997 /*
7998 * Register stats, create critical sections.
7999 */
8000 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
8001 {
8002 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
8003 {
8004 PATADEVSTATE pIf = &pThis->aCts[i].aIfs[j];
8005 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATADMA, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8006 "Number of ATA DMA transfers.", "/Devices/IDE%d/ATA%d/Unit%d/DMA", iInstance, i, j);
8007 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATAPIO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8008 "Number of ATA PIO transfers.", "/Devices/IDE%d/ATA%d/Unit%d/PIO", iInstance, i, j);
8009 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATAPIDMA, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8010 "Number of ATAPI DMA transfers.", "/Devices/IDE%d/ATA%d/Unit%d/AtapiDMA", iInstance, i, j);
8011 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATAPIPIO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8012 "Number of ATAPI PIO transfers.", "/Devices/IDE%d/ATA%d/Unit%d/AtapiPIO", iInstance, i, j);
8013#ifdef VBOX_WITH_STATISTICS /** @todo release too. */
8014 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatReads, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8015 "Profiling of the read operations.", "/Devices/IDE%d/ATA%d/Unit%d/Reads", iInstance, i, j);
8016#endif
8017 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
8018 "Amount of data read.", "/Devices/IDE%d/ATA%d/Unit%d/ReadBytes", iInstance, i, j);
8019#ifdef VBOX_INSTRUMENT_DMA_WRITES
8020 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatInstrVDWrites,STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8021 "Profiling of the VD DMA write operations.", "/Devices/IDE%d/ATA%d/Unit%d/InstrVDWrites", iInstance, i, j);
8022#endif
8023#ifdef VBOX_WITH_STATISTICS
8024 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatWrites, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8025 "Profiling of the write operations.", "/Devices/IDE%d/ATA%d/Unit%d/Writes", iInstance, i, j);
8026#endif
8027 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
8028 "Amount of data written.", "/Devices/IDE%d/ATA%d/Unit%d/WrittenBytes", iInstance, i, j);
8029#ifdef VBOX_WITH_STATISTICS
8030 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatFlushes, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8031 "Profiling of the flush operations.", "/Devices/IDE%d/ATA%d/Unit%d/Flushes", iInstance, i, j);
8032#endif
8033 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatStatusYields, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8034 "Profiling of status polling yields.", "/Devices/IDE%d/ATA%d/Unit%d/StatusYields", iInstance, i, j);
8035 }
8036#ifdef VBOX_WITH_STATISTICS /** @todo release too. */
8037 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncOps, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8038 "The number of async operations.", "/Devices/IDE%d/ATA%d/Async/Operations", iInstance, i);
8039 /** @todo STAMUNIT_MICROSECS */
8040 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncMinWait, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
8041 "Minimum wait in microseconds.", "/Devices/IDE%d/ATA%d/Async/MinWait", iInstance, i);
8042 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncMaxWait, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
8043 "Maximum wait in microseconds.", "/Devices/IDE%d/ATA%d/Async/MaxWait", iInstance, i);
8044 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncTimeUS, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
8045 "Total time spent in microseconds.", "/Devices/IDE%d/ATA%d/Async/TotalTimeUS", iInstance, i);
8046 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncTime, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8047 "Profiling of async operations.", "/Devices/IDE%d/ATA%d/Async/Time", iInstance, i);
8048 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatLockWait, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8049 "Profiling of locks.", "/Devices/IDE%d/ATA%d/Async/LockWait", iInstance, i);
8050#endif /* VBOX_WITH_STATISTICS */
8051
8052 /* Initialize per-controller critical section. */
8053 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->aCts[i].lock, RT_SRC_POS, "ATA#%u-Ctl", i);
8054 AssertLogRelRCReturn(rc, rc);
8055
8056 /* Initialize per-controller async I/O request critical section. */
8057 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->aCts[i].AsyncIORequestLock, RT_SRC_POS, "ATA#%u-Req", i);
8058 AssertLogRelRCReturn(rc, rc);
8059 }
8060
8061 /*
8062 * Attach status driver (optional).
8063 */
8064 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThisCC->IBase, &pBase, "Status Port");
8065 if (RT_SUCCESS(rc))
8066 {
8067 pThisCC->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS);
8068 pThisCC->pMediaNotify = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIANOTIFY);
8069 }
8070 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
8071 {
8072 AssertMsgFailed(("Failed to attach to status driver. rc=%Rrc\n", rc));
8073 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot attach to status driver"));
8074 }
8075
8076 /*
8077 * Attach the units.
8078 */
8079 uint32_t cbTotalBuffer = 0;
8080 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
8081 {
8082 PATACONTROLLER pCtl = &pThis->aCts[i];
8083 PATACONTROLLERR3 pCtlR3 = &pThisCC->aCts[i];
8084
8085 /*
8086 * Start the worker thread.
8087 */
8088 pCtl->uAsyncIOState = ATA_AIO_NEW;
8089 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pCtl->hAsyncIOSem);
8090 AssertLogRelRCReturn(rc, rc);
8091 rc = RTSemEventCreate(&pCtlR3->hSuspendIOSem);
8092 AssertLogRelRCReturn(rc, rc);
8093
8094 ataR3AsyncIOClearRequests(pDevIns, pCtl);
8095 rc = RTThreadCreateF(&pCtlR3->hAsyncIOThread, ataR3AsyncIOThread, pCtlR3, 0,
8096 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "ATA-%u", i);
8097 AssertLogRelRCReturn(rc, rc);
8098 Assert( pCtlR3->hAsyncIOThread != NIL_RTTHREAD && pCtl->hAsyncIOSem != NIL_SUPSEMEVENT
8099 && pCtlR3->hSuspendIOSem != NIL_RTSEMEVENT && PDMDevHlpCritSectIsInitialized(pDevIns, &pCtl->AsyncIORequestLock));
8100 Log(("%s: controller %d AIO thread id %#x; sem %p susp_sem %p\n", __FUNCTION__, i, pCtlR3->hAsyncIOThread, pCtl->hAsyncIOSem, pCtlR3->hSuspendIOSem));
8101
8102 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
8103 {
8104 static const char *s_apszDescs[RT_ELEMENTS(pThis->aCts)][RT_ELEMENTS(pCtl->aIfs)] =
8105 {
8106 { "Primary Master", "Primary Slave" },
8107 { "Secondary Master", "Secondary Slave" }
8108 };
8109
8110 /*
8111 * Try attach the block device and get the interfaces,
8112 * required as well as optional.
8113 */
8114 PATADEVSTATE pIf = &pCtl->aIfs[j];
8115 PATADEVSTATER3 pIfR3 = &pCtlR3->aIfs[j];
8116
8117 rc = PDMDevHlpDriverAttach(pDevIns, pIf->iLUN, &pIfR3->IBase, &pIfR3->pDrvBase, s_apszDescs[i][j]);
8118 if (RT_SUCCESS(rc))
8119 {
8120 rc = ataR3ConfigLun(pIf, pIfR3);
8121 if (RT_SUCCESS(rc))
8122 {
8123 /*
8124 * Init vendor product data.
8125 */
8126 static const char *s_apszCFGMKeys[RT_ELEMENTS(pThis->aCts)][RT_ELEMENTS(pCtl->aIfs)] =
8127 {
8128 { "PrimaryMaster", "PrimarySlave" },
8129 { "SecondaryMaster", "SecondarySlave" }
8130 };
8131
8132 /* Generate a default serial number. */
8133 char szSerial[ATA_SERIAL_NUMBER_LENGTH+1];
8134 RTUUID Uuid;
8135 if (pIfR3->pDrvMedia)
8136 rc = pIfR3->pDrvMedia->pfnGetUuid(pIfR3->pDrvMedia, &Uuid);
8137 else
8138 RTUuidClear(&Uuid);
8139
8140 if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
8141 {
8142 /* Generate a predictable serial for drives which don't have a UUID. */
8143 RTStrPrintf(szSerial, sizeof(szSerial), "VB%x-%04x%04x",
8144 pIf->iLUN + pDevIns->iInstance * 32,
8145 pThis->aCts[i].IOPortBase1, pThis->aCts[i].IOPortBase2);
8146 }
8147 else
8148 RTStrPrintf(szSerial, sizeof(szSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
8149
8150 /* Get user config if present using defaults otherwise. */
8151 PCFGMNODE pCfgNode = pHlp->pfnCFGMGetChild(pCfg, s_apszCFGMKeys[i][j]);
8152 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "SerialNumber", pIf->szSerialNumber, sizeof(pIf->szSerialNumber),
8153 szSerial);
8154 if (RT_FAILURE(rc))
8155 {
8156 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8157 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8158 N_("PIIX3 configuration error: \"SerialNumber\" is longer than 20 bytes"));
8159 return PDMDEV_SET_ERROR(pDevIns, rc,
8160 N_("PIIX3 configuration error: failed to read \"SerialNumber\" as string"));
8161 }
8162
8163 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "FirmwareRevision", pIf->szFirmwareRevision,
8164 sizeof(pIf->szFirmwareRevision), "1.0");
8165 if (RT_FAILURE(rc))
8166 {
8167 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8168 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8169 N_("PIIX3 configuration error: \"FirmwareRevision\" is longer than 8 bytes"));
8170 return PDMDEV_SET_ERROR(pDevIns, rc,
8171 N_("PIIX3 configuration error: failed to read \"FirmwareRevision\" as string"));
8172 }
8173
8174 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ModelNumber", pIf->szModelNumber, sizeof(pIf->szModelNumber),
8175 pIf->fATAPI ? "VBOX CD-ROM" : "VBOX HARDDISK");
8176 if (RT_FAILURE(rc))
8177 {
8178 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8179 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8180 N_("PIIX3 configuration error: \"ModelNumber\" is longer than 40 bytes"));
8181 return PDMDEV_SET_ERROR(pDevIns, rc,
8182 N_("PIIX3 configuration error: failed to read \"ModelNumber\" as string"));
8183 }
8184
8185 /* There are three other identification strings for CD drives used for INQUIRY */
8186 if (pIf->fATAPI)
8187 {
8188 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ATAPIVendorId", pIf->szInquiryVendorId,
8189 sizeof(pIf->szInquiryVendorId), "VBOX");
8190 if (RT_FAILURE(rc))
8191 {
8192 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8193 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8194 N_("PIIX3 configuration error: \"ATAPIVendorId\" is longer than 16 bytes"));
8195 return PDMDEV_SET_ERROR(pDevIns, rc,
8196 N_("PIIX3 configuration error: failed to read \"ATAPIVendorId\" as string"));
8197 }
8198
8199 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ATAPIProductId", pIf->szInquiryProductId,
8200 sizeof(pIf->szInquiryProductId), "CD-ROM");
8201 if (RT_FAILURE(rc))
8202 {
8203 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8204 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8205 N_("PIIX3 configuration error: \"ATAPIProductId\" is longer than 16 bytes"));
8206 return PDMDEV_SET_ERROR(pDevIns, rc,
8207 N_("PIIX3 configuration error: failed to read \"ATAPIProductId\" as string"));
8208 }
8209
8210 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ATAPIRevision", pIf->szInquiryRevision,
8211 sizeof(pIf->szInquiryRevision), "1.0");
8212 if (RT_FAILURE(rc))
8213 {
8214 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8215 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8216 N_("PIIX3 configuration error: \"ATAPIRevision\" is longer than 4 bytes"));
8217 return PDMDEV_SET_ERROR(pDevIns, rc,
8218 N_("PIIX3 configuration error: failed to read \"ATAPIRevision\" as string"));
8219 }
8220
8221 rc = pHlp->pfnCFGMQueryBoolDef(pCfgNode, "OverwriteInquiry", &pIf->fOverwriteInquiry, true);
8222 if (RT_FAILURE(rc))
8223 return PDMDEV_SET_ERROR(pDevIns, rc,
8224 N_("PIIX3 configuration error: failed to read \"OverwriteInquiry\" as boolean"));
8225 }
8226 }
8227 }
8228 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
8229 {
8230 pIfR3->pDrvBase = NULL;
8231 pIfR3->pDrvMedia = NULL;
8232 pIf->cbIOBuffer = 0;
8233 pIf->fPresent = false;
8234 LogRel(("PIIX3 ATA: LUN#%d: no unit\n", pIf->iLUN));
8235 }
8236 else
8237 {
8238 switch (rc)
8239 {
8240 case VERR_ACCESS_DENIED:
8241 /* Error already cached by DrvHostBase */
8242 return rc;
8243 default:
8244 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
8245 N_("PIIX3 cannot attach drive to the %s"),
8246 s_apszDescs[i][j]);
8247 }
8248 }
8249 cbTotalBuffer += pIf->cbIOBuffer;
8250 }
8251 }
8252
8253 /*
8254 * Register the I/O ports.
8255 * The ports are all hardcoded and enforced by the PIIX3 host bridge controller.
8256 */
8257 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
8258 {
8259 Assert(pThis->aCts[i].aIfs[0].fPresent == (pThisCC->aCts[i].aIfs[0].pDrvMedia != NULL));
8260 Assert(pThis->aCts[i].aIfs[1].fPresent == (pThisCC->aCts[i].aIfs[1].pDrvMedia != NULL));
8261
8262 if (!pThisCC->aCts[i].aIfs[0].pDrvMedia && !pThisCC->aCts[i].aIfs[1].pDrvMedia)
8263 {
8264 /* No device present on this ATA bus; requires special handling. */
8265 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase1, 8 /*cPorts*/, IOM_IOPORT_F_ABS,
8266 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8267 "ATA I/O Base 1 - Empty Bus", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPortsEmpty1);
8268 AssertLogRelRCReturn(rc, rc);
8269 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase2, 1 /*cPorts*/, IOM_IOPORT_F_ABS,
8270 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8271 "ATA I/O Base 2 - Empty Bus", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPortsEmpty2);
8272 AssertLogRelRCReturn(rc, rc);
8273 }
8274 else
8275 {
8276 /* At least one device present, register regular handlers. */
8277 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase1, 1 /*cPorts*/, IOM_IOPORT_F_ABS,
8278 ataIOPortWrite1Data, ataIOPortRead1Data,
8279 ataIOPortWriteStr1Data, ataIOPortReadStr1Data, (RTHCPTR)(uintptr_t)i,
8280 "ATA I/O Base 1 - Data", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPorts1First);
8281 AssertLogRelRCReturn(rc, rc);
8282 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7 /*cPorts*/, IOM_IOPORT_F_ABS,
8283 ataIOPortWrite1Other, ataIOPortRead1Other, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8284 "ATA I/O Base 1 - Other", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPorts1Other);
8285 AssertLogRelRCReturn(rc, rc);
8286
8287
8288 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase2, 1 /*cPorts*/, IOM_IOPORT_F_ABS,
8289 ataIOPortWrite2, ataIOPortRead2, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8290 "ATA I/O Base 2", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPorts2);
8291 AssertLogRelRCReturn(rc, rc);
8292 }
8293 }
8294
8295 rc = PDMDevHlpSSMRegisterEx(pDevIns, ATA_SAVED_STATE_VERSION, sizeof(*pThis) + cbTotalBuffer, NULL,
8296 NULL, ataR3LiveExec, NULL,
8297 ataR3SaveLoadPrep, ataR3SaveExec, NULL,
8298 ataR3SaveLoadPrep, ataR3LoadExec, NULL);
8299 if (RT_FAILURE(rc))
8300 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register save state handlers"));
8301
8302 /*
8303 * Initialize the device state.
8304 */
8305 return ataR3ResetCommon(pDevIns, true /*fConstruct*/);
8306}
8307
8308#else /* !IN_RING3 */
8309
8310/**
8311 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
8312 */
8313static DECLCALLBACK(int) ataRZConstruct(PPDMDEVINS pDevIns)
8314{
8315 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
8316 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
8317
8318 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
8319 AssertRCReturn(rc, rc);
8320
8321 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPortsBmDma, ataBMDMAIOPortWrite, ataBMDMAIOPortRead, NULL /*pvUser*/);
8322 AssertRCReturn(rc, rc);
8323
8324 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
8325 {
8326 if (pThis->aCts[i].hIoPorts1First != NIL_IOMIOPORTHANDLE)
8327 {
8328 rc = PDMDevHlpIoPortSetUpContextEx(pDevIns, pThis->aCts[i].hIoPorts1First,
8329 ataIOPortWrite1Data, ataIOPortRead1Data,
8330 ataIOPortWriteStr1Data, ataIOPortReadStr1Data, (RTHCPTR)(uintptr_t)i);
8331 AssertLogRelRCReturn(rc, rc);
8332 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPorts1Other,
8333 ataIOPortWrite1Other, ataIOPortRead1Other, (RTHCPTR)(uintptr_t)i);
8334 AssertLogRelRCReturn(rc, rc);
8335 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPorts2,
8336 ataIOPortWrite2, ataIOPortRead2, (RTHCPTR)(uintptr_t)i);
8337 AssertLogRelRCReturn(rc, rc);
8338 }
8339 else
8340 {
8341 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPortsEmpty1,
8342 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, (void *)(uintptr_t)i /*pvUser*/);
8343 AssertRCReturn(rc, rc);
8344
8345 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPortsEmpty2,
8346 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, (void *)(uintptr_t)i /*pvUser*/);
8347 AssertRCReturn(rc, rc);
8348 }
8349 }
8350
8351 return VINF_SUCCESS;
8352}
8353
8354
8355#endif /* !IN_RING3 */
8356
8357/**
8358 * The device registration structure.
8359 */
8360const PDMDEVREG g_DevicePIIX3IDE =
8361{
8362 /* .u32Version = */ PDM_DEVREG_VERSION,
8363 /* .uReserved0 = */ 0,
8364 /* .szName = */ "piix3ide",
8365 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE
8366 | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION
8367 | PDM_DEVREG_FLAGS_FIRST_RESET_NOTIFICATION,
8368 /* .fClass = */ PDM_DEVREG_CLASS_STORAGE,
8369 /* .cMaxInstances = */ 1,
8370 /* .uSharedVersion = */ 42,
8371 /* .cbInstanceShared = */ sizeof(ATASTATE),
8372 /* .cbInstanceCC = */ sizeof(ATASTATECC),
8373 /* .cbInstanceRC = */ sizeof(ATASTATERC),
8374 /* .cMaxPciDevices = */ 1,
8375 /* .cMaxMsixVectors = */ 0,
8376 /* .pszDescription = */ "Intel PIIX3 ATA controller.\n"
8377 " LUN #0 is primary master.\n"
8378 " LUN #1 is primary slave.\n"
8379 " LUN #2 is secondary master.\n"
8380 " LUN #3 is secondary slave.\n"
8381 " LUN #999 is the LED/Status connector.",
8382#if defined(IN_RING3)
8383 /* .pszRCMod = */ "VBoxDDRC.rc",
8384 /* .pszR0Mod = */ "VBoxDDR0.r0",
8385 /* .pfnConstruct = */ ataR3Construct,
8386 /* .pfnDestruct = */ ataR3Destruct,
8387 /* .pfnRelocate = */ NULL,
8388 /* .pfnMemSetup = */ NULL,
8389 /* .pfnPowerOn = */ NULL,
8390 /* .pfnReset = */ ataR3Reset,
8391 /* .pfnSuspend = */ ataR3Suspend,
8392 /* .pfnResume = */ ataR3Resume,
8393 /* .pfnAttach = */ ataR3Attach,
8394 /* .pfnDetach = */ ataR3Detach,
8395 /* .pfnQueryInterface = */ NULL,
8396 /* .pfnInitComplete = */ NULL,
8397 /* .pfnPowerOff = */ ataR3PowerOff,
8398 /* .pfnSoftReset = */ NULL,
8399 /* .pfnReserved0 = */ NULL,
8400 /* .pfnReserved1 = */ NULL,
8401 /* .pfnReserved2 = */ NULL,
8402 /* .pfnReserved3 = */ NULL,
8403 /* .pfnReserved4 = */ NULL,
8404 /* .pfnReserved5 = */ NULL,
8405 /* .pfnReserved6 = */ NULL,
8406 /* .pfnReserved7 = */ NULL,
8407#elif defined(IN_RING0)
8408 /* .pfnEarlyConstruct = */ NULL,
8409 /* .pfnConstruct = */ ataRZConstruct,
8410 /* .pfnDestruct = */ NULL,
8411 /* .pfnFinalDestruct = */ NULL,
8412 /* .pfnRequest = */ NULL,
8413 /* .pfnReserved0 = */ NULL,
8414 /* .pfnReserved1 = */ NULL,
8415 /* .pfnReserved2 = */ NULL,
8416 /* .pfnReserved3 = */ NULL,
8417 /* .pfnReserved4 = */ NULL,
8418 /* .pfnReserved5 = */ NULL,
8419 /* .pfnReserved6 = */ NULL,
8420 /* .pfnReserved7 = */ NULL,
8421#elif defined(IN_RC)
8422 /* .pfnConstruct = */ ataRZConstruct,
8423 /* .pfnReserved0 = */ NULL,
8424 /* .pfnReserved1 = */ NULL,
8425 /* .pfnReserved2 = */ NULL,
8426 /* .pfnReserved3 = */ NULL,
8427 /* .pfnReserved4 = */ NULL,
8428 /* .pfnReserved5 = */ NULL,
8429 /* .pfnReserved6 = */ NULL,
8430 /* .pfnReserved7 = */ NULL,
8431#else
8432# error "Not in IN_RING3, IN_RING0 or IN_RC!"
8433#endif
8434 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
8435};
8436#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

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