VirtualBox

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

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

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 332.1 KB
Line 
1/* $Id: DevATA.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VBox storage devices: ATA/ATAPI controller device (disk and cdrom).
4 */
5
6/*
7 * Copyright (C) 2006-2022 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 /* 28 bytes of total returned data corresponds to ATAPI 2.6. Note that at least some versions
3147 * of NEC_IDE.SYS DOS driver (possibly other Oak Technology OTI-011 drivers) do not correctly
3148 * handle cases where more than 28 bytes are returned due to bugs. See @bugref{5869}.
3149 */
3150 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3151 Assert(s->cbElementaryTransfer <= 28);
3152 scsiH2BE_U16(&pbBuf[0], 26);
3153 pbBuf[2] = (uint8_t)s->MediaTrackType;
3154 pbBuf[3] = 0;
3155 pbBuf[4] = 0;
3156 pbBuf[5] = 0;
3157 pbBuf[6] = 0;
3158 pbBuf[7] = 0;
3159
3160 pbBuf[8] = 0x2a;
3161 pbBuf[9] = 18; /* page length */
3162 pbBuf[10] = 0x08; /* DVD-ROM read support */
3163 pbBuf[11] = 0x00; /* no write support */
3164 /* The following claims we support audio play. This is obviously false,
3165 * but the Linux generic CDROM support makes many features depend on this
3166 * capability. If it's not set, this causes many things to be disabled. */
3167 pbBuf[12] = 0x71; /* multisession support, mode 2 form 1/2 support, audio play */
3168 pbBuf[13] = 0x00; /* no subchannel reads supported */
3169 pbBuf[14] = (1 << 0) | (1 << 3) | (1 << 5); /* lock supported, eject supported, tray type loading mechanism */
3170 if (pDevR3->pDrvMount->pfnIsLocked(pDevR3->pDrvMount))
3171 pbBuf[14] |= 1 << 1; /* report lock state */
3172 pbBuf[15] = 0; /* no subchannel reads supported, no separate audio volume control, no changer etc. */
3173 scsiH2BE_U16(&pbBuf[16], 5632); /* (obsolete) claim 32x speed support */
3174 scsiH2BE_U16(&pbBuf[18], 2); /* number of audio volume levels */
3175 scsiH2BE_U16(&pbBuf[20], RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE) / _1K); /* buffer size supported in Kbyte */
3176 scsiH2BE_U16(&pbBuf[22], 5632); /* (obsolete) current read speed 32x */
3177 pbBuf[24] = 0; /* reserved */
3178 pbBuf[25] = 0; /* reserved for digital audio (see idx 15) */
3179 pbBuf[26] = 0; /* reserved */
3180 pbBuf[27] = 0; /* reserved */
3181 s->iSourceSink = ATAFN_SS_NULL;
3182 atapiR3CmdOK(pCtl, s);
3183 return false;
3184}
3185
3186
3187/**
3188 * Sink/Source: ATAPI REQUEST SENSE
3189 */
3190static bool atapiR3RequestSenseSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3191{
3192 uint8_t *pbBuf = s->abIOBuffer;
3193 RT_NOREF(pDevIns, pDevR3);
3194
3195 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3196 memset(pbBuf, '\0', RT_MIN(s->cbElementaryTransfer, sizeof(s->abIOBuffer)));
3197 AssertCompile(sizeof(s->abIOBuffer) >= sizeof(s->abATAPISense));
3198 memcpy(pbBuf, s->abATAPISense, RT_MIN(s->cbElementaryTransfer, sizeof(s->abATAPISense)));
3199 s->iSourceSink = ATAFN_SS_NULL;
3200 atapiR3CmdOK(pCtl, s);
3201 return false;
3202}
3203
3204
3205/**
3206 * Sink/Source: ATAPI MECHANISM STATUS
3207 */
3208static bool atapiR3MechanismStatusSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3209{
3210 uint8_t *pbBuf = s->abIOBuffer;
3211 RT_NOREF(pDevIns, pDevR3);
3212
3213 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3214 Assert(s->cbElementaryTransfer <= 8);
3215 scsiH2BE_U16(pbBuf, 0);
3216 /* no current LBA */
3217 pbBuf[2] = 0;
3218 pbBuf[3] = 0;
3219 pbBuf[4] = 0;
3220 pbBuf[5] = 1;
3221 scsiH2BE_U16(pbBuf + 6, 0);
3222 s->iSourceSink = ATAFN_SS_NULL;
3223 atapiR3CmdOK(pCtl, s);
3224 return false;
3225}
3226
3227
3228/**
3229 * Sink/Source: ATAPI READ TOC NORMAL
3230 */
3231static bool atapiR3ReadTOCNormalSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3232{
3233 uint8_t *pbBuf = s->abIOBuffer;
3234 uint8_t *q;
3235 uint8_t iStartTrack;
3236 bool fMSF;
3237 uint32_t cbSize;
3238 RT_NOREF(pDevIns);
3239
3240 /* Track fields are 8-bit and 1-based, so cut the track count at 255,
3241 avoiding any potential buffer overflow issues below. */
3242 uint32_t cTracks = pDevR3->pDrvMedia->pfnGetRegionCount(pDevR3->pDrvMedia);
3243 AssertStmt(cTracks <= UINT8_MAX, cTracks = UINT8_MAX);
3244 AssertCompile(sizeof(s->abIOBuffer) >= 2 + 256 + 8);
3245
3246 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3247 fMSF = (s->abATAPICmd[1] >> 1) & 1;
3248 iStartTrack = s->abATAPICmd[6];
3249 if (iStartTrack == 0)
3250 iStartTrack = 1;
3251
3252 if (iStartTrack > cTracks && iStartTrack != 0xaa)
3253 {
3254 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3255 return false;
3256 }
3257 q = pbBuf + 2;
3258 *q++ = iStartTrack; /* first track number */
3259 *q++ = cTracks; /* last track number */
3260 for (uint32_t iTrack = iStartTrack; iTrack <= cTracks; iTrack++)
3261 {
3262 uint64_t uLbaStart = 0;
3263 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048;
3264
3265 int rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, iTrack - 1, &uLbaStart,
3266 NULL, NULL, &enmDataForm);
3267 AssertRC(rc);
3268
3269 *q++ = 0; /* reserved */
3270
3271 if (enmDataForm == VDREGIONDATAFORM_CDDA)
3272 *q++ = 0x10; /* ADR, control */
3273 else
3274 *q++ = 0x14; /* ADR, control */
3275
3276 *q++ = (uint8_t)iTrack; /* track number */
3277 *q++ = 0; /* reserved */
3278 if (fMSF)
3279 {
3280 *q++ = 0; /* reserved */
3281 scsiLBA2MSF(q, (uint32_t)uLbaStart);
3282 q += 3;
3283 }
3284 else
3285 {
3286 /* sector 0 */
3287 scsiH2BE_U32(q, (uint32_t)uLbaStart);
3288 q += 4;
3289 }
3290 }
3291 /* lead out track */
3292 *q++ = 0; /* reserved */
3293 *q++ = 0x14; /* ADR, control */
3294 *q++ = 0xaa; /* track number */
3295 *q++ = 0; /* reserved */
3296
3297 /* Query start and length of last track to get the start of the lead out track. */
3298 uint64_t uLbaStart = 0;
3299 uint64_t cBlocks = 0;
3300
3301 int rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, cTracks - 1, &uLbaStart,
3302 &cBlocks, NULL, NULL);
3303 AssertRC(rc);
3304
3305 uLbaStart += cBlocks;
3306 if (fMSF)
3307 {
3308 *q++ = 0; /* reserved */
3309 scsiLBA2MSF(q, (uint32_t)uLbaStart);
3310 q += 3;
3311 }
3312 else
3313 {
3314 scsiH2BE_U32(q, (uint32_t)uLbaStart);
3315 q += 4;
3316 }
3317 cbSize = q - pbBuf;
3318 scsiH2BE_U16(pbBuf, cbSize - 2);
3319 if (cbSize < s->cbTotalTransfer)
3320 s->cbTotalTransfer = cbSize;
3321 s->iSourceSink = ATAFN_SS_NULL;
3322 atapiR3CmdOK(pCtl, s);
3323 return false;
3324}
3325
3326
3327/**
3328 * Sink/Source: ATAPI READ TOC MULTI
3329 */
3330static bool atapiR3ReadTOCMultiSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3331{
3332 uint8_t *pbBuf = s->abIOBuffer;
3333 bool fMSF;
3334 RT_NOREF(pDevIns);
3335
3336 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3337 Assert(s->cbElementaryTransfer <= 12);
3338 fMSF = (s->abATAPICmd[1] >> 1) & 1;
3339 /* multi session: only a single session defined */
3340 /** @todo double-check this stuff against what a real drive says for a CD-ROM (not a CD-R)
3341 * with only a single data session. Maybe solve the problem with "cdrdao read-toc" not being
3342 * able to figure out whether numbers are in BCD or hex. */
3343 memset(pbBuf, 0, 12);
3344 pbBuf[1] = 0x0a;
3345 pbBuf[2] = 0x01;
3346 pbBuf[3] = 0x01;
3347
3348 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048;
3349 int rc = pDevR3->pDrvMedia->pfnQueryRegionProperties(pDevR3->pDrvMedia, 0, NULL, NULL, NULL, &enmDataForm);
3350 AssertRC(rc);
3351
3352 if (enmDataForm == VDREGIONDATAFORM_CDDA)
3353 pbBuf[5] = 0x10; /* ADR, control */
3354 else
3355 pbBuf[5] = 0x14; /* ADR, control */
3356
3357 pbBuf[6] = 1; /* first track in last complete session */
3358 if (fMSF)
3359 {
3360 pbBuf[8] = 0; /* reserved */
3361 scsiLBA2MSF(&pbBuf[9], 0);
3362 }
3363 else
3364 {
3365 /* sector 0 */
3366 scsiH2BE_U32(pbBuf + 8, 0);
3367 }
3368 s->iSourceSink = ATAFN_SS_NULL;
3369 atapiR3CmdOK(pCtl, s);
3370 return false;
3371}
3372
3373
3374/**
3375 * Sink/Source: ATAPI READ TOC RAW
3376 */
3377static bool atapiR3ReadTOCRawSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3378{
3379 uint8_t *pbBuf = s->abIOBuffer;
3380 uint8_t *q;
3381 uint8_t iStartTrack;
3382 bool fMSF;
3383 uint32_t cbSize;
3384 RT_NOREF(pDevIns, pDevR3);
3385
3386 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE);
3387 fMSF = (s->abATAPICmd[1] >> 1) & 1;
3388 iStartTrack = s->abATAPICmd[6];
3389
3390 q = pbBuf + 2;
3391 *q++ = 1; /* first session */
3392 *q++ = 1; /* last session */
3393
3394 *q++ = 1; /* session number */
3395 *q++ = 0x14; /* data track */
3396 *q++ = 0; /* track number */
3397 *q++ = 0xa0; /* first track in program area */
3398 *q++ = 0; /* min */
3399 *q++ = 0; /* sec */
3400 *q++ = 0; /* frame */
3401 *q++ = 0;
3402 *q++ = 1; /* first track */
3403 *q++ = 0x00; /* disk type CD-DA or CD data */
3404 *q++ = 0;
3405
3406 *q++ = 1; /* session number */
3407 *q++ = 0x14; /* data track */
3408 *q++ = 0; /* track number */
3409 *q++ = 0xa1; /* last track in program area */
3410 *q++ = 0; /* min */
3411 *q++ = 0; /* sec */
3412 *q++ = 0; /* frame */
3413 *q++ = 0;
3414 *q++ = 1; /* last track */
3415 *q++ = 0;
3416 *q++ = 0;
3417
3418 *q++ = 1; /* session number */
3419 *q++ = 0x14; /* data track */
3420 *q++ = 0; /* track number */
3421 *q++ = 0xa2; /* lead-out */
3422 *q++ = 0; /* min */
3423 *q++ = 0; /* sec */
3424 *q++ = 0; /* frame */
3425 if (fMSF)
3426 {
3427 *q++ = 0; /* reserved */
3428 scsiLBA2MSF(q, s->cTotalSectors);
3429 q += 3;
3430 }
3431 else
3432 {
3433 scsiH2BE_U32(q, s->cTotalSectors);
3434 q += 4;
3435 }
3436
3437 *q++ = 1; /* session number */
3438 *q++ = 0x14; /* ADR, control */
3439 *q++ = 0; /* track number */
3440 *q++ = 1; /* point */
3441 *q++ = 0; /* min */
3442 *q++ = 0; /* sec */
3443 *q++ = 0; /* frame */
3444 if (fMSF)
3445 {
3446 *q++ = 0; /* reserved */
3447 scsiLBA2MSF(q, 0);
3448 q += 3;
3449 }
3450 else
3451 {
3452 /* sector 0 */
3453 scsiH2BE_U32(q, 0);
3454 q += 4;
3455 }
3456
3457 cbSize = q - pbBuf;
3458 scsiH2BE_U16(pbBuf, cbSize - 2);
3459 if (cbSize < s->cbTotalTransfer)
3460 s->cbTotalTransfer = cbSize;
3461 s->iSourceSink = ATAFN_SS_NULL;
3462 atapiR3CmdOK(pCtl, s);
3463 return false;
3464}
3465
3466
3467static void atapiR3ParseCmdVirtualATAPI(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3468{
3469 const uint8_t *pbPacket = s->abATAPICmd;
3470 uint32_t cbMax;
3471 uint32_t cSectors, iATAPILBA;
3472
3473 switch (pbPacket[0])
3474 {
3475 case SCSI_TEST_UNIT_READY:
3476 if (s->cNotifiedMediaChange > 0)
3477 {
3478 if (s->cNotifiedMediaChange-- > 2)
3479 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3480 else
3481 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3482 }
3483 else if (pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3484 atapiR3CmdOK(pCtl, s);
3485 else
3486 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3487 break;
3488 case SCSI_GET_EVENT_STATUS_NOTIFICATION:
3489 cbMax = scsiBE2H_U16(pbPacket + 7);
3490 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
3491 break;
3492 case SCSI_MODE_SENSE_10:
3493 {
3494 uint8_t uPageControl, uPageCode;
3495 cbMax = scsiBE2H_U16(pbPacket + 7);
3496 uPageControl = pbPacket[2] >> 6;
3497 uPageCode = pbPacket[2] & 0x3f;
3498 switch (uPageControl)
3499 {
3500 case SCSI_PAGECONTROL_CURRENT:
3501 switch (uPageCode)
3502 {
3503 case SCSI_MODEPAGE_ERROR_RECOVERY:
3504 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 16), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true);
3505 break;
3506 case SCSI_MODEPAGE_CD_STATUS:
3507 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 28), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
3508 break;
3509 default:
3510 goto error_cmd;
3511 }
3512 break;
3513 case SCSI_PAGECONTROL_CHANGEABLE:
3514 goto error_cmd;
3515 case SCSI_PAGECONTROL_DEFAULT:
3516 goto error_cmd;
3517 default:
3518 case SCSI_PAGECONTROL_SAVED:
3519 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
3520 break;
3521 }
3522 break;
3523 }
3524 case SCSI_REQUEST_SENSE:
3525 cbMax = pbPacket[4];
3526 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
3527 break;
3528 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
3529 if (pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3530 {
3531 if (pbPacket[4] & 1)
3532 pDevR3->pDrvMount->pfnLock(pDevR3->pDrvMount);
3533 else
3534 pDevR3->pDrvMount->pfnUnlock(pDevR3->pDrvMount);
3535 atapiR3CmdOK(pCtl, s);
3536 }
3537 else
3538 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3539 break;
3540 case SCSI_READ_10:
3541 case SCSI_READ_12:
3542 {
3543 if (s->cNotifiedMediaChange > 0)
3544 {
3545 s->cNotifiedMediaChange-- ;
3546 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3547 break;
3548 }
3549 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3550 {
3551 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3552 break;
3553 }
3554 if (pbPacket[0] == SCSI_READ_10)
3555 cSectors = scsiBE2H_U16(pbPacket + 7);
3556 else
3557 cSectors = scsiBE2H_U32(pbPacket + 6);
3558 iATAPILBA = scsiBE2H_U32(pbPacket + 2);
3559
3560 if (cSectors == 0)
3561 {
3562 atapiR3CmdOK(pCtl, s);
3563 break;
3564 }
3565
3566 /* Check that the sector size is valid. */
3567 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_INVALID;
3568 int rc = pDevR3->pDrvMedia->pfnQueryRegionPropertiesForLba(pDevR3->pDrvMedia, iATAPILBA,
3569 NULL, NULL, NULL, &enmDataForm);
3570 if (RT_UNLIKELY( rc == VERR_NOT_FOUND
3571 || ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)))
3572 {
3573 /* Rate limited logging, one log line per second. For
3574 * guests that insist on reading from places outside the
3575 * valid area this often generates too many release log
3576 * entries otherwise. */
3577 static uint64_t uLastLogTS = 0;
3578 if (RTTimeMilliTS() >= uLastLogTS + 1000)
3579 {
3580 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
3581 uLastLogTS = RTTimeMilliTS();
3582 }
3583 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
3584 break;
3585 }
3586 else if ( enmDataForm != VDREGIONDATAFORM_MODE1_2048
3587 && enmDataForm != VDREGIONDATAFORM_MODE1_2352
3588 && enmDataForm != VDREGIONDATAFORM_MODE2_2336
3589 && enmDataForm != VDREGIONDATAFORM_MODE2_2352
3590 && enmDataForm != VDREGIONDATAFORM_RAW)
3591 {
3592 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
3593 RT_ZERO(abATAPISense);
3594
3595 abATAPISense[0] = 0x70 | (1 << 7);
3596 abATAPISense[2] = (SCSI_SENSE_ILLEGAL_REQUEST & 0x0f) | SCSI_SENSE_FLAG_ILI;
3597 scsiH2BE_U32(&abATAPISense[3], iATAPILBA);
3598 abATAPISense[7] = 10;
3599 abATAPISense[12] = SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK;
3600 atapiR3CmdError(pCtl, s, &abATAPISense[0], sizeof(abATAPISense));
3601 break;
3602 }
3603 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2048);
3604 break;
3605 }
3606 case SCSI_READ_CD_MSF:
3607 case SCSI_READ_CD:
3608 {
3609 if (s->cNotifiedMediaChange > 0)
3610 {
3611 s->cNotifiedMediaChange-- ;
3612 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3613 break;
3614 }
3615 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3616 {
3617 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3618 break;
3619 }
3620 if ((pbPacket[10] & 0x7) != 0)
3621 {
3622 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3623 break;
3624 }
3625 if (pbPacket[0] == SCSI_READ_CD)
3626 {
3627 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
3628 iATAPILBA = scsiBE2H_U32(pbPacket + 2);
3629 }
3630 else /* READ CD MSF */
3631 {
3632 iATAPILBA = scsiMSF2LBA(pbPacket + 3);
3633 if (iATAPILBA > scsiMSF2LBA(pbPacket + 6))
3634 {
3635 Log2(("Start MSF %02u:%02u:%02u > end MSF %02u:%02u:%02u!\n", *(pbPacket + 3), *(pbPacket + 4), *(pbPacket + 5),
3636 *(pbPacket + 6), *(pbPacket + 7), *(pbPacket + 8)));
3637 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3638 break;
3639 }
3640 cSectors = scsiMSF2LBA(pbPacket + 6) - iATAPILBA;
3641 Log2(("Start MSF %02u:%02u:%02u -> LBA %u\n", *(pbPacket + 3), *(pbPacket + 4), *(pbPacket + 5), iATAPILBA));
3642 Log2(("End MSF %02u:%02u:%02u -> %u sectors\n", *(pbPacket + 6), *(pbPacket + 7), *(pbPacket + 8), cSectors));
3643 }
3644 if (cSectors == 0)
3645 {
3646 atapiR3CmdOK(pCtl, s);
3647 break;
3648 }
3649 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
3650 {
3651 /* Rate limited logging, one log line per second. For
3652 * guests that insist on reading from places outside the
3653 * valid area this often generates too many release log
3654 * entries otherwise. */
3655 static uint64_t uLastLogTS = 0;
3656 if (RTTimeMilliTS() >= uLastLogTS + 1000)
3657 {
3658 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
3659 uLastLogTS = RTTimeMilliTS();
3660 }
3661 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
3662 break;
3663 }
3664 /*
3665 * If the LBA is in an audio track we are required to ignore pretty much all
3666 * of the channel selection values (except 0x00) and map everything to 0x10
3667 * which means read user data with a sector size of 2352 bytes.
3668 *
3669 * (MMC-6 chapter 6.19.2.6)
3670 */
3671 uint8_t uChnSel = pbPacket[9] & 0xf8;
3672 VDREGIONDATAFORM enmDataForm;
3673 int rc = pDevR3->pDrvMedia->pfnQueryRegionPropertiesForLba(pDevR3->pDrvMedia, iATAPILBA,
3674 NULL, NULL, NULL, &enmDataForm);
3675 AssertRC(rc);
3676
3677 if (enmDataForm == VDREGIONDATAFORM_CDDA)
3678 {
3679 if (uChnSel == 0)
3680 {
3681 /* nothing */
3682 atapiR3CmdOK(pCtl, s);
3683 }
3684 else
3685 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2352);
3686 }
3687 else
3688 {
3689 switch (uChnSel)
3690 {
3691 case 0x00:
3692 /* nothing */
3693 atapiR3CmdOK(pCtl, s);
3694 break;
3695 case 0x10:
3696 /* normal read */
3697 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2048);
3698 break;
3699 case 0xf8:
3700 /* read all data */
3701 atapiR3ReadSectors(pDevIns, pCtl, s, iATAPILBA, cSectors, 2352);
3702 break;
3703 default:
3704 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8));
3705 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3706 break;
3707 }
3708 }
3709 break;
3710 }
3711 case SCSI_SEEK_10:
3712 {
3713 if (s->cNotifiedMediaChange > 0)
3714 {
3715 s->cNotifiedMediaChange-- ;
3716 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3717 break;
3718 }
3719 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3720 {
3721 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3722 break;
3723 }
3724 iATAPILBA = scsiBE2H_U32(pbPacket + 2);
3725 if (iATAPILBA > s->cTotalSectors)
3726 {
3727 /* Rate limited logging, one log line per second. For
3728 * guests that insist on seeking to places outside the
3729 * valid area this often generates too many release log
3730 * entries otherwise. */
3731 static uint64_t uLastLogTS = 0;
3732 if (RTTimeMilliTS() >= uLastLogTS + 1000)
3733 {
3734 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA));
3735 uLastLogTS = RTTimeMilliTS();
3736 }
3737 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
3738 break;
3739 }
3740 atapiR3CmdOK(pCtl, s);
3741 ataSetStatus(pCtl, s, ATA_STAT_SEEK); /* Linux expects this. */
3742 break;
3743 }
3744 case SCSI_START_STOP_UNIT:
3745 {
3746 int rc = VINF_SUCCESS;
3747 switch (pbPacket[4] & 3)
3748 {
3749 case 0: /* 00 - Stop motor */
3750 case 1: /* 01 - Start motor */
3751 break;
3752 case 2: /* 10 - Eject media */
3753 {
3754 /* This must be done from EMT. */
3755 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
3756
3757 ataR3LockLeave(pDevIns, pCtl);
3758 rc = PDMDevHlpVMReqPriorityCallWait(pDevIns, VMCPUID_ANY,
3759 (PFNRT)pDevR3->pDrvMount->pfnUnmount, 3,
3760 pDevR3->pDrvMount, false /*=fForce*/, true /*=fEject*/);
3761 Assert(RT_SUCCESS(rc) || rc == VERR_PDM_MEDIA_LOCKED || rc == VERR_PDM_MEDIA_NOT_MOUNTED);
3762 if (RT_SUCCESS(rc) && pThisCC->pMediaNotify)
3763 {
3764 rc = PDMDevHlpVMReqCallNoWait(pDevIns, VMCPUID_ANY,
3765 (PFNRT)pThisCC->pMediaNotify->pfnEjected, 2,
3766 pThisCC->pMediaNotify, s->iLUN);
3767 AssertRC(rc);
3768 }
3769
3770 ataR3LockEnter(pDevIns, pCtl);
3771 break;
3772 }
3773 case 3: /* 11 - Load media */
3774 /** @todo rc = pDevR3->pDrvMount->pfnLoadMedia(pDevR3->pDrvMount) */
3775 break;
3776 }
3777 if (RT_SUCCESS(rc))
3778 atapiR3CmdOK(pCtl, s);
3779 else
3780 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
3781 break;
3782 }
3783 case SCSI_MECHANISM_STATUS:
3784 {
3785 cbMax = scsiBE2H_U16(pbPacket + 8);
3786 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true);
3787 break;
3788 }
3789 case SCSI_READ_TOC_PMA_ATIP:
3790 {
3791 uint8_t format;
3792
3793 if (s->cNotifiedMediaChange > 0)
3794 {
3795 s->cNotifiedMediaChange-- ;
3796 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3797 break;
3798 }
3799 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3800 {
3801 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3802 break;
3803 }
3804 cbMax = scsiBE2H_U16(pbPacket + 7);
3805 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
3806 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
3807 * the other field is clear... */
3808 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
3809 switch (format)
3810 {
3811 case 0:
3812 ataR3StartTransfer(pDevIns, pCtl, s, cbMax, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true);
3813 break;
3814 case 1:
3815 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 12), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true);
3816 break;
3817 case 2:
3818 ataR3StartTransfer(pDevIns, pCtl, s, cbMax, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true);
3819 break;
3820 default:
3821 error_cmd:
3822 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
3823 break;
3824 }
3825 break;
3826 }
3827 case SCSI_READ_CAPACITY:
3828 if (s->cNotifiedMediaChange > 0)
3829 {
3830 s->cNotifiedMediaChange-- ;
3831 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3832 break;
3833 }
3834 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3835 {
3836 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3837 break;
3838 }
3839 ataR3StartTransfer(pDevIns, pCtl, s, 8, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_CAPACITY, true);
3840 break;
3841 case SCSI_READ_DISC_INFORMATION:
3842 if (s->cNotifiedMediaChange > 0)
3843 {
3844 s->cNotifiedMediaChange-- ;
3845 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3846 break;
3847 }
3848 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3849 {
3850 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3851 break;
3852 }
3853 cbMax = scsiBE2H_U16(pbPacket + 7);
3854 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 34), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_DISC_INFORMATION, true);
3855 break;
3856 case SCSI_READ_TRACK_INFORMATION:
3857 if (s->cNotifiedMediaChange > 0)
3858 {
3859 s->cNotifiedMediaChange-- ;
3860 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
3861 break;
3862 }
3863 else if (!pDevR3->pDrvMount->pfnIsMounted(pDevR3->pDrvMount))
3864 {
3865 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
3866 break;
3867 }
3868 cbMax = scsiBE2H_U16(pbPacket + 7);
3869 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 36), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION, true);
3870 break;
3871 case SCSI_GET_CONFIGURATION:
3872 /* No media change stuff here, it can confuse Linux guests. */
3873 cbMax = scsiBE2H_U16(pbPacket + 7);
3874 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 80), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_CONFIGURATION, true);
3875 break;
3876 case SCSI_INQUIRY:
3877 cbMax = scsiBE2H_U16(pbPacket + 3);
3878 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 36), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_INQUIRY, true);
3879 break;
3880 case SCSI_READ_DVD_STRUCTURE:
3881 {
3882 cbMax = scsiBE2H_U16(pbPacket + 8);
3883 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbMax, 4), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_DVD_STRUCTURE, true);
3884 break;
3885 }
3886 default:
3887 atapiR3CmdErrorSimple(pCtl, s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
3888 break;
3889 }
3890}
3891
3892
3893/*
3894 * Parse ATAPI commands, passing them directly to the CD/DVD drive.
3895 */
3896static void atapiR3ParseCmdPassthrough(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3897{
3898 const uint8_t *pbPacket = &s->abATAPICmd[0];
3899
3900 /* Some cases we have to handle here. */
3901 if ( pbPacket[0] == SCSI_GET_EVENT_STATUS_NOTIFICATION
3902 && ASMAtomicReadU32(&s->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
3903 {
3904 uint32_t cbTransfer = scsiBE2H_U16(pbPacket + 7);
3905 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(cbTransfer, 8), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
3906 }
3907 else if ( pbPacket[0] == SCSI_REQUEST_SENSE
3908 && (s->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
3909 ataR3StartTransfer(pDevIns, pCtl, s, RT_MIN(pbPacket[4], 18), PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
3910 else
3911 {
3912 size_t cbBuf = 0;
3913 size_t cbATAPISector = 0;
3914 size_t cbTransfer = 0;
3915 PDMMEDIATXDIR uTxDir = PDMMEDIATXDIR_NONE;
3916 uint8_t u8ScsiSts = SCSI_STATUS_OK;
3917
3918 if (pbPacket[0] == SCSI_FORMAT_UNIT || pbPacket[0] == SCSI_GET_PERFORMANCE)
3919 cbBuf = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */
3920
3921 bool fPassthrough = ATAPIPassthroughParseCdb(pbPacket, sizeof(s->abATAPICmd), cbBuf, pDevR3->pTrackList,
3922 &s->abATAPISense[0], sizeof(s->abATAPISense), &uTxDir, &cbTransfer,
3923 &cbATAPISector, &u8ScsiSts);
3924 if (fPassthrough)
3925 {
3926 s->cbATAPISector = (uint32_t)cbATAPISector;
3927 Assert(s->cbATAPISector == (uint32_t)cbATAPISector);
3928 Assert(cbTransfer == (uint32_t)cbTransfer);
3929
3930 /*
3931 * Send a command to the drive, passing data in/out as required.
3932 * Commands which exceed the I/O buffer size are split below
3933 * or aborted if splitting is not implemented.
3934 */
3935 Log2(("ATAPI PT: max size %d\n", cbTransfer));
3936 if (cbTransfer == 0)
3937 uTxDir = PDMMEDIATXDIR_NONE;
3938 ataR3StartTransfer(pDevIns, pCtl, s, (uint32_t)cbTransfer, uTxDir, ATAFN_BT_ATAPI_PASSTHROUGH_CMD, ATAFN_SS_ATAPI_PASSTHROUGH, true);
3939 }
3940 else if (u8ScsiSts == SCSI_STATUS_CHECK_CONDITION)
3941 {
3942 /* Sense data is already set, end the request and notify the guest. */
3943 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, s->abATAPISense[2] & 0x0f, SCSISenseText(s->abATAPISense[2] & 0x0f),
3944 s->abATAPISense[12], s->abATAPISense[13], SCSISenseExtText(s->abATAPISense[12], s->abATAPISense[13])));
3945 s->uATARegError = s->abATAPISense[2] << 4;
3946 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_ERR);
3947 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
3948 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
3949 s->cbTotalTransfer = 0;
3950 s->cbElementaryTransfer = 0;
3951 s->cbAtapiPassthroughTransfer = 0;
3952 s->iIOBufferCur = 0;
3953 s->iIOBufferEnd = 0;
3954 s->uTxDir = PDMMEDIATXDIR_NONE;
3955 s->iBeginTransfer = ATAFN_BT_NULL;
3956 s->iSourceSink = ATAFN_SS_NULL;
3957 }
3958 else if (u8ScsiSts == SCSI_STATUS_OK)
3959 atapiR3CmdOK(pCtl, s);
3960 }
3961}
3962
3963
3964static void atapiR3ParseCmd(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3965{
3966 const uint8_t *pbPacket;
3967
3968 pbPacket = s->abATAPICmd;
3969# ifdef DEBUG
3970 Log(("%s: LUN#%d DMA=%d CMD=%#04x \"%s\"\n", __FUNCTION__, s->iLUN, s->fDMA, pbPacket[0], SCSICmdText(pbPacket[0])));
3971# else /* !DEBUG */
3972 Log(("%s: LUN#%d DMA=%d CMD=%#04x\n", __FUNCTION__, s->iLUN, s->fDMA, pbPacket[0]));
3973# endif /* !DEBUG */
3974 Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, s->uATARegLCyl | (s->uATARegHCyl << 8), ATAPI_PACKET_SIZE, pbPacket));
3975
3976 if (s->fATAPIPassthrough)
3977 atapiR3ParseCmdPassthrough(pDevIns, pCtl, s, pDevR3);
3978 else
3979 atapiR3ParseCmdVirtualATAPI(pDevIns, pCtl, s, pDevR3);
3980}
3981
3982
3983/**
3984 * Sink/Source: PACKET
3985 */
3986static bool ataR3PacketSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
3987{
3988 s->fDMA = !!(s->uATARegFeature & 1);
3989 memcpy(s->abATAPICmd, s->abIOBuffer, ATAPI_PACKET_SIZE);
3990 s->uTxDir = PDMMEDIATXDIR_NONE;
3991 s->cbTotalTransfer = 0;
3992 s->cbElementaryTransfer = 0;
3993 s->cbAtapiPassthroughTransfer = 0;
3994 atapiR3ParseCmd(pDevIns, pCtl, s, pDevR3);
3995 return false;
3996}
3997
3998
3999/**
4000 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium removed" event
4001 * from now on, regardless if there was a medium inserted or not.
4002 */
4003static void ataR3MediumRemoved(PATADEVSTATE s)
4004{
4005 ASMAtomicWriteU32(&s->MediaEventStatus, ATA_EVENT_STATUS_MEDIA_REMOVED);
4006}
4007
4008
4009/**
4010 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium inserted". If
4011 * there was already a medium inserted, don't forget to send the "medium
4012 * removed" event first.
4013 */
4014static void ataR3MediumInserted(PATADEVSTATE s)
4015{
4016 uint32_t OldStatus, NewStatus;
4017 do
4018 {
4019 OldStatus = ASMAtomicReadU32(&s->MediaEventStatus);
4020 switch (OldStatus)
4021 {
4022 case ATA_EVENT_STATUS_MEDIA_CHANGED:
4023 case ATA_EVENT_STATUS_MEDIA_REMOVED:
4024 /* no change, we will send "medium removed" + "medium inserted" */
4025 NewStatus = ATA_EVENT_STATUS_MEDIA_CHANGED;
4026 break;
4027 default:
4028 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW;
4029 break;
4030 }
4031 } while (!ASMAtomicCmpXchgU32(&s->MediaEventStatus, NewStatus, OldStatus));
4032}
4033
4034
4035/**
4036 * @interface_method_impl{PDMIMOUNTNOTIFY,pfnMountNotify}
4037 */
4038static DECLCALLBACK(void) ataR3MountNotify(PPDMIMOUNTNOTIFY pInterface)
4039{
4040 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IMountNotify);
4041 PATASTATE pThis = PDMDEVINS_2_DATA(pIfR3->pDevIns, PATASTATE);
4042 PATADEVSTATE pIf = &RT_SAFE_SUBSCRIPT(RT_SAFE_SUBSCRIPT(pThis->aCts, pIfR3->iCtl).aIfs, pIfR3->iDev);
4043 Log(("%s: changing LUN#%d\n", __FUNCTION__, pIfR3->iLUN));
4044
4045 /* Ignore the call if we're called while being attached. */
4046 if (!pIfR3->pDrvMedia)
4047 return;
4048
4049 uint32_t cRegions = pIfR3->pDrvMedia->pfnGetRegionCount(pIfR3->pDrvMedia);
4050 for (uint32_t i = 0; i < cRegions; i++)
4051 {
4052 uint64_t cBlocks = 0;
4053 int rc = pIfR3->pDrvMedia->pfnQueryRegionProperties(pIfR3->pDrvMedia, i, NULL, &cBlocks,
4054 NULL, NULL);
4055 AssertRC(rc);
4056 pIf->cTotalSectors += cBlocks;
4057 }
4058
4059 LogRel(("PIIX3 ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors));
4060
4061 /* Report media changed in TEST UNIT and other (probably incorrect) places. */
4062 if (pIf->cNotifiedMediaChange < 2)
4063 pIf->cNotifiedMediaChange = 1;
4064 ataR3MediumInserted(pIf);
4065 ataR3MediumTypeSet(pIf, ATA_MEDIA_TYPE_UNKNOWN);
4066}
4067
4068/**
4069 * @interface_method_impl{PDMIMOUNTNOTIFY,pfnUnmountNotify}
4070 */
4071static DECLCALLBACK(void) ataR3UnmountNotify(PPDMIMOUNTNOTIFY pInterface)
4072{
4073 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IMountNotify);
4074 PATASTATE pThis = PDMDEVINS_2_DATA(pIfR3->pDevIns, PATASTATE);
4075 PATADEVSTATE pIf = &RT_SAFE_SUBSCRIPT(RT_SAFE_SUBSCRIPT(pThis->aCts, pIfR3->iCtl).aIfs, pIfR3->iDev);
4076 Log(("%s:\n", __FUNCTION__));
4077 pIf->cTotalSectors = 0;
4078
4079 /*
4080 * Whatever I do, XP will not use the GET MEDIA STATUS nor the EVENT stuff.
4081 * However, it will respond to TEST UNIT with a 0x6 0x28 (media changed) sense code.
4082 * So, we'll give it 4 TEST UNIT command to catch up, two which the media is not
4083 * present and 2 in which it is changed.
4084 */
4085 pIf->cNotifiedMediaChange = 1;
4086 ataR3MediumRemoved(pIf);
4087 ataR3MediumTypeSet(pIf, ATA_MEDIA_NO_DISC);
4088}
4089
4090/**
4091 * Begin Transfer: PACKET
4092 */
4093static void ataR3PacketBT(PATACONTROLLER pCtl, PATADEVSTATE s)
4094{
4095 s->cbElementaryTransfer = s->cbTotalTransfer;
4096 s->cbAtapiPassthroughTransfer = s->cbTotalTransfer;
4097 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_CD;
4098 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
4099 ataSetStatusValue(pCtl, s, ATA_STAT_READY);
4100}
4101
4102
4103static void ataR3ResetDevice(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
4104{
4105 LogFlowFunc(("\n"));
4106 s->cMultSectors = ATA_MAX_MULT_SECTORS;
4107 s->cNotifiedMediaChange = 0;
4108 ASMAtomicWriteU32(&s->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED);
4109 ASMAtomicWriteU32(&s->MediaTrackType, ATA_MEDIA_TYPE_UNKNOWN);
4110 ataUnsetIRQ(pDevIns, pCtl, s);
4111
4112 s->uATARegSelect = 0x20;
4113 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_SEEK);
4114 ataR3SetSignature(s);
4115 s->cbTotalTransfer = 0;
4116 s->cbElementaryTransfer = 0;
4117 s->cbAtapiPassthroughTransfer = 0;
4118 s->iIOBufferPIODataStart = 0;
4119 s->iIOBufferPIODataEnd = 0;
4120 s->iBeginTransfer = ATAFN_BT_NULL;
4121 s->iSourceSink = ATAFN_SS_NULL;
4122 s->fDMA = false;
4123 s->fATAPITransfer = false;
4124 s->uATATransferMode = ATA_MODE_UDMA | 2; /* PIIX3 supports only up to UDMA2 */
4125
4126 s->XCHSGeometry = s->PCHSGeometry; /* Restore default CHS translation. */
4127
4128 s->uATARegFeature = 0;
4129}
4130
4131
4132static void ataR3DeviceDiag(PATACONTROLLER pCtl, PATADEVSTATE s)
4133{
4134 ataR3SetSignature(s);
4135 if (s->fATAPI)
4136 ataSetStatusValue(pCtl, s, 0); /* NOTE: READY is _not_ set */
4137 else
4138 ataSetStatusValue(pCtl, s, ATA_STAT_READY | ATA_STAT_SEEK);
4139 s->uATARegError = 0x01;
4140}
4141
4142
4143/**
4144 * Sink/Source: EXECUTE DEVICE DIAGNOTIC
4145 */
4146static bool ataR3ExecuteDeviceDiagnosticSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4147{
4148 RT_NOREF(pDevIns, s, pDevR3);
4149
4150 /* EXECUTE DEVICE DIAGNOSTIC is a very special command which always
4151 * gets executed, regardless of which device is selected. As a side
4152 * effect, it always completes with device 0 selected.
4153 */
4154 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
4155 ataR3DeviceDiag(pCtl, &pCtl->aIfs[i]);
4156
4157 LogRel(("ATA: LUN#%d: EXECUTE DEVICE DIAGNOSTIC, status %02X\n", s->iLUN, s->uATARegStatus));
4158 pCtl->iSelectedIf = 0;
4159
4160 return false;
4161}
4162
4163
4164/**
4165 * Sink/Source: INITIALIZE DEVICE PARAMETERS
4166 */
4167static bool ataR3InitDevParmSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4168{
4169 RT_NOREF(pDevR3);
4170 LogFlowFunc(("\n"));
4171
4172 /* Technical Note:
4173 * On ST506 type drives with a separate controller, the INITIALIZE DRIVE PARAMETERS command was
4174 * required to inform the controller of drive geometry. The controller needed to know the
4175 * number of heads and sectors per track so that it could correctly advance to the next track
4176 * or cylinder when executing multi-sector commands. Setting a geometry that didn't match the
4177 * drive made very little sense because sectors had fixed CHS addresses. It was at best
4178 * possible to reduce the drive's capacity by limiting the number of heads and/or sectors
4179 * per track.
4180 *
4181 * IDE drives inherently have to know their true geometry, but most of them also support
4182 * programmable translation that can be set through the INITIALIZE DEVICE PARAMETERS command.
4183 * In fact most older IDE drives typically weren't operated using their default (native) geometry,
4184 * and with newer IDE drives that's not even an option.
4185 *
4186 * Up to and including ATA-5, the standard defined a CHS to LBA translation (since ATA-6, CHS
4187 * support is optional):
4188 *
4189 * LBA = (((cyl_num * heads_per_cyl) + head_num) * sectors_per_track) + sector_num - 1
4190 *
4191 * The INITIALIZE DEVICE PARAMETERS command sets the heads_per_cyl and sectors_per_track
4192 * values used in the above formula.
4193 *
4194 * Drives must obviously support an INITIALIZE DRIVE PARAMETERS command matching the drive's
4195 * default CHS translation. Everything else is optional.
4196 *
4197 * We support any geometry with non-zero sectors per track because there's no reason not to;
4198 * this behavior is common in many if not most IDE drives.
4199 */
4200
4201 PDMMEDIAGEOMETRY Geom = { 0 };
4202
4203 Geom.cHeads = (s->uATARegSelect & 0x0f) + 1; /* Effective range 1-16. */
4204 Geom.cSectors = s->uATARegNSector; /* Range 0-255, zero is not valid. */
4205
4206 if (Geom.cSectors)
4207 {
4208 uint64_t cCylinders = s->cTotalSectors / (Geom.cHeads * Geom.cSectors);
4209 Geom.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
4210
4211 s->XCHSGeometry = Geom;
4212
4213 ataR3LockLeave(pDevIns, pCtl);
4214 LogRel(("ATA: LUN#%d: INITIALIZE DEVICE PARAMETERS: %u sectors per track, %u heads\n",
4215 s->iLUN, s->uATARegNSector, (s->uATARegSelect & 0x0f) + 1));
4216 RTThreadSleep(pCtl->msDelayIRQ);
4217 ataR3LockEnter(pDevIns, pCtl);
4218 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4219 }
4220 else
4221 {
4222 ataR3LockLeave(pDevIns, pCtl);
4223 LogRel(("ATA: LUN#%d: INITIALIZE DEVICE PARAMETERS error (zero sectors per track)!\n", s->iLUN));
4224 RTThreadSleep(pCtl->msDelayIRQ);
4225 ataR3LockEnter(pDevIns, pCtl);
4226 ataR3CmdError(pCtl, s, ABRT_ERR);
4227 }
4228 return false;
4229}
4230
4231
4232/**
4233 * Sink/Source: RECALIBRATE
4234 */
4235static bool ataR3RecalibrateSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4236{
4237 RT_NOREF(pDevR3);
4238 LogFlowFunc(("\n"));
4239 ataR3LockLeave(pDevIns, pCtl);
4240 RTThreadSleep(pCtl->msDelayIRQ);
4241 ataR3LockEnter(pDevIns, pCtl);
4242 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4243 return false;
4244}
4245
4246
4247static int ataR3TrimSectors(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3,
4248 uint64_t u64Sector, uint32_t cSectors, bool *pfRedo)
4249{
4250 RTRANGE TrimRange;
4251 int rc;
4252
4253 ataR3LockLeave(pDevIns, pCtl);
4254
4255 TrimRange.offStart = u64Sector * s->cbSector;
4256 TrimRange.cbRange = cSectors * s->cbSector;
4257
4258 s->Led.Asserted.s.fWriting = s->Led.Actual.s.fWriting = 1;
4259 rc = pDevR3->pDrvMedia->pfnDiscard(pDevR3->pDrvMedia, &TrimRange, 1);
4260 s->Led.Actual.s.fWriting = 0;
4261
4262 if (RT_SUCCESS(rc))
4263 *pfRedo = false;
4264 else
4265 *pfRedo = ataR3IsRedoSetWarning(pDevIns, pCtl, rc);
4266
4267 ataR3LockEnter(pDevIns, pCtl);
4268 return rc;
4269}
4270
4271
4272/**
4273 * Sink/Source: TRIM
4274 */
4275static bool ataR3TrimSS(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3)
4276{
4277 int rc = VERR_GENERAL_FAILURE;
4278 uint32_t cRangesMax;
4279 uint64_t *pu64Range = (uint64_t *)&s->abIOBuffer[0];
4280 bool fRedo = false;
4281
4282 cRangesMax = RT_MIN(s->cbElementaryTransfer, sizeof(s->abIOBuffer)) / sizeof(uint64_t);
4283 Assert(cRangesMax);
4284
4285 while (cRangesMax-- > 0)
4286 {
4287 if (ATA_RANGE_LENGTH_GET(*pu64Range) == 0)
4288 break;
4289
4290 rc = ataR3TrimSectors(pDevIns, pCtl, s, pDevR3, *pu64Range & ATA_RANGE_LBA_MASK,
4291 ATA_RANGE_LENGTH_GET(*pu64Range), &fRedo);
4292 if (RT_FAILURE(rc))
4293 break;
4294
4295 pu64Range++;
4296 }
4297
4298 if (RT_SUCCESS(rc))
4299 {
4300 s->iSourceSink = ATAFN_SS_NULL;
4301 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4302 }
4303 else
4304 {
4305 if (fRedo)
4306 return fRedo;
4307 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
4308 LogRel(("PIIX3 ATA: LUN#%d: disk trim error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
4309 s->iLUN, rc, *pu64Range & ATA_RANGE_LBA_MASK, ATA_RANGE_LENGTH_GET(*pu64Range)));
4310
4311 /*
4312 * Check if we got interrupted. We don't need to set status variables
4313 * because the request was aborted.
4314 */
4315 if (rc != VERR_INTERRUPTED)
4316 ataR3CmdError(pCtl, s, ID_ERR);
4317 }
4318
4319 return false;
4320}
4321
4322
4323static void ataR3ParseCmd(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s, PATADEVSTATER3 pDevR3, uint8_t cmd)
4324{
4325# ifdef DEBUG
4326 Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, s->iLUN, cmd, ATACmdText(cmd)));
4327# else /* !DEBUG */
4328 Log(("%s: LUN#%d CMD=%#04x\n", __FUNCTION__, s->iLUN, cmd));
4329# endif /* !DEBUG */
4330 s->fLBA48 = false;
4331 s->fDMA = false;
4332 if (cmd == ATA_IDLE_IMMEDIATE)
4333 {
4334 /* Detect Linux timeout recovery, first tries IDLE IMMEDIATE (which
4335 * would overwrite the failing command unfortunately), then RESET. */
4336 int32_t uCmdWait = -1;
4337 uint64_t uNow = RTTimeNanoTS();
4338 if (s->u64CmdTS)
4339 uCmdWait = (uNow - s->u64CmdTS) / 1000;
4340 LogRel(("PIIX3 ATA: LUN#%d: IDLE IMMEDIATE, CmdIf=%#04x (%d usec ago)\n",
4341 s->iLUN, s->uATARegCommand, uCmdWait));
4342 }
4343 s->uATARegCommand = cmd;
4344 switch (cmd)
4345 {
4346 case ATA_IDENTIFY_DEVICE:
4347 if (pDevR3->pDrvMedia && !s->fATAPI)
4348 ataR3StartTransfer(pDevIns, pCtl, s, 512, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_NULL, ATAFN_SS_IDENTIFY, false);
4349 else
4350 {
4351 if (s->fATAPI)
4352 ataR3SetSignature(s);
4353 ataR3CmdError(pCtl, s, ABRT_ERR);
4354 ataUnsetStatus(pCtl, s, ATA_STAT_READY);
4355 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4356 }
4357 break;
4358 case ATA_RECALIBRATE:
4359 if (s->fATAPI)
4360 goto abort_cmd;
4361 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_RECALIBRATE, false);
4362 break;
4363 case ATA_INITIALIZE_DEVICE_PARAMETERS:
4364 if (s->fATAPI)
4365 goto abort_cmd;
4366 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_INITIALIZE_DEVICE_PARAMETERS, false);
4367 break;
4368 case ATA_SET_MULTIPLE_MODE:
4369 if ( s->uATARegNSector != 0
4370 && ( s->uATARegNSector > ATA_MAX_MULT_SECTORS
4371 || (s->uATARegNSector & (s->uATARegNSector - 1)) != 0))
4372 {
4373 ataR3CmdError(pCtl, s, ABRT_ERR);
4374 }
4375 else
4376 {
4377 Log2(("%s: set multi sector count to %d\n", __FUNCTION__, s->uATARegNSector));
4378 s->cMultSectors = s->uATARegNSector;
4379 ataR3CmdOK(pCtl, s, 0);
4380 }
4381 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4382 break;
4383 case ATA_READ_VERIFY_SECTORS_EXT:
4384 s->fLBA48 = true;
4385 RT_FALL_THRU();
4386 case ATA_READ_VERIFY_SECTORS:
4387 case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES:
4388 /* do sector number check ? */
4389 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4390 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4391 break;
4392 case ATA_READ_SECTORS_EXT:
4393 s->fLBA48 = true;
4394 RT_FALL_THRU();
4395 case ATA_READ_SECTORS:
4396 case ATA_READ_SECTORS_WITHOUT_RETRIES:
4397 if (!pDevR3->pDrvMedia || s->fATAPI)
4398 goto abort_cmd;
4399 s->cSectorsPerIRQ = 1;
4400 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
4401 break;
4402 case ATA_WRITE_SECTORS_EXT:
4403 s->fLBA48 = true;
4404 RT_FALL_THRU();
4405 case ATA_WRITE_SECTORS:
4406 case ATA_WRITE_SECTORS_WITHOUT_RETRIES:
4407 if (!pDevR3->pDrvMedia || s->fATAPI)
4408 goto abort_cmd;
4409 s->cSectorsPerIRQ = 1;
4410 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
4411 break;
4412 case ATA_READ_MULTIPLE_EXT:
4413 s->fLBA48 = true;
4414 RT_FALL_THRU();
4415 case ATA_READ_MULTIPLE:
4416 if (!pDevR3->pDrvMedia || !s->cMultSectors || s->fATAPI)
4417 goto abort_cmd;
4418 s->cSectorsPerIRQ = s->cMultSectors;
4419 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
4420 break;
4421 case ATA_WRITE_MULTIPLE_EXT:
4422 s->fLBA48 = true;
4423 RT_FALL_THRU();
4424 case ATA_WRITE_MULTIPLE:
4425 if (!pDevR3->pDrvMedia || !s->cMultSectors || s->fATAPI)
4426 goto abort_cmd;
4427 s->cSectorsPerIRQ = s->cMultSectors;
4428 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
4429 break;
4430 case ATA_READ_DMA_EXT:
4431 s->fLBA48 = true;
4432 RT_FALL_THRU();
4433 case ATA_READ_DMA:
4434 case ATA_READ_DMA_WITHOUT_RETRIES:
4435 if (!pDevR3->pDrvMedia || s->fATAPI)
4436 goto abort_cmd;
4437 s->cSectorsPerIRQ = ATA_MAX_MULT_SECTORS;
4438 s->fDMA = true;
4439 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
4440 break;
4441 case ATA_WRITE_DMA_EXT:
4442 s->fLBA48 = true;
4443 RT_FALL_THRU();
4444 case ATA_WRITE_DMA:
4445 case ATA_WRITE_DMA_WITHOUT_RETRIES:
4446 if (!pDevR3->pDrvMedia || s->fATAPI)
4447 goto abort_cmd;
4448 s->cSectorsPerIRQ = ATA_MAX_MULT_SECTORS;
4449 s->fDMA = true;
4450 ataR3StartTransfer(pDevIns, pCtl, s, ataR3GetNSectors(s) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
4451 break;
4452 case ATA_READ_NATIVE_MAX_ADDRESS_EXT:
4453 if (!pDevR3->pDrvMedia || s->fATAPI)
4454 goto abort_cmd;
4455 s->fLBA48 = true;
4456 ataR3SetSector(s, s->cTotalSectors - 1);
4457 ataR3CmdOK(pCtl, s, 0);
4458 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4459 break;
4460 case ATA_SEEK: /* Used by the SCO OpenServer. Command is marked as obsolete */
4461 ataR3CmdOK(pCtl, s, 0);
4462 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4463 break;
4464 case ATA_READ_NATIVE_MAX_ADDRESS:
4465 if (!pDevR3->pDrvMedia || s->fATAPI)
4466 goto abort_cmd;
4467 ataR3SetSector(s, RT_MIN(s->cTotalSectors, 1 << 28) - 1);
4468 ataR3CmdOK(pCtl, s, 0);
4469 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4470 break;
4471 case ATA_CHECK_POWER_MODE:
4472 s->uATARegNSector = 0xff; /* drive active or idle */
4473 ataR3CmdOK(pCtl, s, 0);
4474 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4475 break;
4476 case ATA_SET_FEATURES:
4477 Log2(("%s: feature=%#x\n", __FUNCTION__, s->uATARegFeature));
4478 if (!pDevR3->pDrvMedia)
4479 goto abort_cmd;
4480 switch (s->uATARegFeature)
4481 {
4482 case 0x02: /* write cache enable */
4483 Log2(("%s: write cache enable\n", __FUNCTION__));
4484 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4485 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4486 break;
4487 case 0xaa: /* read look-ahead enable */
4488 Log2(("%s: read look-ahead enable\n", __FUNCTION__));
4489 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4490 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4491 break;
4492 case 0x55: /* read look-ahead disable */
4493 Log2(("%s: read look-ahead disable\n", __FUNCTION__));
4494 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4495 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4496 break;
4497 case 0xcc: /* reverting to power-on defaults enable */
4498 Log2(("%s: revert to power-on defaults enable\n", __FUNCTION__));
4499 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4500 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4501 break;
4502 case 0x66: /* reverting to power-on defaults disable */
4503 Log2(("%s: revert to power-on defaults disable\n", __FUNCTION__));
4504 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4505 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4506 break;
4507 case 0x82: /* write cache disable */
4508 Log2(("%s: write cache disable\n", __FUNCTION__));
4509 /* As per the ATA/ATAPI-6 specs, a write cache disable
4510 * command MUST flush the write buffers to disc. */
4511 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_FLUSH, false);
4512 break;
4513 case 0x03: { /* set transfer mode */
4514 Log2(("%s: transfer mode %#04x\n", __FUNCTION__, s->uATARegNSector));
4515 switch (s->uATARegNSector & 0xf8)
4516 {
4517 case 0x00: /* PIO default */
4518 case 0x08: /* PIO mode */
4519 break;
4520 case ATA_MODE_MDMA: /* MDMA mode */
4521 s->uATATransferMode = (s->uATARegNSector & 0xf8) | RT_MIN(s->uATARegNSector & 0x07, ATA_MDMA_MODE_MAX);
4522 break;
4523 case ATA_MODE_UDMA: /* UDMA mode */
4524 s->uATATransferMode = (s->uATARegNSector & 0xf8) | RT_MIN(s->uATARegNSector & 0x07, ATA_UDMA_MODE_MAX);
4525 break;
4526 default:
4527 goto abort_cmd;
4528 }
4529 ataR3CmdOK(pCtl, s, ATA_STAT_SEEK);
4530 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4531 break;
4532 }
4533 default:
4534 goto abort_cmd;
4535 }
4536 /*
4537 * OS/2 workarond:
4538 * The OS/2 IDE driver from MCP2 appears to rely on the feature register being
4539 * reset here. According to the specification, this is a driver bug as the register
4540 * contents are undefined after the call. This means we can just as well reset it.
4541 */
4542 s->uATARegFeature = 0;
4543 break;
4544 case ATA_FLUSH_CACHE_EXT:
4545 case ATA_FLUSH_CACHE:
4546 if (!pDevR3->pDrvMedia || s->fATAPI)
4547 goto abort_cmd;
4548 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_FLUSH, false);
4549 break;
4550 case ATA_STANDBY_IMMEDIATE:
4551 ataR3CmdOK(pCtl, s, 0);
4552 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4553 break;
4554 case ATA_IDLE_IMMEDIATE:
4555 LogRel(("PIIX3 ATA: LUN#%d: aborting current command\n", s->iLUN));
4556 ataR3AbortCurrentCommand(pDevIns, pCtl, s, false);
4557 break;
4558 case ATA_SLEEP:
4559 ataR3CmdOK(pCtl, s, 0);
4560 ataHCSetIRQ(pDevIns, pCtl, s);
4561 break;
4562 /* ATAPI commands */
4563 case ATA_IDENTIFY_PACKET_DEVICE:
4564 if (s->fATAPI)
4565 ataR3StartTransfer(pDevIns, pCtl, s, 512, PDMMEDIATXDIR_FROM_DEVICE, ATAFN_BT_NULL, ATAFN_SS_ATAPI_IDENTIFY, false);
4566 else
4567 {
4568 ataR3CmdError(pCtl, s, ABRT_ERR);
4569 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4570 }
4571 break;
4572 case ATA_EXECUTE_DEVICE_DIAGNOSTIC:
4573 ataR3StartTransfer(pDevIns, pCtl, s, 0, PDMMEDIATXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC, false);
4574 break;
4575 case ATA_DEVICE_RESET:
4576 if (!s->fATAPI)
4577 goto abort_cmd;
4578 LogRel(("PIIX3 ATA: LUN#%d: performing device RESET\n", s->iLUN));
4579 ataR3AbortCurrentCommand(pDevIns, pCtl, s, true);
4580 break;
4581 case ATA_PACKET:
4582 if (!s->fATAPI)
4583 goto abort_cmd;
4584 /* overlapping commands not supported */
4585 if (s->uATARegFeature & 0x02)
4586 goto abort_cmd;
4587 ataR3StartTransfer(pDevIns, pCtl, s, ATAPI_PACKET_SIZE, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_PACKET, ATAFN_SS_PACKET, false);
4588 break;
4589 case ATA_DATA_SET_MANAGEMENT:
4590 if (!pDevR3->pDrvMedia || !pDevR3->pDrvMedia->pfnDiscard)
4591 goto abort_cmd;
4592 if ( !(s->uATARegFeature & UINT8_C(0x01))
4593 || (s->uATARegFeature & ~UINT8_C(0x01)))
4594 goto abort_cmd;
4595 s->fDMA = true;
4596 ataR3StartTransfer(pDevIns, pCtl, s, (s->uATARegNSectorHOB << 8 | s->uATARegNSector) * s->cbSector, PDMMEDIATXDIR_TO_DEVICE, ATAFN_BT_NULL, ATAFN_SS_TRIM, false);
4597 break;
4598 default:
4599 abort_cmd:
4600 ataR3CmdError(pCtl, s, ABRT_ERR);
4601 if (s->fATAPI)
4602 ataUnsetStatus(pCtl, s, ATA_STAT_READY);
4603 ataHCSetIRQ(pDevIns, pCtl, s); /* Shortcut, do not use AIO thread. */
4604 break;
4605 }
4606}
4607
4608# endif /* IN_RING3 */
4609#endif /* IN_RING0 || IN_RING3 */
4610
4611/*
4612 * Note: There are four distinct cases of port I/O handling depending on
4613 * which devices (if any) are attached to an IDE channel:
4614 *
4615 * 1) No device attached. No response to writes or reads (i.e. reads return
4616 * all bits set).
4617 *
4618 * 2) Both devices attached. Reads and writes are processed normally.
4619 *
4620 * 3) Device 0 only. If device 0 is selected, normal behavior applies. But
4621 * if Device 1 is selected, writes are still directed to Device 0 (except
4622 * commands are not executed), reads from control/command registers are
4623 * directed to Device 0, but status/alt status reads return 0. If Device 1
4624 * is a PACKET device, all reads return 0. See ATAPI-6 clause 9.16.1 and
4625 * Table 18 in clause 7.1.
4626 *
4627 * 4) Device 1 only - non-standard(!). Device 1 can't tell if Device 0 is
4628 * present or not and behaves the same. That means if Device 0 is selected,
4629 * Device 1 responds to writes (except commands are not executed) but does
4630 * not respond to reads. If Device 1 selected, normal behavior applies.
4631 * See ATAPI-6 clause 9.16.2 and Table 15 in clause 7.1.
4632 */
4633
4634static VBOXSTRICTRC ataIOPortWriteU8(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t addr, uint32_t val, uintptr_t iCtl)
4635{
4636 RT_NOREF(iCtl);
4637 Log2(("%s: LUN#%d write addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN, addr, val));
4638 addr &= 7;
4639 switch (addr)
4640 {
4641 case 0:
4642 break;
4643 case 1: /* feature register */
4644 /* NOTE: data is written to the two drives */
4645 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4646 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4647 pCtl->aIfs[0].uATARegFeatureHOB = pCtl->aIfs[0].uATARegFeature;
4648 pCtl->aIfs[1].uATARegFeatureHOB = pCtl->aIfs[1].uATARegFeature;
4649 pCtl->aIfs[0].uATARegFeature = val;
4650 pCtl->aIfs[1].uATARegFeature = val;
4651 break;
4652 case 2: /* sector count */
4653 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4654 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4655 pCtl->aIfs[0].uATARegNSectorHOB = pCtl->aIfs[0].uATARegNSector;
4656 pCtl->aIfs[1].uATARegNSectorHOB = pCtl->aIfs[1].uATARegNSector;
4657 pCtl->aIfs[0].uATARegNSector = val;
4658 pCtl->aIfs[1].uATARegNSector = val;
4659 break;
4660 case 3: /* sector number */
4661 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4662 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4663 pCtl->aIfs[0].uATARegSectorHOB = pCtl->aIfs[0].uATARegSector;
4664 pCtl->aIfs[1].uATARegSectorHOB = pCtl->aIfs[1].uATARegSector;
4665 pCtl->aIfs[0].uATARegSector = val;
4666 pCtl->aIfs[1].uATARegSector = val;
4667 break;
4668 case 4: /* cylinder low */
4669 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4670 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4671 pCtl->aIfs[0].uATARegLCylHOB = pCtl->aIfs[0].uATARegLCyl;
4672 pCtl->aIfs[1].uATARegLCylHOB = pCtl->aIfs[1].uATARegLCyl;
4673 pCtl->aIfs[0].uATARegLCyl = val;
4674 pCtl->aIfs[1].uATARegLCyl = val;
4675 break;
4676 case 5: /* cylinder high */
4677 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4678 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
4679 pCtl->aIfs[0].uATARegHCylHOB = pCtl->aIfs[0].uATARegHCyl;
4680 pCtl->aIfs[1].uATARegHCylHOB = pCtl->aIfs[1].uATARegHCyl;
4681 pCtl->aIfs[0].uATARegHCyl = val;
4682 pCtl->aIfs[1].uATARegHCyl = val;
4683 break;
4684 case 6: /* drive/head */
4685 pCtl->aIfs[0].uATARegSelect = (val & ~0x10) | 0xa0;
4686 pCtl->aIfs[1].uATARegSelect = (val | 0x10) | 0xa0;
4687 if (((val >> 4) & ATA_SELECTED_IF_MASK) != pCtl->iSelectedIf)
4688 {
4689 /* select another drive */
4690 uintptr_t const iSelectedIf = (val >> 4) & ATA_SELECTED_IF_MASK;
4691 pCtl->iSelectedIf = (uint8_t)iSelectedIf;
4692 /* The IRQ line is multiplexed between the two drives, so
4693 * update the state when switching to another drive. Only need
4694 * to update interrupt line if it is enabled and there is a
4695 * state change. */
4696 if ( !(pCtl->aIfs[iSelectedIf].uATARegDevCtl & ATA_DEVCTL_DISABLE_IRQ)
4697 && pCtl->aIfs[iSelectedIf].fIrqPending != pCtl->aIfs[iSelectedIf ^ 1].fIrqPending)
4698 {
4699 if (pCtl->aIfs[iSelectedIf].fIrqPending)
4700 {
4701 Log2(("%s: LUN#%d asserting IRQ (drive select change)\n", __FUNCTION__, pCtl->aIfs[iSelectedIf].iLUN));
4702 /* The BMDMA unit unconditionally sets BM_STATUS_INT if
4703 * the interrupt line is asserted. It monitors the line
4704 * for a rising edge. */
4705 pCtl->BmDma.u8Status |= BM_STATUS_INT;
4706 if (pCtl->irq == 16)
4707 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
4708 else
4709 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 1);
4710 }
4711 else
4712 {
4713 Log2(("%s: LUN#%d deasserting IRQ (drive select change)\n", __FUNCTION__, pCtl->aIfs[iSelectedIf].iLUN));
4714 if (pCtl->irq == 16)
4715 PDMDevHlpPCISetIrq(pDevIns, 0, 0);
4716 else
4717 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 0);
4718 }
4719 }
4720 }
4721 break;
4722 default:
4723 case 7: /* command */
4724 {
4725 /* ignore commands to non-existent device */
4726 uintptr_t iSelectedIf = pCtl->iSelectedIf & ATA_SELECTED_IF_MASK;
4727 PATADEVSTATE pDev = &pCtl->aIfs[iSelectedIf];
4728 if (iSelectedIf && !pDev->fPresent) /** @todo r=bird the iSelectedIf test here looks bogus... explain. */
4729 break;
4730#ifndef IN_RING3
4731 /* Don't do anything complicated in GC */
4732 return VINF_IOM_R3_IOPORT_WRITE;
4733#else /* IN_RING3 */
4734 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
4735 ataUnsetIRQ(pDevIns, pCtl, &pCtl->aIfs[iSelectedIf]);
4736 ataR3ParseCmd(pDevIns, pCtl, &pCtl->aIfs[iSelectedIf], &pThisCC->aCts[iCtl].aIfs[iSelectedIf], val);
4737 break;
4738#endif /* !IN_RING3 */
4739 }
4740 }
4741 return VINF_SUCCESS;
4742}
4743
4744
4745static VBOXSTRICTRC ataIOPortReadU8(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t addr, uint32_t *pu32)
4746{
4747 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
4748 uint32_t val;
4749 bool fHOB;
4750
4751 /* Check if the guest is reading from a non-existent device. */
4752 if (RT_LIKELY(s->fPresent))
4753 { /* likely */ }
4754 else
4755 {
4756 if (pCtl->iSelectedIf) /* Device 1 selected, Device 0 responding for it. */
4757 {
4758 Assert(pCtl->aIfs[0].fPresent);
4759
4760 /* When an ATAPI device 0 responds for non-present device 1, it generally
4761 * returns zeros on reads. The Error register is an exception. See clause 7.1,
4762 * table 16 in ATA-6 specification.
4763 */
4764 if (((addr & 7) != 1) && pCtl->aIfs[0].fATAPI)
4765 {
4766 Log2(("%s: addr=%#x, val=0: LUN#%d not attached/LUN#%d ATAPI\n", __FUNCTION__, addr, s->iLUN, pCtl->aIfs[0].iLUN));
4767 *pu32 = 0;
4768 return VINF_SUCCESS;
4769 }
4770 /* Else handle normally. */
4771 }
4772 else /* Device 0 selected (but not present). */
4773 {
4774 /* Because device 1 has no way to tell if there is device 0, the behavior is the same
4775 * as for an empty bus; see comments in ataIOPortReadEmptyBus(). Note that EFI (TianoCore)
4776 * relies on this behavior when detecting devices.
4777 */
4778 *pu32 = ATA_EMPTY_BUS_DATA;
4779 Log2(("%s: addr=%#x: LUN#%d not attached, val=%#02x\n", __FUNCTION__, addr, s->iLUN, *pu32));
4780 return VINF_SUCCESS;
4781 }
4782 }
4783
4784 fHOB = !!(s->uATARegDevCtl & (1 << 7));
4785 switch (addr & 7)
4786 {
4787 case 0: /* data register */
4788 val = 0xff;
4789 break;
4790 case 1: /* error register */
4791 /* The ATA specification is very terse when it comes to specifying
4792 * the precise effects of reading back the error/feature register.
4793 * The error register (read-only) shares the register number with
4794 * the feature register (write-only), so it seems that it's not
4795 * necessary to support the usual HOB readback here. */
4796 if (!s->fPresent)
4797 val = 0;
4798 else
4799 val = s->uATARegError;
4800 break;
4801 case 2: /* sector count */
4802 if (fHOB)
4803 val = s->uATARegNSectorHOB;
4804 else
4805 val = s->uATARegNSector;
4806 break;
4807 case 3: /* sector number */
4808 if (fHOB)
4809 val = s->uATARegSectorHOB;
4810 else
4811 val = s->uATARegSector;
4812 break;
4813 case 4: /* cylinder low */
4814 if (fHOB)
4815 val = s->uATARegLCylHOB;
4816 else
4817 val = s->uATARegLCyl;
4818 break;
4819 case 5: /* cylinder high */
4820 if (fHOB)
4821 val = s->uATARegHCylHOB;
4822 else
4823 val = s->uATARegHCyl;
4824 break;
4825 case 6: /* drive/head */
4826 /* This register must always work as long as there is at least
4827 * one drive attached to the controller. It is common between
4828 * both drives anyway (completely identical content). */
4829 if (!pCtl->aIfs[0].fPresent && !pCtl->aIfs[1].fPresent)
4830 val = 0;
4831 else
4832 val = s->uATARegSelect;
4833 break;
4834 default:
4835 case 7: /* primary status */
4836 {
4837 if (!s->fPresent)
4838 val = 0;
4839 else
4840 val = s->uATARegStatus;
4841
4842 /* Give the async I/O thread an opportunity to make progress,
4843 * don't let it starve by guests polling frequently. EMT has a
4844 * lower priority than the async I/O thread, but sometimes the
4845 * host OS doesn't care. With some guests we are only allowed to
4846 * be busy for about 5 milliseconds in some situations. Note that
4847 * this is no guarantee for any other VBox thread getting
4848 * scheduled, so this just lowers the CPU load a bit when drives
4849 * are busy. It cannot help with timing problems. */
4850 if (val & ATA_STAT_BUSY)
4851 {
4852#ifdef IN_RING3
4853 /* @bugref{1960}: Don't yield all the time, unless it's a reset (can be tricky). */
4854 bool fYield = (s->cBusyStatusHackR3++ & s->cBusyStatusHackR3Rate) == 0
4855 || pCtl->fReset;
4856
4857 ataR3LockLeave(pDevIns, pCtl);
4858
4859 /*
4860 * The thread might be stuck in an I/O operation due to a high I/O
4861 * load on the host (see @bugref{3301}). To perform the reset
4862 * successfully we interrupt the operation by sending a signal to
4863 * the thread if the thread didn't responded in 10ms.
4864 *
4865 * This works only on POSIX hosts (Windows has a CancelSynchronousIo
4866 * function which does the same but it was introduced with Vista) but
4867 * so far this hang was only observed on Linux and Mac OS X.
4868 *
4869 * This is a workaround and needs to be solved properly.
4870 */
4871 if (pCtl->fReset)
4872 {
4873 uint64_t u64ResetTimeStop = RTTimeMilliTS();
4874 if (u64ResetTimeStop - pCtl->u64ResetTime >= 10)
4875 {
4876 LogRel(("PIIX3 ATA LUN#%d: Async I/O thread probably stuck in operation, interrupting\n", s->iLUN));
4877 pCtl->u64ResetTime = u64ResetTimeStop;
4878# ifndef RT_OS_WINDOWS /* We've got this API on windows, but it doesn't necessarily interrupt I/O. */
4879 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
4880 PATACONTROLLERR3 pCtlR3 = &RT_SAFE_SUBSCRIPT(pThisCC->aCts, pCtl->iCtl);
4881 RTThreadPoke(pCtlR3->hAsyncIOThread);
4882# endif
4883 Assert(fYield);
4884 }
4885 }
4886
4887 if (fYield)
4888 {
4889 STAM_REL_PROFILE_ADV_START(&s->StatStatusYields, a);
4890 RTThreadYield();
4891 STAM_REL_PROFILE_ADV_STOP(&s->StatStatusYields, a);
4892 }
4893 ASMNopPause();
4894
4895 ataR3LockEnter(pDevIns, pCtl);
4896
4897 val = s->uATARegStatus;
4898#else /* !IN_RING3 */
4899 /* Cannot yield CPU in raw-mode and ring-0 context. And switching
4900 * to host context for each and every busy status is too costly,
4901 * especially on SMP systems where we don't gain much by
4902 * yielding the CPU to someone else. */
4903 if ((s->cBusyStatusHackRZ++ & s->cBusyStatusHackRZRate) == 1)
4904 {
4905 s->cBusyStatusHackR3 = 0; /* Forces a yield. */
4906 return VINF_IOM_R3_IOPORT_READ;
4907 }
4908#endif /* !IN_RING3 */
4909 }
4910 else
4911 {
4912 s->cBusyStatusHackRZ = 0;
4913 s->cBusyStatusHackR3 = 0;
4914 }
4915 ataUnsetIRQ(pDevIns, pCtl, s);
4916 break;
4917 }
4918 }
4919 Log2(("%s: LUN#%d addr=%#x val=%#04x\n", __FUNCTION__, s->iLUN, addr, val));
4920 *pu32 = val;
4921 return VINF_SUCCESS;
4922}
4923
4924
4925/*
4926 * Read the Alternate status register. Does not affect interrupts.
4927 */
4928static uint32_t ataStatusRead(PATACONTROLLER pCtl, uint32_t uIoPortForLog)
4929{
4930 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
4931 uint32_t val;
4932 RT_NOREF(uIoPortForLog);
4933
4934 Assert(pCtl->aIfs[0].fPresent || pCtl->aIfs[1].fPresent); /* Channel must not be empty. */
4935 if (pCtl->iSelectedIf == 1 && !s->fPresent)
4936 val = 0; /* Device 1 selected, Device 0 responding for it. */
4937 else
4938 val = s->uATARegStatus;
4939 Log2(("%s: LUN#%d read addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN, uIoPortForLog, val));
4940 return val;
4941}
4942
4943static int ataControlWrite(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t val, uint32_t uIoPortForLog)
4944{
4945 RT_NOREF(uIoPortForLog);
4946#ifndef IN_RING3
4947 if ((val ^ pCtl->aIfs[0].uATARegDevCtl) & ATA_DEVCTL_RESET)
4948 return VINF_IOM_R3_IOPORT_WRITE; /* The RESET stuff is too complicated for RC+R0. */
4949#endif /* !IN_RING3 */
4950
4951 Log2(("%s: LUN#%d write addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN, uIoPortForLog, val));
4952 /* RESET is common for both drives attached to a controller. */
4953 if ( !(pCtl->aIfs[0].uATARegDevCtl & ATA_DEVCTL_RESET)
4954 && (val & ATA_DEVCTL_RESET))
4955 {
4956#ifdef IN_RING3
4957 /* Software RESET low to high */
4958 int32_t uCmdWait0 = -1;
4959 int32_t uCmdWait1 = -1;
4960 uint64_t uNow = RTTimeNanoTS();
4961 if (pCtl->aIfs[0].u64CmdTS)
4962 uCmdWait0 = (uNow - pCtl->aIfs[0].u64CmdTS) / 1000;
4963 if (pCtl->aIfs[1].u64CmdTS)
4964 uCmdWait1 = (uNow - pCtl->aIfs[1].u64CmdTS) / 1000;
4965 LogRel(("PIIX3 ATA: Ctl#%d: RESET, DevSel=%d AIOIf=%d CmdIf0=%#04x (%d usec ago) CmdIf1=%#04x (%d usec ago)\n",
4966 pCtl->iCtl, pCtl->iSelectedIf, pCtl->iAIOIf,
4967 pCtl->aIfs[0].uATARegCommand, uCmdWait0,
4968 pCtl->aIfs[1].uATARegCommand, uCmdWait1));
4969 pCtl->fReset = true;
4970 /* Everything must be done after the reset flag is set, otherwise
4971 * there are unavoidable races with the currently executing request
4972 * (which might just finish in the mean time). */
4973 pCtl->fChainedTransfer = false;
4974 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
4975 {
4976 ataR3ResetDevice(pDevIns, pCtl, &pCtl->aIfs[i]);
4977 /* The following cannot be done using ataSetStatusValue() since the
4978 * reset flag is already set, which suppresses all status changes. */
4979 pCtl->aIfs[i].uATARegStatus = ATA_STAT_BUSY | ATA_STAT_SEEK;
4980 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, pCtl->aIfs[i].iLUN, pCtl->aIfs[i].uATARegStatus));
4981 pCtl->aIfs[i].uATARegError = 0x01;
4982 }
4983 pCtl->iSelectedIf = 0;
4984 ataR3AsyncIOClearRequests(pDevIns, pCtl);
4985 Log2(("%s: Ctl#%d: message to async I/O thread, resetA\n", __FUNCTION__, pCtl->iCtl));
4986 if (val & ATA_DEVCTL_HOB)
4987 {
4988 val &= ~ATA_DEVCTL_HOB;
4989 Log2(("%s: ignored setting HOB\n", __FUNCTION__));
4990 }
4991
4992 /* Save the timestamp we started the reset. */
4993 pCtl->u64ResetTime = RTTimeMilliTS();
4994
4995 /* Issue the reset request now. */
4996 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataResetARequest);
4997#else /* !IN_RING3 */
4998 AssertMsgFailed(("RESET handling is too complicated for GC\n"));
4999#endif /* IN_RING3 */
5000 }
5001 else if ( (pCtl->aIfs[0].uATARegDevCtl & ATA_DEVCTL_RESET)
5002 && !(val & ATA_DEVCTL_RESET))
5003 {
5004#ifdef IN_RING3
5005 /* Software RESET high to low */
5006 Log(("%s: deasserting RESET\n", __FUNCTION__));
5007 Log2(("%s: Ctl#%d: message to async I/O thread, resetC\n", __FUNCTION__, pCtl->iCtl));
5008 if (val & ATA_DEVCTL_HOB)
5009 {
5010 val &= ~ATA_DEVCTL_HOB;
5011 Log2(("%s: ignored setting HOB\n", __FUNCTION__));
5012 }
5013 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataResetCRequest);
5014#else /* !IN_RING3 */
5015 AssertMsgFailed(("RESET handling is too complicated for GC\n"));
5016#endif /* IN_RING3 */
5017 }
5018
5019 /* Change of interrupt disable flag. Update interrupt line if interrupt
5020 * is pending on the current interface. */
5021 if ( ((val ^ pCtl->aIfs[0].uATARegDevCtl) & ATA_DEVCTL_DISABLE_IRQ)
5022 && pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].fIrqPending)
5023 {
5024 if (!(val & ATA_DEVCTL_DISABLE_IRQ))
5025 {
5026 Log2(("%s: LUN#%d asserting IRQ (interrupt disable change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN));
5027 /* The BMDMA unit unconditionally sets BM_STATUS_INT if the
5028 * interrupt line is asserted. It monitors the line for a rising
5029 * edge. */
5030 pCtl->BmDma.u8Status |= BM_STATUS_INT;
5031 if (pCtl->irq == 16)
5032 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
5033 else
5034 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 1);
5035 }
5036 else
5037 {
5038 Log2(("%s: LUN#%d deasserting IRQ (interrupt disable change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].iLUN));
5039 if (pCtl->irq == 16)
5040 PDMDevHlpPCISetIrq(pDevIns, 0, 0);
5041 else
5042 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 0);
5043 }
5044 }
5045
5046 if (val & ATA_DEVCTL_HOB)
5047 Log2(("%s: set HOB\n", __FUNCTION__));
5048
5049 pCtl->aIfs[0].uATARegDevCtl = val;
5050 pCtl->aIfs[1].uATARegDevCtl = val;
5051
5052 return VINF_SUCCESS;
5053}
5054
5055#if defined(IN_RING0) || defined(IN_RING3)
5056
5057static void ataHCPIOTransfer(PPDMDEVINS pDevIns, PATACONTROLLER pCtl)
5058{
5059 PATADEVSTATE s;
5060
5061 s = &pCtl->aIfs[pCtl->iAIOIf & ATA_SELECTED_IF_MASK];
5062 Log3(("%s: if=%p\n", __FUNCTION__, s));
5063
5064 if (s->cbTotalTransfer && s->iIOBufferCur > s->iIOBufferEnd)
5065 {
5066# ifdef IN_RING3
5067 LogRel(("PIIX3 ATA: LUN#%d: %s data in the middle of a PIO transfer - VERY SLOW\n",
5068 s->iLUN, s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE ? "loading" : "storing"));
5069 /* Any guest OS that triggers this case has a pathetic ATA driver.
5070 * In a real system it would block the CPU via IORDY, here we do it
5071 * very similarly by not continuing with the current instruction
5072 * until the transfer to/from the storage medium is completed. */
5073 uint8_t const iSourceSink = s->iSourceSink;
5074 if ( iSourceSink != ATAFN_SS_NULL
5075 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
5076 {
5077 bool fRedo;
5078 uint8_t status = s->uATARegStatus;
5079 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
5080 PATADEVSTATER3 pDevR3 = &RT_SAFE_SUBSCRIPT(RT_SAFE_SUBSCRIPT(pThisCC->aCts, pCtl->iCtl).aIfs, s->iDev);
5081
5082 ataSetStatusValue(pCtl, s, ATA_STAT_BUSY);
5083 Log2(("%s: calling source/sink function\n", __FUNCTION__));
5084 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
5085 pCtl->fRedo = fRedo;
5086 if (RT_UNLIKELY(fRedo))
5087 return;
5088 ataSetStatusValue(pCtl, s, status);
5089 s->iIOBufferCur = 0;
5090 s->iIOBufferEnd = s->cbElementaryTransfer;
5091 }
5092 else
5093 Assert(iSourceSink == ATAFN_SS_NULL);
5094# else
5095 AssertReleaseFailed();
5096# endif
5097 }
5098 if (s->cbTotalTransfer)
5099 {
5100 if (s->fATAPITransfer)
5101 ataHCPIOTransferLimitATAPI(s);
5102
5103 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
5104 s->cbElementaryTransfer = s->cbTotalTransfer;
5105
5106 Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
5107 __FUNCTION__, s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE ? "T2I" : "I2T",
5108 s->cbTotalTransfer, s->cbElementaryTransfer,
5109 s->iIOBufferCur, s->iIOBufferEnd));
5110 ataHCPIOTransferStart(pCtl, s, s->iIOBufferCur, s->cbElementaryTransfer);
5111 s->cbTotalTransfer -= s->cbElementaryTransfer;
5112 s->iIOBufferCur += s->cbElementaryTransfer;
5113
5114 if (s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
5115 s->cbElementaryTransfer = s->cbTotalTransfer;
5116 }
5117 else
5118 ataHCPIOTransferStop(pDevIns, pCtl, s);
5119}
5120
5121
5122DECLINLINE(void) ataHCPIOTransferFinish(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATADEVSTATE s)
5123{
5124 /* Do not interfere with RESET processing if the PIO transfer finishes
5125 * while the RESET line is asserted. */
5126 if (pCtl->fReset)
5127 {
5128 Log2(("%s: Ctl#%d: suppressed continuing PIO transfer as RESET is active\n", __FUNCTION__, pCtl->iCtl));
5129 return;
5130 }
5131
5132 if ( s->uTxDir == PDMMEDIATXDIR_TO_DEVICE
5133 || ( s->iSourceSink != ATAFN_SS_NULL
5134 && s->iIOBufferCur >= s->iIOBufferEnd))
5135 {
5136 /* Need to continue the transfer in the async I/O thread. This is
5137 * the case for write operations or generally for not yet finished
5138 * transfers (some data might need to be read). */
5139 ataSetStatus(pCtl, s, ATA_STAT_BUSY);
5140 ataUnsetStatus(pCtl, s, ATA_STAT_READY | ATA_STAT_DRQ);
5141
5142 Log2(("%s: Ctl#%d: message to async I/O thread, continuing PIO transfer\n", __FUNCTION__, pCtl->iCtl));
5143 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataPIORequest);
5144 }
5145 else
5146 {
5147 /* Either everything finished (though some data might still be pending)
5148 * or some data is pending before the next read is due. */
5149
5150 /* Continue a previously started transfer. */
5151 ataUnsetStatus(pCtl, s, ATA_STAT_DRQ);
5152 ataSetStatus(pCtl, s, ATA_STAT_READY);
5153
5154 if (s->cbTotalTransfer)
5155 {
5156 /* There is more to transfer, happens usually for large ATAPI
5157 * reads - the protocol limits the chunk size to 65534 bytes. */
5158 ataHCPIOTransfer(pDevIns, pCtl);
5159 ataHCSetIRQ(pDevIns, pCtl, s);
5160 }
5161 else
5162 {
5163 Log2(("%s: Ctl#%d: skipping message to async I/O thread, ending PIO transfer\n", __FUNCTION__, pCtl->iCtl));
5164 /* Finish PIO transfer. */
5165 ataHCPIOTransfer(pDevIns, pCtl);
5166 Assert(!pCtl->fRedo);
5167 }
5168 }
5169}
5170
5171#endif /* IN_RING0 || IN_RING3 */
5172
5173/**
5174 * Fallback for ataCopyPioData124 that handles unaligned and out of bounds cases.
5175 *
5176 * @param pIf The device interface to work with.
5177 * @param pbDst The destination buffer.
5178 * @param pbSrc The source buffer.
5179 * @param offStart The start offset (iIOBufferPIODataStart).
5180 * @param cbCopy The number of bytes to copy, either 1, 2 or 4 bytes.
5181 */
5182DECL_NO_INLINE(static, void) ataCopyPioData124Slow(PATADEVSTATE pIf, uint8_t *pbDst, const uint8_t *pbSrc,
5183 uint32_t offStart, uint32_t cbCopy)
5184{
5185 uint32_t const offNext = offStart + cbCopy;
5186 uint32_t const cbIOBuffer = RT_MIN(pIf->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE);
5187
5188 if (offStart + cbCopy > cbIOBuffer)
5189 {
5190 Log(("%s: cbCopy=%#x offStart=%#x cbIOBuffer=%#x offNext=%#x (iIOBufferPIODataEnd=%#x)\n",
5191 __FUNCTION__, cbCopy, offStart, cbIOBuffer, offNext, pIf->iIOBufferPIODataEnd));
5192 if (offStart < cbIOBuffer)
5193 cbCopy = cbIOBuffer - offStart;
5194 else
5195 cbCopy = 0;
5196 }
5197
5198 switch (cbCopy)
5199 {
5200 case 4: pbDst[3] = pbSrc[3]; RT_FALL_THRU();
5201 case 3: pbDst[2] = pbSrc[2]; RT_FALL_THRU();
5202 case 2: pbDst[1] = pbSrc[1]; RT_FALL_THRU();
5203 case 1: pbDst[0] = pbSrc[0]; RT_FALL_THRU();
5204 case 0: break;
5205 default: AssertFailed(); /* impossible */
5206 }
5207
5208 pIf->iIOBufferPIODataStart = offNext;
5209
5210}
5211
5212
5213/**
5214 * Work for ataDataWrite & ataDataRead that copies data without using memcpy.
5215 *
5216 * This also updates pIf->iIOBufferPIODataStart.
5217 *
5218 * The two buffers are either stack (32-bit aligned) or somewhere within
5219 * pIf->abIOBuffer.
5220 *
5221 * @param pIf The device interface to work with.
5222 * @param pbDst The destination buffer.
5223 * @param pbSrc The source buffer.
5224 * @param offStart The start offset (iIOBufferPIODataStart).
5225 * @param cbCopy The number of bytes to copy, either 1, 2 or 4 bytes.
5226 */
5227DECLINLINE(void) ataCopyPioData124(PATADEVSTATE pIf, uint8_t *pbDst, const uint8_t *pbSrc, uint32_t offStart, uint32_t cbCopy)
5228{
5229 /*
5230 * Quick bounds checking can be done by checking that the abIOBuffer offset
5231 * (iIOBufferPIODataStart) is aligned at the transfer size (which is ASSUMED
5232 * to be 1, 2 or 4). However, since we're paranoid and don't currently
5233 * trust iIOBufferPIODataEnd to be within bounds, we current check against the
5234 * IO buffer size too.
5235 */
5236 Assert(cbCopy == 1 || cbCopy == 2 || cbCopy == 4);
5237 if (RT_LIKELY( !(offStart & (cbCopy - 1))
5238 && offStart + cbCopy <= RT_MIN(pIf->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE)))
5239 {
5240 switch (cbCopy)
5241 {
5242 case 4: *(uint32_t *)pbDst = *(uint32_t const *)pbSrc; break;
5243 case 2: *(uint16_t *)pbDst = *(uint16_t const *)pbSrc; break;
5244 case 1: *pbDst = *pbSrc; break;
5245 }
5246 pIf->iIOBufferPIODataStart = offStart + cbCopy;
5247 }
5248 else
5249 ataCopyPioData124Slow(pIf, pbDst, pbSrc, offStart, cbCopy);
5250}
5251
5252
5253/**
5254 * @callback_method_impl{FNIOMIOPORTNEWOUT,
5255 * Port I/O Handler for primary port range OUT operations.}
5256 * @note offPort is an absolute port number!
5257 */
5258static DECLCALLBACK(VBOXSTRICTRC)
5259ataIOPortWrite1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
5260{
5261 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5262 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5263 RT_NOREF(offPort);
5264
5265 Assert((uintptr_t)pvUser < 2);
5266 Assert(offPort == pCtl->IOPortBase1);
5267 Assert(cb == 2 || cb == 4); /* Writes to the data port may be 16-bit or 32-bit. */
5268
5269 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
5270 if (rc == VINF_SUCCESS)
5271 {
5272 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5273 uint32_t const iIOBufferPIODataStart = RT_MIN(s->iIOBufferPIODataStart, sizeof(s->abIOBuffer));
5274 uint32_t const iIOBufferPIODataEnd = RT_MIN(s->iIOBufferPIODataEnd, sizeof(s->abIOBuffer));
5275
5276 if (iIOBufferPIODataStart < iIOBufferPIODataEnd)
5277 {
5278 Assert(s->uTxDir == PDMMEDIATXDIR_TO_DEVICE);
5279 uint8_t *pbDst = &s->abIOBuffer[iIOBufferPIODataStart];
5280 uint8_t const *pbSrc = (uint8_t const *)&u32;
5281
5282#ifdef IN_RC
5283 /* Raw-mode: The ataHCPIOTransfer following the last transfer unit
5284 requires I/O thread signalling, we must go to ring-3 for that. */
5285 if (iIOBufferPIODataStart + cb < iIOBufferPIODataEnd)
5286 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5287 else
5288 rc = VINF_IOM_R3_IOPORT_WRITE;
5289
5290#elif defined(IN_RING0)
5291 /* Ring-0: We can do I/O thread signalling here, however for paranoid reasons
5292 triggered by a special case in ataHCPIOTransferFinish, we take extra care here. */
5293 if (iIOBufferPIODataStart + cb < iIOBufferPIODataEnd)
5294 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5295 else if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE) /* paranoia */
5296 {
5297 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5298 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5299 }
5300 else
5301 {
5302 Log(("%s: Unexpected\n", __FUNCTION__));
5303 rc = VINF_IOM_R3_IOPORT_WRITE;
5304 }
5305
5306#else /* IN_RING 3*/
5307 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cb);
5308 if (s->iIOBufferPIODataStart >= iIOBufferPIODataEnd)
5309 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5310#endif /* IN_RING 3*/
5311 }
5312 else
5313 Log2(("%s: DUMMY data\n", __FUNCTION__));
5314
5315 Log3(("%s: addr=%#x val=%.*Rhxs rc=%d\n", __FUNCTION__, offPort + pCtl->IOPortBase1, cb, &u32, VBOXSTRICTRC_VAL(rc)));
5316 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5317 }
5318 else
5319 Log3(("%s: addr=%#x -> %d\n", __FUNCTION__, offPort + pCtl->IOPortBase1, VBOXSTRICTRC_VAL(rc)));
5320 return rc;
5321}
5322
5323
5324/**
5325 * @callback_method_impl{FNIOMIOPORTNEWIN,
5326 * Port I/O Handler for primary port range IN operations.}
5327 * @note offPort is an absolute port number!
5328 */
5329static DECLCALLBACK(VBOXSTRICTRC)
5330ataIOPortRead1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
5331{
5332 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5333 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5334 RT_NOREF(offPort);
5335
5336 Assert((uintptr_t)pvUser < 2);
5337 Assert(offPort == pCtl->IOPortBase1);
5338
5339 /* Reads from the data register may be 16-bit or 32-bit. Byte accesses are
5340 upgraded to word. */
5341 Assert(cb == 1 || cb == 2 || cb == 4);
5342 uint32_t cbActual = cb != 1 ? cb : 2;
5343 *pu32 = 0;
5344
5345 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
5346 if (rc == VINF_SUCCESS)
5347 {
5348 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5349
5350 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd)
5351 {
5352 AssertMsg(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE, ("%#x\n", s->uTxDir));
5353 uint32_t const iIOBufferPIODataStart = RT_MIN(s->iIOBufferPIODataStart, sizeof(s->abIOBuffer));
5354 uint32_t const iIOBufferPIODataEnd = RT_MIN(s->iIOBufferPIODataEnd, sizeof(s->abIOBuffer));
5355 uint8_t const *pbSrc = &s->abIOBuffer[iIOBufferPIODataStart];
5356 uint8_t *pbDst = (uint8_t *)pu32;
5357
5358#ifdef IN_RC
5359 /* All but the last transfer unit is simple enough for RC, but
5360 * sending a request to the async IO thread is too complicated. */
5361 if (iIOBufferPIODataStart + cbActual < iIOBufferPIODataEnd)
5362 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5363 else
5364 rc = VINF_IOM_R3_IOPORT_READ;
5365
5366#elif defined(IN_RING0)
5367 /* Ring-0: We can do I/O thread signalling here. However there is one
5368 case in ataHCPIOTransfer that does a LogRel and would (but not from
5369 here) call directly into the driver code. We detect that odd case
5370 here cand return to ring-3 to handle it. */
5371 if (iIOBufferPIODataStart + cbActual < iIOBufferPIODataEnd)
5372 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5373 else if ( s->cbTotalTransfer == 0
5374 || s->iSourceSink != ATAFN_SS_NULL
5375 || s->iIOBufferCur <= s->iIOBufferEnd)
5376 {
5377 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5378 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5379 }
5380 else
5381 {
5382 Log(("%s: Unexpected\n",__FUNCTION__));
5383 rc = VINF_IOM_R3_IOPORT_READ;
5384 }
5385
5386#else /* IN_RING3 */
5387 ataCopyPioData124(s, pbDst, pbSrc, iIOBufferPIODataStart, cbActual);
5388 if (s->iIOBufferPIODataStart >= iIOBufferPIODataEnd)
5389 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5390#endif /* IN_RING3 */
5391
5392 /* Just to be on the safe side (caller takes care of this, really). */
5393 if (cb == 1)
5394 *pu32 &= 0xff;
5395 }
5396 else
5397 {
5398 Log2(("%s: DUMMY data\n", __FUNCTION__));
5399 memset(pu32, 0xff, cb);
5400 }
5401 Log3(("%s: addr=%#x val=%.*Rhxs rc=%d\n", __FUNCTION__, offPort, cb, pu32, VBOXSTRICTRC_VAL(rc)));
5402
5403 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5404 }
5405 else
5406 Log3(("%s: addr=%#x -> %d\n", __FUNCTION__, offPort, VBOXSTRICTRC_VAL(rc)));
5407
5408 return rc;
5409}
5410
5411
5412/**
5413 * @callback_method_impl{FNIOMIOPORTNEWINSTRING,
5414 * Port I/O Handler for primary port range IN string operations.}
5415 * @note offPort is an absolute port number!
5416 */
5417static DECLCALLBACK(VBOXSTRICTRC)
5418ataIOPortReadStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint8_t *pbDst, uint32_t *pcTransfers, unsigned cb)
5419{
5420 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5421 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5422 RT_NOREF(offPort);
5423
5424 Assert((uintptr_t)pvUser < 2);
5425 Assert(offPort == pCtl->IOPortBase1);
5426 Assert(*pcTransfers > 0);
5427
5428 VBOXSTRICTRC rc;
5429 if (cb == 2 || cb == 4)
5430 {
5431 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
5432 if (rc == VINF_SUCCESS)
5433 {
5434 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5435
5436 uint32_t const offStart = s->iIOBufferPIODataStart;
5437 uint32_t const offEnd = s->iIOBufferPIODataEnd;
5438 if (offStart < offEnd)
5439 {
5440 /*
5441 * Figure how much we can copy. Usually it's the same as the request.
5442 * The last transfer unit cannot be handled in RC, as it involves
5443 * thread communication. In R0 we let the non-string callback handle it,
5444 * and ditto for overflows/dummy data.
5445 */
5446 uint32_t cAvailable = (offEnd - offStart) / cb;
5447#ifndef IN_RING3
5448 if (cAvailable > 0)
5449 cAvailable--;
5450#endif
5451 uint32_t const cRequested = *pcTransfers;
5452 if (cAvailable > cRequested)
5453 cAvailable = cRequested;
5454 uint32_t const cbTransfer = cAvailable * cb;
5455 uint32_t const offEndThisXfer = offStart + cbTransfer;
5456 if ( offEndThisXfer <= RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE)
5457 && offStart < RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE) /* paranoia */
5458 && cbTransfer > 0)
5459 {
5460 /*
5461 * Do the transfer.
5462 */
5463 uint8_t const *pbSrc = &s->abIOBuffer[offStart];
5464 memcpy(pbDst, pbSrc, cbTransfer);
5465 Log3(("%s: addr=%#x cb=%#x cbTransfer=%#x val=%.*Rhxd\n",
5466 __FUNCTION__, offPort, cb, cbTransfer, cbTransfer, pbSrc));
5467 s->iIOBufferPIODataStart = offEndThisXfer;
5468#ifdef IN_RING3
5469 if (offEndThisXfer >= offEnd)
5470 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5471#endif
5472 *pcTransfers = cRequested - cAvailable;
5473 }
5474 else
5475 Log2(("ataIOPortReadStr1Data: DUMMY/Overflow!\n"));
5476 }
5477 else
5478 {
5479 /*
5480 * Dummy read (shouldn't happen) return 0xff like the non-string handler.
5481 */
5482 Log2(("ataIOPortReadStr1Data: DUMMY data (%#x bytes)\n", *pcTransfers * cb));
5483 memset(pbDst, 0xff, *pcTransfers * cb);
5484 *pcTransfers = 0;
5485 }
5486
5487 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5488 }
5489 }
5490 /*
5491 * Let the non-string I/O callback handle 1 byte reads.
5492 */
5493 else
5494 {
5495 Log2(("ataIOPortReadStr1Data: 1 byte read (%#x transfers)\n", *pcTransfers));
5496 AssertFailed();
5497 rc = VINF_SUCCESS;
5498 }
5499 return rc;
5500}
5501
5502
5503/**
5504 * @callback_method_impl{FNIOMIOPORTNEWOUTSTRING,
5505 * Port I/O Handler for primary port range OUT string operations.}
5506 * @note offPort is an absolute port number!
5507 */
5508static DECLCALLBACK(VBOXSTRICTRC)
5509ataIOPortWriteStr1Data(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb)
5510{
5511 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5512 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
5513 RT_NOREF(offPort);
5514
5515 Assert((uintptr_t)pvUser < 2);
5516 Assert(offPort == pCtl->IOPortBase1);
5517 Assert(*pcTransfers > 0);
5518
5519 VBOXSTRICTRC rc;
5520 if (cb == 2 || cb == 4)
5521 {
5522 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
5523 if (rc == VINF_SUCCESS)
5524 {
5525 PATADEVSTATE s = &pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK];
5526
5527 uint32_t const offStart = s->iIOBufferPIODataStart;
5528 uint32_t const offEnd = s->iIOBufferPIODataEnd;
5529 if (offStart < offEnd)
5530 {
5531 /*
5532 * Figure how much we can copy. Usually it's the same as the request.
5533 * The last transfer unit cannot be handled in RC, as it involves
5534 * thread communication. In R0 we let the non-string callback handle it,
5535 * and ditto for overflows/dummy data.
5536 */
5537 uint32_t cAvailable = (offEnd - offStart) / cb;
5538#ifndef IN_RING3
5539 if (cAvailable)
5540 cAvailable--;
5541#endif
5542 uint32_t const cRequested = *pcTransfers;
5543 if (cAvailable > cRequested)
5544 cAvailable = cRequested;
5545 uint32_t const cbTransfer = cAvailable * cb;
5546 uint32_t const offEndThisXfer = offStart + cbTransfer;
5547 if ( offEndThisXfer <= RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE)
5548 && offStart < RT_MIN(s->cbIOBuffer, ATA_MAX_IO_BUFFER_SIZE) /* paranoia */
5549 && cbTransfer > 0)
5550 {
5551 /*
5552 * Do the transfer.
5553 */
5554 void *pvDst = &s->abIOBuffer[offStart];
5555 memcpy(pvDst, pbSrc, cbTransfer);
5556 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, offPort + pCtl->IOPortBase1, cbTransfer, pvDst));
5557 s->iIOBufferPIODataStart = offEndThisXfer;
5558#ifdef IN_RING3
5559 if (offEndThisXfer >= offEnd)
5560 ataHCPIOTransferFinish(pDevIns, pCtl, s);
5561#endif
5562 *pcTransfers = cRequested - cAvailable;
5563 }
5564 else
5565 Log2(("ataIOPortWriteStr1Data: DUMMY/Overflow!\n"));
5566 }
5567 else
5568 {
5569 Log2(("ataIOPortWriteStr1Data: DUMMY data (%#x bytes)\n", *pcTransfers * cb));
5570 *pcTransfers = 0;
5571 }
5572
5573 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
5574 }
5575 }
5576 /*
5577 * Let the non-string I/O callback handle 1 byte reads.
5578 */
5579 else
5580 {
5581 Log2(("ataIOPortWriteStr1Data: 1 byte write (%#x transfers)\n", *pcTransfers));
5582 AssertFailed();
5583 rc = VINF_SUCCESS;
5584 }
5585
5586 return rc;
5587}
5588
5589
5590#ifdef IN_RING3
5591
5592static void ataR3DMATransferStop(PATADEVSTATE s)
5593{
5594 s->cbTotalTransfer = 0;
5595 s->cbElementaryTransfer = 0;
5596 s->iBeginTransfer = ATAFN_BT_NULL;
5597 s->iSourceSink = ATAFN_SS_NULL;
5598}
5599
5600
5601/**
5602 * Perform the entire DMA transfer in one go (unless a source/sink operation
5603 * has to be redone or a RESET comes in between). Unlike the PIO counterpart
5604 * this function cannot handle empty transfers.
5605 *
5606 * @param pDevIns The device instance.
5607 * @param pCtl Controller for which to perform the transfer, shared bits.
5608 * @param pCtlR3 The ring-3 controller state.
5609 */
5610static void ataR3DMATransfer(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATACONTROLLERR3 pCtlR3)
5611{
5612 uint8_t const iAIOIf = pCtl->iAIOIf & ATA_SELECTED_IF_MASK;
5613 PATADEVSTATE s = &pCtl->aIfs[iAIOIf];
5614 PATADEVSTATER3 pDevR3 = &pCtlR3->aIfs[iAIOIf];
5615 bool fRedo;
5616 RTGCPHYS32 GCPhysDesc;
5617 uint32_t cbTotalTransfer, cbElementaryTransfer;
5618 uint32_t iIOBufferCur, iIOBufferEnd;
5619 PDMMEDIATXDIR uTxDir;
5620 bool fLastDesc = false;
5621
5622 Assert(sizeof(BMDMADesc) == 8);
5623
5624 fRedo = pCtl->fRedo;
5625 if (RT_LIKELY(!fRedo))
5626 Assert(s->cbTotalTransfer);
5627 uTxDir = (PDMMEDIATXDIR)s->uTxDir;
5628 cbTotalTransfer = s->cbTotalTransfer;
5629 cbElementaryTransfer = RT_MIN(s->cbElementaryTransfer, sizeof(s->abIOBuffer));
5630 iIOBufferEnd = RT_MIN(s->iIOBufferEnd, sizeof(s->abIOBuffer));
5631 iIOBufferCur = RT_MIN(RT_MIN(s->iIOBufferCur, sizeof(s->abIOBuffer)), iIOBufferEnd);
5632
5633 /* The DMA loop is designed to hold the lock only when absolutely
5634 * necessary. This avoids long freezes should the guest access the
5635 * ATA registers etc. for some reason. */
5636 ataR3LockLeave(pDevIns, pCtl);
5637
5638 Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
5639 __FUNCTION__, uTxDir == PDMMEDIATXDIR_FROM_DEVICE ? "T2I" : "I2T",
5640 cbTotalTransfer, cbElementaryTransfer,
5641 iIOBufferCur, iIOBufferEnd));
5642 for (GCPhysDesc = pCtl->GCPhysFirstDMADesc;
5643 GCPhysDesc <= pCtl->GCPhysLastDMADesc;
5644 GCPhysDesc += sizeof(BMDMADesc))
5645 {
5646 BMDMADesc DMADesc;
5647 RTGCPHYS32 GCPhysBuffer;
5648 uint32_t cbBuffer;
5649
5650 if (RT_UNLIKELY(fRedo))
5651 {
5652 GCPhysBuffer = pCtl->GCPhysRedoDMABuffer;
5653 cbBuffer = pCtl->cbRedoDMABuffer;
5654 fLastDesc = pCtl->fRedoDMALastDesc;
5655 DMADesc.GCPhysBuffer = DMADesc.cbBuffer = 0; /* Shut up MSC. */
5656 }
5657 else
5658 {
5659 PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysDesc, &DMADesc, sizeof(BMDMADesc));
5660 GCPhysBuffer = RT_LE2H_U32(DMADesc.GCPhysBuffer);
5661 cbBuffer = RT_LE2H_U32(DMADesc.cbBuffer);
5662 fLastDesc = RT_BOOL(cbBuffer & UINT32_C(0x80000000));
5663 cbBuffer &= 0xfffe;
5664 if (cbBuffer == 0)
5665 cbBuffer = 0x10000;
5666 if (cbBuffer > cbTotalTransfer)
5667 cbBuffer = cbTotalTransfer;
5668 }
5669
5670 while (RT_UNLIKELY(fRedo) || (cbBuffer && cbTotalTransfer))
5671 {
5672 if (RT_LIKELY(!fRedo))
5673 {
5674 uint32_t cbXfer = RT_MIN(RT_MIN(cbBuffer, iIOBufferEnd - iIOBufferCur),
5675 sizeof(s->abIOBuffer) - RT_MIN(iIOBufferCur, sizeof(s->abIOBuffer)));
5676 Log2(("%s: DMA desc %#010x: addr=%#010x size=%#010x orig_size=%#010x\n", __FUNCTION__,
5677 (int)GCPhysDesc, GCPhysBuffer, cbBuffer, RT_LE2H_U32(DMADesc.cbBuffer) & 0xfffe));
5678
5679 if (uTxDir == PDMMEDIATXDIR_FROM_DEVICE)
5680 PDMDevHlpPCIPhysWriteUser(pDevIns, GCPhysBuffer, &s->abIOBuffer[iIOBufferCur], cbXfer);
5681 else
5682 PDMDevHlpPCIPhysReadUser(pDevIns, GCPhysBuffer, &s->abIOBuffer[iIOBufferCur], cbXfer);
5683
5684 iIOBufferCur += cbXfer;
5685 cbTotalTransfer -= cbXfer;
5686 cbBuffer -= cbXfer;
5687 GCPhysBuffer += cbXfer;
5688 }
5689 if ( iIOBufferCur == iIOBufferEnd
5690 && (uTxDir == PDMMEDIATXDIR_TO_DEVICE || cbTotalTransfer))
5691 {
5692 if (uTxDir == PDMMEDIATXDIR_FROM_DEVICE && cbElementaryTransfer > cbTotalTransfer)
5693 cbElementaryTransfer = cbTotalTransfer;
5694
5695 ataR3LockEnter(pDevIns, pCtl);
5696
5697 /* The RESET handler could have cleared the DMA transfer
5698 * state (since we didn't hold the lock until just now
5699 * the guest can continue in parallel). If so, the state
5700 * is already set up so the loop is exited immediately. */
5701 uint8_t const iSourceSink = s->iSourceSink;
5702 if ( iSourceSink != ATAFN_SS_NULL
5703 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
5704 {
5705 s->iIOBufferCur = iIOBufferCur;
5706 s->iIOBufferEnd = iIOBufferEnd;
5707 s->cbElementaryTransfer = cbElementaryTransfer;
5708 s->cbTotalTransfer = cbTotalTransfer;
5709 Log2(("%s: calling source/sink function\n", __FUNCTION__));
5710 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
5711 if (RT_UNLIKELY(fRedo))
5712 {
5713 pCtl->GCPhysFirstDMADesc = GCPhysDesc;
5714 pCtl->GCPhysRedoDMABuffer = GCPhysBuffer;
5715 pCtl->cbRedoDMABuffer = cbBuffer;
5716 pCtl->fRedoDMALastDesc = fLastDesc;
5717 }
5718 else
5719 {
5720 cbTotalTransfer = s->cbTotalTransfer;
5721 cbElementaryTransfer = s->cbElementaryTransfer;
5722
5723 if (uTxDir == PDMMEDIATXDIR_TO_DEVICE && cbElementaryTransfer > cbTotalTransfer)
5724 cbElementaryTransfer = cbTotalTransfer;
5725 iIOBufferCur = 0;
5726 iIOBufferEnd = RT_MIN(cbElementaryTransfer, sizeof(s->abIOBuffer));
5727 }
5728 pCtl->fRedo = fRedo;
5729 }
5730 else
5731 {
5732 /* This forces the loop to exit immediately. */
5733 Assert(iSourceSink == ATAFN_SS_NULL);
5734 GCPhysDesc = pCtl->GCPhysLastDMADesc + 1;
5735 }
5736
5737 ataR3LockLeave(pDevIns, pCtl);
5738 if (RT_UNLIKELY(fRedo))
5739 break;
5740 }
5741 }
5742
5743 if (RT_UNLIKELY(fRedo))
5744 break;
5745
5746 /* end of transfer */
5747 if (!cbTotalTransfer || fLastDesc)
5748 break;
5749
5750 ataR3LockEnter(pDevIns, pCtl);
5751
5752 if (!(pCtl->BmDma.u8Cmd & BM_CMD_START) || pCtl->fReset)
5753 {
5754 LogRel(("PIIX3 ATA: Ctl#%d: ABORT DMA%s\n", pCtl->iCtl, pCtl->fReset ? " due to RESET" : ""));
5755 if (!pCtl->fReset)
5756 ataR3DMATransferStop(s);
5757 /* This forces the loop to exit immediately. */
5758 GCPhysDesc = pCtl->GCPhysLastDMADesc + 1;
5759 }
5760
5761 ataR3LockLeave(pDevIns, pCtl);
5762 }
5763
5764 ataR3LockEnter(pDevIns, pCtl);
5765 if (RT_UNLIKELY(fRedo))
5766 return;
5767
5768 if (fLastDesc)
5769 pCtl->BmDma.u8Status &= ~BM_STATUS_DMAING;
5770 s->cbTotalTransfer = cbTotalTransfer;
5771 s->cbElementaryTransfer = cbElementaryTransfer;
5772 s->iIOBufferCur = iIOBufferCur;
5773 s->iIOBufferEnd = iIOBufferEnd;
5774}
5775
5776/**
5777 * Signal PDM that we're idle (if we actually are).
5778 *
5779 * @param pDevIns The device instance.
5780 * @param pCtl The shared controller state.
5781 * @param pCtlR3 The ring-3 controller state.
5782 */
5783static void ataR3AsyncSignalIdle(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, PATACONTROLLERR3 pCtlR3)
5784{
5785 /*
5786 * Take the lock here and recheck the idle indicator to avoid
5787 * unnecessary work and racing ataR3WaitForAsyncIOIsIdle.
5788 */
5789 int rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->AsyncIORequestLock, VINF_SUCCESS);
5790 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pCtl->AsyncIORequestLock, rc);
5791
5792 if ( pCtlR3->fSignalIdle
5793 && ataR3AsyncIOIsIdle(pDevIns, pCtl, false /*fStrict*/))
5794 {
5795 PDMDevHlpAsyncNotificationCompleted(pDevIns);
5796 RTThreadUserSignal(pCtlR3->hAsyncIOThread); /* for ataR3Construct/ataR3ResetCommon. */
5797 }
5798
5799 rc = PDMDevHlpCritSectLeave(pDevIns, &pCtl->AsyncIORequestLock);
5800 AssertRC(rc);
5801}
5802
5803/**
5804 * Async I/O thread for an interface.
5805 *
5806 * Once upon a time this was readable code with several loops and a different
5807 * semaphore for each purpose. But then came the "how can one save the state in
5808 * the middle of a PIO transfer" question. The solution was to use an ASM,
5809 * which is what's there now.
5810 */
5811static DECLCALLBACK(int) ataR3AsyncIOThread(RTTHREAD hThreadSelf, void *pvUser)
5812{
5813 PATACONTROLLERR3 const pCtlR3 = (PATACONTROLLERR3)pvUser;
5814 PPDMDEVINSR3 const pDevIns = pCtlR3->pDevIns;
5815 PATASTATE const pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
5816 PATASTATER3 const pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
5817 uintptr_t const iCtl = pCtlR3 - &pThisCC->aCts[0];
5818 PATACONTROLLER const pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, iCtl);
5819 int rc = VINF_SUCCESS;
5820 uint64_t u64TS = 0; /* shut up gcc */
5821 uint64_t uWait;
5822 const ATARequest *pReq;
5823 RT_NOREF(hThreadSelf);
5824 Assert(pCtl->iCtl == pCtlR3->iCtl);
5825
5826 pReq = NULL;
5827 pCtl->fChainedTransfer = false;
5828 while (!pCtlR3->fShutdown)
5829 {
5830 /* Keep this thread from doing anything as long as EMT is suspended. */
5831 while (pCtl->fRedoIdle)
5832 {
5833 if (pCtlR3->fSignalIdle)
5834 ataR3AsyncSignalIdle(pDevIns, pCtl, pCtlR3);
5835 rc = RTSemEventWait(pCtlR3->hSuspendIOSem, RT_INDEFINITE_WAIT);
5836 /* Continue if we got a signal by RTThreadPoke().
5837 * We will get notified if there is a request to process.
5838 */
5839 if (RT_UNLIKELY(rc == VERR_INTERRUPTED))
5840 continue;
5841 if (RT_FAILURE(rc) || pCtlR3->fShutdown)
5842 break;
5843
5844 pCtl->fRedoIdle = false;
5845 }
5846
5847 /* Wait for work. */
5848 while (pReq == NULL)
5849 {
5850 if (pCtlR3->fSignalIdle)
5851 ataR3AsyncSignalIdle(pDevIns, pCtl, pCtlR3);
5852 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pCtl->hAsyncIOSem, RT_INDEFINITE_WAIT);
5853 /* Continue if we got a signal by RTThreadPoke().
5854 * We will get notified if there is a request to process.
5855 */
5856 if (RT_UNLIKELY(rc == VERR_INTERRUPTED))
5857 continue;
5858 if (RT_FAILURE(rc) || RT_UNLIKELY(pCtlR3->fShutdown))
5859 break;
5860
5861 pReq = ataR3AsyncIOGetCurrentRequest(pDevIns, pCtl);
5862 }
5863
5864 if (RT_FAILURE(rc) || pCtlR3->fShutdown)
5865 break;
5866
5867 if (pReq == NULL)
5868 continue;
5869
5870 ATAAIO ReqType = pReq->ReqType;
5871
5872 Log2(("%s: Ctl#%d: state=%d, req=%d\n", __FUNCTION__, pCtl->iCtl, pCtl->uAsyncIOState, ReqType));
5873 if (pCtl->uAsyncIOState != ReqType)
5874 {
5875 /* The new state is not the state that was expected by the normal
5876 * state changes. This is either a RESET/ABORT or there's something
5877 * really strange going on. */
5878 if ( (pCtl->uAsyncIOState == ATA_AIO_PIO || pCtl->uAsyncIOState == ATA_AIO_DMA)
5879 && (ReqType == ATA_AIO_PIO || ReqType == ATA_AIO_DMA))
5880 {
5881 /* Incorrect sequence of PIO/DMA states. Dump request queue. */
5882 ataR3AsyncIODumpRequests(pDevIns, pCtl);
5883 }
5884 AssertReleaseMsg( ReqType == ATA_AIO_RESET_ASSERTED
5885 || ReqType == ATA_AIO_RESET_CLEARED
5886 || ReqType == ATA_AIO_ABORT
5887 || pCtl->uAsyncIOState == ReqType,
5888 ("I/O state inconsistent: state=%d request=%d\n", pCtl->uAsyncIOState, ReqType));
5889 }
5890
5891 /* Do our work. */
5892 ataR3LockEnter(pDevIns, pCtl);
5893
5894 if (pCtl->uAsyncIOState == ATA_AIO_NEW && !pCtl->fChainedTransfer)
5895 {
5896 u64TS = RTTimeNanoTS();
5897#if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
5898 STAM_PROFILE_ADV_START(&pCtl->StatAsyncTime, a);
5899#endif
5900 }
5901
5902 switch (ReqType)
5903 {
5904 case ATA_AIO_NEW:
5905 {
5906 uint8_t const iIf = pReq->u.t.iIf & ATA_SELECTED_IF_MASK;
5907 pCtl->iAIOIf = iIf;
5908 PATADEVSTATE s = &pCtl->aIfs[iIf];
5909 PATADEVSTATER3 pDevR3 = &pCtlR3->aIfs[iIf];
5910
5911 s->cbTotalTransfer = pReq->u.t.cbTotalTransfer;
5912 s->uTxDir = pReq->u.t.uTxDir;
5913 s->iBeginTransfer = pReq->u.t.iBeginTransfer;
5914 s->iSourceSink = pReq->u.t.iSourceSink;
5915 s->iIOBufferEnd = 0;
5916 s->u64CmdTS = u64TS;
5917
5918 if (s->fATAPI)
5919 {
5920 if (pCtl->fChainedTransfer)
5921 {
5922 /* Only count the actual transfers, not the PIO
5923 * transfer of the ATAPI command bytes. */
5924 if (s->fDMA)
5925 STAM_REL_COUNTER_INC(&s->StatATAPIDMA);
5926 else
5927 STAM_REL_COUNTER_INC(&s->StatATAPIPIO);
5928 }
5929 }
5930 else
5931 {
5932 if (s->fDMA)
5933 STAM_REL_COUNTER_INC(&s->StatATADMA);
5934 else
5935 STAM_REL_COUNTER_INC(&s->StatATAPIO);
5936 }
5937
5938 pCtl->fChainedTransfer = false;
5939
5940 uint8_t const iBeginTransfer = s->iBeginTransfer;
5941 if ( iBeginTransfer != ATAFN_BT_NULL
5942 && iBeginTransfer < RT_ELEMENTS(g_apfnBeginTransFuncs))
5943 {
5944 Log2(("%s: Ctl#%d: calling begin transfer function\n", __FUNCTION__, pCtl->iCtl));
5945 g_apfnBeginTransFuncs[iBeginTransfer](pCtl, s);
5946 s->iBeginTransfer = ATAFN_BT_NULL;
5947 if (s->uTxDir != PDMMEDIATXDIR_FROM_DEVICE)
5948 s->iIOBufferEnd = s->cbElementaryTransfer;
5949 }
5950 else
5951 {
5952 Assert(iBeginTransfer == ATAFN_BT_NULL);
5953 s->cbElementaryTransfer = s->cbTotalTransfer;
5954 s->iIOBufferEnd = s->cbTotalTransfer;
5955 }
5956 s->iIOBufferCur = 0;
5957
5958 if (s->uTxDir != PDMMEDIATXDIR_TO_DEVICE)
5959 {
5960 uint8_t const iSourceSink = s->iSourceSink;
5961 if ( iSourceSink != ATAFN_SS_NULL
5962 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
5963 {
5964 bool fRedo;
5965 Log2(("%s: Ctl#%d: calling source/sink function\n", __FUNCTION__, pCtl->iCtl));
5966 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
5967 pCtl->fRedo = fRedo;
5968 if (RT_UNLIKELY(fRedo && !pCtl->fReset))
5969 {
5970 /* Operation failed at the initial transfer, restart
5971 * everything from scratch by resending the current
5972 * request. Occurs very rarely, not worth optimizing. */
5973 LogRel(("%s: Ctl#%d: redo entire operation\n", __FUNCTION__, pCtl->iCtl));
5974 ataHCAsyncIOPutRequest(pDevIns, pCtl, pReq);
5975 break;
5976 }
5977 }
5978 else
5979 {
5980 Assert(iSourceSink == ATAFN_SS_NULL);
5981 ataR3CmdOK(pCtl, s, 0);
5982 }
5983 s->iIOBufferEnd = s->cbElementaryTransfer;
5984
5985 }
5986
5987 /* Do not go into the transfer phase if RESET is asserted.
5988 * The CritSect is released while waiting for the host OS
5989 * to finish the I/O, thus RESET is possible here. Most
5990 * important: do not change uAsyncIOState. */
5991 if (pCtl->fReset)
5992 break;
5993
5994 if (s->fDMA)
5995 {
5996 if (s->cbTotalTransfer)
5997 {
5998 ataSetStatus(pCtl, s, ATA_STAT_DRQ);
5999
6000 pCtl->uAsyncIOState = ATA_AIO_DMA;
6001 /* If BMDMA is already started, do the transfer now. */
6002 if (pCtl->BmDma.u8Cmd & BM_CMD_START)
6003 {
6004 Log2(("%s: Ctl#%d: message to async I/O thread, continuing DMA transfer immediately\n", __FUNCTION__, pCtl->iCtl));
6005 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataDMARequest);
6006 }
6007 }
6008 else
6009 {
6010 Assert(s->uTxDir == PDMMEDIATXDIR_NONE); /* Any transfer which has an initial transfer size of 0 must be marked as such. */
6011 /* Finish DMA transfer. */
6012 ataR3DMATransferStop(s);
6013 ataHCSetIRQ(pDevIns, pCtl, s);
6014 pCtl->uAsyncIOState = ATA_AIO_NEW;
6015 }
6016 }
6017 else
6018 {
6019 if (s->cbTotalTransfer)
6020 {
6021 ataHCPIOTransfer(pDevIns, pCtl);
6022 Assert(!pCtl->fRedo);
6023 if (s->fATAPITransfer || s->uTxDir != PDMMEDIATXDIR_TO_DEVICE)
6024 ataHCSetIRQ(pDevIns, pCtl, s);
6025
6026 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
6027 {
6028 /* Write operations and not yet finished transfers
6029 * must be completed in the async I/O thread. */
6030 pCtl->uAsyncIOState = ATA_AIO_PIO;
6031 }
6032 else
6033 {
6034 /* Finished read operation can be handled inline
6035 * in the end of PIO transfer handling code. Linux
6036 * depends on this, as it waits only briefly for
6037 * devices to become ready after incoming data
6038 * transfer. Cannot find anything in the ATA spec
6039 * that backs this assumption, but as all kernels
6040 * are affected (though most of the time it does
6041 * not cause any harm) this must work. */
6042 pCtl->uAsyncIOState = ATA_AIO_NEW;
6043 }
6044 }
6045 else
6046 {
6047 Assert(s->uTxDir == PDMMEDIATXDIR_NONE); /* Any transfer which has an initial transfer size of 0 must be marked as such. */
6048 /* Finish PIO transfer. */
6049 ataHCPIOTransfer(pDevIns, pCtl);
6050 Assert(!pCtl->fRedo);
6051 if (!s->fATAPITransfer)
6052 ataHCSetIRQ(pDevIns, pCtl, s);
6053 pCtl->uAsyncIOState = ATA_AIO_NEW;
6054 }
6055 }
6056 break;
6057 }
6058
6059 case ATA_AIO_DMA:
6060 {
6061 BMDMAState *bm = &pCtl->BmDma;
6062 PATADEVSTATE s = &pCtl->aIfs[pCtl->iAIOIf & ATA_SELECTED_IF_MASK];
6063 ATAFNSS iOriginalSourceSink = (ATAFNSS)s->iSourceSink; /* Used by the hack below, but gets reset by then. */
6064
6065 if (s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE)
6066 AssertRelease(bm->u8Cmd & BM_CMD_WRITE);
6067 else
6068 AssertRelease(!(bm->u8Cmd & BM_CMD_WRITE));
6069
6070 if (RT_LIKELY(!pCtl->fRedo))
6071 {
6072 /* The specs say that the descriptor table must not cross a
6073 * 4K boundary. */
6074 pCtl->GCPhysFirstDMADesc = bm->GCPhysAddr;
6075 pCtl->GCPhysLastDMADesc = RT_ALIGN_32(bm->GCPhysAddr + 1, _4K) - sizeof(BMDMADesc);
6076 }
6077 ataR3DMATransfer(pDevIns, pCtl, pCtlR3);
6078
6079 if (RT_UNLIKELY(pCtl->fRedo && !pCtl->fReset))
6080 {
6081 LogRel(("PIIX3 ATA: Ctl#%d: redo DMA operation\n", pCtl->iCtl));
6082 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataDMARequest);
6083 break;
6084 }
6085
6086 /* The infamous delay IRQ hack. */
6087 if ( iOriginalSourceSink == ATAFN_SS_WRITE_SECTORS
6088 && s->cbTotalTransfer == 0
6089 && pCtl->msDelayIRQ)
6090 {
6091 /* Delay IRQ for writing. Required to get the Win2K
6092 * installation work reliably (otherwise it crashes,
6093 * usually during component install). So far no better
6094 * solution has been found. */
6095 Log(("%s: delay IRQ hack\n", __FUNCTION__));
6096 ataR3LockLeave(pDevIns, pCtl);
6097 RTThreadSleep(pCtl->msDelayIRQ);
6098 ataR3LockEnter(pDevIns, pCtl);
6099 }
6100
6101 ataUnsetStatus(pCtl, s, ATA_STAT_DRQ);
6102 Assert(!pCtl->fChainedTransfer);
6103 Assert(s->iSourceSink == ATAFN_SS_NULL);
6104 if (s->fATAPITransfer)
6105 {
6106 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
6107 Log2(("%s: Ctl#%d: interrupt reason %#04x\n", __FUNCTION__, pCtl->iCtl, s->uATARegNSector));
6108 s->fATAPITransfer = false;
6109 }
6110 ataHCSetIRQ(pDevIns, pCtl, s);
6111 pCtl->uAsyncIOState = ATA_AIO_NEW;
6112 break;
6113 }
6114
6115 case ATA_AIO_PIO:
6116 {
6117 uint8_t const iIf = pCtl->iAIOIf & ATA_SELECTED_IF_MASK;
6118 pCtl->iAIOIf = iIf;
6119 PATADEVSTATE s = &pCtl->aIfs[iIf];
6120 PATADEVSTATER3 pDevR3 = &pCtlR3->aIfs[iIf];
6121
6122 uint8_t const iSourceSink = s->iSourceSink;
6123 if ( iSourceSink != ATAFN_SS_NULL
6124 && iSourceSink < RT_ELEMENTS(g_apfnSourceSinkFuncs))
6125 {
6126 bool fRedo;
6127 Log2(("%s: Ctl#%d: calling source/sink function\n", __FUNCTION__, pCtl->iCtl));
6128 fRedo = g_apfnSourceSinkFuncs[iSourceSink](pDevIns, pCtl, s, pDevR3);
6129 pCtl->fRedo = fRedo;
6130 if (RT_UNLIKELY(fRedo && !pCtl->fReset))
6131 {
6132 LogRel(("PIIX3 ATA: Ctl#%d: redo PIO operation\n", pCtl->iCtl));
6133 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataPIORequest);
6134 break;
6135 }
6136 s->iIOBufferCur = 0;
6137 s->iIOBufferEnd = s->cbElementaryTransfer;
6138 }
6139 else
6140 {
6141 /* Continue a previously started transfer. */
6142 Assert(iSourceSink == ATAFN_SS_NULL);
6143 ataUnsetStatus(pCtl, s, ATA_STAT_BUSY);
6144 ataSetStatus(pCtl, s, ATA_STAT_READY);
6145 }
6146
6147 /* It is possible that the drives on this controller get RESET
6148 * during the above call to the source/sink function. If that's
6149 * the case, don't restart the transfer and don't finish it the
6150 * usual way. RESET handling took care of all that already.
6151 * Most important: do not change uAsyncIOState. */
6152 if (pCtl->fReset)
6153 break;
6154
6155 if (s->cbTotalTransfer)
6156 {
6157 ataHCPIOTransfer(pDevIns, pCtl);
6158 ataHCSetIRQ(pDevIns, pCtl, s);
6159
6160 if (s->uTxDir == PDMMEDIATXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
6161 {
6162 /* Write operations and not yet finished transfers
6163 * must be completed in the async I/O thread. */
6164 pCtl->uAsyncIOState = ATA_AIO_PIO;
6165 }
6166 else
6167 {
6168 /* Finished read operation can be handled inline
6169 * in the end of PIO transfer handling code. Linux
6170 * depends on this, as it waits only briefly for
6171 * devices to become ready after incoming data
6172 * transfer. Cannot find anything in the ATA spec
6173 * that backs this assumption, but as all kernels
6174 * are affected (though most of the time it does
6175 * not cause any harm) this must work. */
6176 pCtl->uAsyncIOState = ATA_AIO_NEW;
6177 }
6178 }
6179 else
6180 {
6181 /* The infamous delay IRQ hack. */
6182 if (RT_UNLIKELY(pCtl->msDelayIRQ))
6183 {
6184 /* Various antique guests have buggy disk drivers silently
6185 * assuming that disk operations take a relatively long time.
6186 * Work around such bugs by holding off interrupts a bit.
6187 */
6188 Log(("%s: delay IRQ hack (PIO)\n", __FUNCTION__));
6189 ataR3LockLeave(pDevIns, pCtl);
6190 RTThreadSleep(pCtl->msDelayIRQ);
6191 ataR3LockEnter(pDevIns, pCtl);
6192 }
6193
6194 /* Finish PIO transfer. */
6195 ataHCPIOTransfer(pDevIns, pCtl);
6196 if ( !pCtl->fChainedTransfer
6197 && !s->fATAPITransfer
6198 && s->uTxDir != PDMMEDIATXDIR_FROM_DEVICE)
6199 {
6200 ataHCSetIRQ(pDevIns, pCtl, s);
6201 }
6202 pCtl->uAsyncIOState = ATA_AIO_NEW;
6203 }
6204 break;
6205 }
6206
6207 case ATA_AIO_RESET_ASSERTED:
6208 pCtl->uAsyncIOState = ATA_AIO_RESET_CLEARED;
6209 ataHCPIOTransferStop(pDevIns, pCtl, &pCtl->aIfs[0]);
6210 ataHCPIOTransferStop(pDevIns, pCtl, &pCtl->aIfs[1]);
6211 /* Do not change the DMA registers, they are not affected by the
6212 * ATA controller reset logic. It should be sufficient to issue a
6213 * new command, which is now possible as the state is cleared. */
6214 break;
6215
6216 case ATA_AIO_RESET_CLEARED:
6217 pCtl->uAsyncIOState = ATA_AIO_NEW;
6218 pCtl->fReset = false;
6219 /* Ensure that half-completed transfers are not redone. A reset
6220 * cancels the entire transfer, so continuing is wrong. */
6221 pCtl->fRedo = false;
6222 pCtl->fRedoDMALastDesc = false;
6223 LogRel(("PIIX3 ATA: Ctl#%d: finished processing RESET\n", pCtl->iCtl));
6224 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
6225 {
6226 ataR3SetSignature(&pCtl->aIfs[i]);
6227 if (pCtl->aIfs[i].fATAPI)
6228 ataSetStatusValue(pCtl, &pCtl->aIfs[i], 0); /* NOTE: READY is _not_ set */
6229 else
6230 ataSetStatusValue(pCtl, &pCtl->aIfs[i], ATA_STAT_READY | ATA_STAT_SEEK);
6231 }
6232 break;
6233
6234 case ATA_AIO_ABORT:
6235 {
6236 /* Abort the current command no matter what. There cannot be
6237 * any command activity on the other drive otherwise using
6238 * one thread per controller wouldn't work at all. */
6239 PATADEVSTATE s = &pCtl->aIfs[pReq->u.a.iIf & ATA_SELECTED_IF_MASK];
6240
6241 pCtl->uAsyncIOState = ATA_AIO_NEW;
6242 /* Do not change the DMA registers, they are not affected by the
6243 * ATA controller reset logic. It should be sufficient to issue a
6244 * new command, which is now possible as the state is cleared. */
6245 if (pReq->u.a.fResetDrive)
6246 {
6247 ataR3ResetDevice(pDevIns, pCtl, s);
6248 ataR3DeviceDiag(pCtl, s);
6249 }
6250 else
6251 {
6252 /* Stop any pending DMA transfer. */
6253 s->fDMA = false;
6254 ataHCPIOTransferStop(pDevIns, pCtl, s);
6255 ataUnsetStatus(pCtl, s, ATA_STAT_BUSY | ATA_STAT_DRQ | ATA_STAT_SEEK | ATA_STAT_ERR);
6256 ataSetStatus(pCtl, s, ATA_STAT_READY);
6257 ataHCSetIRQ(pDevIns, pCtl, s);
6258 }
6259 break;
6260 }
6261
6262 default:
6263 AssertMsgFailed(("Undefined async I/O state %d\n", pCtl->uAsyncIOState));
6264 }
6265
6266 ataR3AsyncIORemoveCurrentRequest(pDevIns, pCtl, ReqType);
6267 pReq = ataR3AsyncIOGetCurrentRequest(pDevIns, pCtl);
6268
6269 if (pCtl->uAsyncIOState == ATA_AIO_NEW && !pCtl->fChainedTransfer)
6270 {
6271# if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
6272 STAM_PROFILE_ADV_STOP(&pCtl->StatAsyncTime, a);
6273# endif
6274
6275 u64TS = RTTimeNanoTS() - u64TS;
6276 uWait = u64TS / 1000;
6277 uintptr_t const iAIOIf = pCtl->iAIOIf & ATA_SELECTED_IF_MASK;
6278 Log(("%s: Ctl#%d: LUN#%d finished I/O transaction in %d microseconds\n",
6279 __FUNCTION__, pCtl->iCtl, pCtl->aIfs[iAIOIf].iLUN, (uint32_t)(uWait)));
6280 /* Mark command as finished. */
6281 pCtl->aIfs[iAIOIf].u64CmdTS = 0;
6282
6283 /*
6284 * Release logging of command execution times depends on the
6285 * command type. ATAPI commands often take longer (due to CD/DVD
6286 * spin up time etc.) so the threshold is different.
6287 */
6288 if (pCtl->aIfs[iAIOIf].uATARegCommand != ATA_PACKET)
6289 {
6290 if (uWait > 8 * 1000 * 1000)
6291 {
6292 /*
6293 * Command took longer than 8 seconds. This is close
6294 * enough or over the guest's command timeout, so place
6295 * an entry in the release log to allow tracking such
6296 * timing errors (which are often caused by the host).
6297 */
6298 LogRel(("PIIX3 ATA: execution time for ATA command %#04x was %d seconds\n",
6299 pCtl->aIfs[iAIOIf].uATARegCommand, uWait / (1000 * 1000)));
6300 }
6301 }
6302 else
6303 {
6304 if (uWait > 20 * 1000 * 1000)
6305 {
6306 /*
6307 * Command took longer than 20 seconds. This is close
6308 * enough or over the guest's command timeout, so place
6309 * an entry in the release log to allow tracking such
6310 * timing errors (which are often caused by the host).
6311 */
6312 LogRel(("PIIX3 ATA: execution time for ATAPI command %#04x was %d seconds\n",
6313 pCtl->aIfs[iAIOIf].abATAPICmd[0], uWait / (1000 * 1000)));
6314 }
6315 }
6316
6317# if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
6318 if (uWait < pCtl->StatAsyncMinWait || !pCtl->StatAsyncMinWait)
6319 pCtl->StatAsyncMinWait = uWait;
6320 if (uWait > pCtl->StatAsyncMaxWait)
6321 pCtl->StatAsyncMaxWait = uWait;
6322
6323 STAM_COUNTER_ADD(&pCtl->StatAsyncTimeUS, uWait);
6324 STAM_COUNTER_INC(&pCtl->StatAsyncOps);
6325# endif /* DEBUG || VBOX_WITH_STATISTICS */
6326 }
6327
6328 ataR3LockLeave(pDevIns, pCtl);
6329 }
6330
6331 /* Signal the ultimate idleness. */
6332 RTThreadUserSignal(pCtlR3->hAsyncIOThread);
6333 if (pCtlR3->fSignalIdle)
6334 PDMDevHlpAsyncNotificationCompleted(pDevIns);
6335
6336 /* Cleanup the state. */
6337 /* Do not destroy request lock yet, still needed for proper shutdown. */
6338 pCtlR3->fShutdown = false;
6339
6340 Log2(("%s: Ctl#%d: return %Rrc\n", __FUNCTION__, pCtl->iCtl, rc));
6341 return rc;
6342}
6343
6344#endif /* IN_RING3 */
6345
6346static uint32_t ataBMDMACmdReadB(PATACONTROLLER pCtl, uint32_t addr)
6347{
6348 uint32_t val = pCtl->BmDma.u8Cmd;
6349 RT_NOREF(addr);
6350 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6351 return val;
6352}
6353
6354
6355static void ataBMDMACmdWriteB(PPDMDEVINS pDevIns, PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6356{
6357 RT_NOREF(pDevIns, addr);
6358 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6359 if (!(val & BM_CMD_START))
6360 {
6361 pCtl->BmDma.u8Status &= ~BM_STATUS_DMAING;
6362 pCtl->BmDma.u8Cmd = val & (BM_CMD_START | BM_CMD_WRITE);
6363 }
6364 else
6365 {
6366#ifndef IN_RC
6367 /* Check whether the guest OS wants to change DMA direction in
6368 * mid-flight. Not allowed, according to the PIIX3 specs. */
6369 Assert(!(pCtl->BmDma.u8Status & BM_STATUS_DMAING) || !((val ^ pCtl->BmDma.u8Cmd) & 0x04));
6370 uint8_t uOldBmDmaStatus = pCtl->BmDma.u8Status;
6371 pCtl->BmDma.u8Status |= BM_STATUS_DMAING;
6372 pCtl->BmDma.u8Cmd = val & (BM_CMD_START | BM_CMD_WRITE);
6373
6374 /* Do not continue DMA transfers while the RESET line is asserted. */
6375 if (pCtl->fReset)
6376 {
6377 Log2(("%s: Ctl#%d: suppressed continuing DMA transfer as RESET is active\n", __FUNCTION__, pCtl->iCtl));
6378 return;
6379 }
6380
6381 /* Do not start DMA transfers if there's a PIO transfer going on,
6382 * or if there is already a transfer started on this controller. */
6383 if ( !pCtl->aIfs[pCtl->iSelectedIf & ATA_SELECTED_IF_MASK].fDMA
6384 || (uOldBmDmaStatus & BM_STATUS_DMAING))
6385 return;
6386
6387 if (pCtl->aIfs[pCtl->iAIOIf & ATA_SELECTED_IF_MASK].uATARegStatus & ATA_STAT_DRQ)
6388 {
6389 Log2(("%s: Ctl#%d: message to async I/O thread, continuing DMA transfer\n", __FUNCTION__, pCtl->iCtl));
6390 ataHCAsyncIOPutRequest(pDevIns, pCtl, &g_ataDMARequest);
6391 }
6392#else /* !IN_RING3 */
6393 AssertMsgFailed(("DMA START handling is too complicated for RC\n"));
6394#endif /* IN_RING3 */
6395 }
6396}
6397
6398static uint32_t ataBMDMAStatusReadB(PATACONTROLLER pCtl, uint32_t addr)
6399{
6400 uint32_t val = pCtl->BmDma.u8Status;
6401 RT_NOREF(addr);
6402 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6403 return val;
6404}
6405
6406static void ataBMDMAStatusWriteB(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6407{
6408 RT_NOREF(addr);
6409 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
6410 pCtl->BmDma.u8Status = (val & (BM_STATUS_D0DMA | BM_STATUS_D1DMA))
6411 | (pCtl->BmDma.u8Status & BM_STATUS_DMAING)
6412 | (pCtl->BmDma.u8Status & ~val & (BM_STATUS_ERROR | BM_STATUS_INT));
6413}
6414
6415static uint32_t ataBMDMAAddrReadL(PATACONTROLLER pCtl, uint32_t addr)
6416{
6417 uint32_t val = (uint32_t)pCtl->BmDma.GCPhysAddr;
6418 RT_NOREF(addr);
6419 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6420 return val;
6421}
6422
6423static void ataBMDMAAddrWriteL(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6424{
6425 RT_NOREF(addr);
6426 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6427 pCtl->BmDma.GCPhysAddr = val & ~3;
6428}
6429
6430static void ataBMDMAAddrWriteLowWord(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6431{
6432 RT_NOREF(addr);
6433 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6434 pCtl->BmDma.GCPhysAddr = (pCtl->BmDma.GCPhysAddr & 0xFFFF0000) | RT_LOWORD(val & ~3);
6435
6436}
6437
6438static void ataBMDMAAddrWriteHighWord(PATACONTROLLER pCtl, uint32_t addr, uint32_t val)
6439{
6440 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
6441 RT_NOREF(addr);
6442 pCtl->BmDma.GCPhysAddr = (RT_LOWORD(val) << 16) | RT_LOWORD(pCtl->BmDma.GCPhysAddr);
6443}
6444
6445/** Helper for ataBMDMAIOPortRead and ataBMDMAIOPortWrite. */
6446#define VAL(port, size) ( ((port) & BM_DMA_CTL_IOPORTS_MASK) | ((size) << BM_DMA_CTL_IOPORTS_SHIFT) )
6447
6448/**
6449 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6450 * Port I/O Handler for bus-master DMA IN operations - both controllers.}
6451 */
6452static DECLCALLBACK(VBOXSTRICTRC)
6453ataBMDMAIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6454{
6455 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6456 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (offPort >> BM_DMA_CTL_IOPORTS_SHIFT));
6457 RT_NOREF(pvUser);
6458
6459 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
6460 if (rc == VINF_SUCCESS)
6461 {
6462 switch (VAL(offPort, cb))
6463 {
6464 case VAL(0, 1): *pu32 = ataBMDMACmdReadB(pCtl, offPort); break;
6465 case VAL(0, 2): *pu32 = ataBMDMACmdReadB(pCtl, offPort); break;
6466 case VAL(2, 1): *pu32 = ataBMDMAStatusReadB(pCtl, offPort); break;
6467 case VAL(2, 2): *pu32 = ataBMDMAStatusReadB(pCtl, offPort); break;
6468 case VAL(4, 4): *pu32 = ataBMDMAAddrReadL(pCtl, offPort); break;
6469 case VAL(0, 4):
6470 /* The SCO OpenServer tries to read 4 bytes starting from offset 0. */
6471 *pu32 = ataBMDMACmdReadB(pCtl, offPort) | (ataBMDMAStatusReadB(pCtl, offPort) << 16);
6472 break;
6473 default:
6474 ASSERT_GUEST_MSG_FAILED(("Unsupported read from port %x size=%d\n", offPort, cb));
6475 rc = VERR_IOM_IOPORT_UNUSED;
6476 break;
6477 }
6478 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6479 }
6480 return rc;
6481}
6482
6483/**
6484 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6485 * Port I/O Handler for bus-master DMA OUT operations - both controllers.}
6486 */
6487static DECLCALLBACK(VBOXSTRICTRC)
6488ataBMDMAIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6489{
6490 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6491 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (offPort >> BM_DMA_CTL_IOPORTS_SHIFT));
6492 RT_NOREF(pvUser);
6493
6494 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
6495 if (rc == VINF_SUCCESS)
6496 {
6497 switch (VAL(offPort, cb))
6498 {
6499 case VAL(0, 1):
6500#ifdef IN_RC
6501 if (u32 & BM_CMD_START)
6502 {
6503 rc = VINF_IOM_R3_IOPORT_WRITE;
6504 break;
6505 }
6506#endif
6507 ataBMDMACmdWriteB(pDevIns, pCtl, offPort, u32);
6508 break;
6509 case VAL(2, 1): ataBMDMAStatusWriteB(pCtl, offPort, u32); break;
6510 case VAL(4, 4): ataBMDMAAddrWriteL(pCtl, offPort, u32); break;
6511 case VAL(4, 2): ataBMDMAAddrWriteLowWord(pCtl, offPort, u32); break;
6512 case VAL(6, 2): ataBMDMAAddrWriteHighWord(pCtl, offPort, u32); break;
6513 default:
6514 ASSERT_GUEST_MSG_FAILED(("Unsupported write to port %x size=%d val=%x\n", offPort, cb, u32));
6515 break;
6516 }
6517 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6518 }
6519 return rc;
6520}
6521
6522#undef VAL
6523
6524#ifdef IN_RING3
6525
6526/* -=-=-=-=-=- ATASTATE::IBase -=-=-=-=-=- */
6527
6528/**
6529 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
6530 */
6531static DECLCALLBACK(void *) ataR3Status_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
6532{
6533 PATASTATER3 pThisCC = RT_FROM_MEMBER(pInterface, ATASTATER3, IBase);
6534 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThisCC->IBase);
6535 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThisCC->ILeds);
6536 return NULL;
6537}
6538
6539
6540/* -=-=-=-=-=- ATASTATE::ILeds -=-=-=-=-=- */
6541
6542/**
6543 * Gets the pointer to the status LED of a unit.
6544 *
6545 * @returns VBox status code.
6546 * @param pInterface Pointer to the interface structure containing the called function pointer.
6547 * @param iLUN The unit which status LED we desire.
6548 * @param ppLed Where to store the LED pointer.
6549 */
6550static DECLCALLBACK(int) ataR3Status_QueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
6551{
6552 if (iLUN < 4)
6553 {
6554 PATASTATER3 pThisCC = RT_FROM_MEMBER(pInterface, ATASTATER3, ILeds);
6555 PATASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PATASTATE);
6556 switch (iLUN)
6557 {
6558 case 0: *ppLed = &pThis->aCts[0].aIfs[0].Led; break;
6559 case 1: *ppLed = &pThis->aCts[0].aIfs[1].Led; break;
6560 case 2: *ppLed = &pThis->aCts[1].aIfs[0].Led; break;
6561 case 3: *ppLed = &pThis->aCts[1].aIfs[1].Led; break;
6562 }
6563 Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
6564 return VINF_SUCCESS;
6565 }
6566 return VERR_PDM_LUN_NOT_FOUND;
6567}
6568
6569
6570/* -=-=-=-=-=- ATADEVSTATE::IBase -=-=-=-=-=- */
6571
6572/**
6573 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
6574 */
6575static DECLCALLBACK(void *) ataR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
6576{
6577 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IBase);
6578 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pIfR3->IBase);
6579 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pIfR3->IPort);
6580 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pIfR3->IMountNotify);
6581 return NULL;
6582}
6583
6584
6585/* -=-=-=-=-=- ATADEVSTATE::IPort -=-=-=-=-=- */
6586
6587/**
6588 * @interface_method_impl{PDMIMEDIAPORT,pfnQueryDeviceLocation}
6589 */
6590static DECLCALLBACK(int) ataR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController,
6591 uint32_t *piInstance, uint32_t *piLUN)
6592{
6593 PATADEVSTATER3 pIfR3 = RT_FROM_MEMBER(pInterface, ATADEVSTATER3, IPort);
6594 PPDMDEVINS pDevIns = pIfR3->pDevIns;
6595
6596 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
6597 AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
6598 AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
6599
6600 *ppcszController = pDevIns->pReg->szName;
6601 *piInstance = pDevIns->iInstance;
6602 *piLUN = pIfR3->iLUN;
6603
6604 return VINF_SUCCESS;
6605}
6606
6607#endif /* IN_RING3 */
6608
6609/* -=-=-=-=-=- Wrappers -=-=-=-=-=- */
6610
6611
6612/**
6613 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6614 * Port I/O Handler for OUT operations on unpopulated IDE channels.}
6615 * @note offPort is an absolute port number!
6616 */
6617static DECLCALLBACK(VBOXSTRICTRC)
6618ataIOPortWriteEmptyBus(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6619{
6620 RT_NOREF(pDevIns, pvUser, offPort, u32, cb);
6621
6622#ifdef VBOX_STRICT
6623 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6624 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6625 Assert((uintptr_t)pvUser < 2);
6626 Assert(!pCtl->aIfs[0].fPresent && !pCtl->aIfs[1].fPresent);
6627#endif
6628
6629 /* This is simply a black hole, writes on unpopulated IDE channels elicit no response. */
6630 LogFunc(("Empty bus: Ignoring write to port %x val=%x size=%d\n", offPort, u32, cb));
6631 return VINF_SUCCESS;
6632}
6633
6634
6635/**
6636 * @callback_method_impl{FNIOMIOPORTNEWIN,
6637 * Port I/O Handler for IN operations on unpopulated IDE channels.}
6638 * @note offPort is an absolute port number!
6639 */
6640static DECLCALLBACK(VBOXSTRICTRC)
6641ataIOPortReadEmptyBus(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6642{
6643 RT_NOREF(pDevIns, offPort, pvUser);
6644
6645#ifdef VBOX_STRICT
6646 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6647 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6648 Assert((uintptr_t)pvUser < 2);
6649 Assert(cb <= 4);
6650 Assert(!pCtl->aIfs[0].fPresent && !pCtl->aIfs[1].fPresent);
6651#endif
6652
6653 /*
6654 * Reads on unpopulated IDE channels behave in a unique way. Newer ATA specifications
6655 * mandate that the host must have a pull-down resistor on signal DD7. As a consequence,
6656 * bit 7 is always read as zero. This greatly aids in ATA device detection because
6657 * the empty bus does not look to the host like a permanently busy drive, and no long
6658 * timeouts (on the order of 30 seconds) are needed.
6659 *
6660 * The response is entirely static and does not require any locking or other fancy
6661 * stuff. Breaking it out simplifies the I/O handling for non-empty IDE channels which
6662 * is quite complicated enough already.
6663 */
6664 *pu32 = ATA_EMPTY_BUS_DATA_32 >> ((4 - cb) * 8);
6665 LogFunc(("Empty bus: port %x val=%x size=%d\n", offPort, *pu32, cb));
6666 return VINF_SUCCESS;
6667}
6668
6669
6670/**
6671 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6672 * Port I/O Handler for primary port range OUT operations.}
6673 * @note offPort is an absolute port number!
6674 */
6675static DECLCALLBACK(VBOXSTRICTRC)
6676ataIOPortWrite1Other(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6677{
6678 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6679 uintptr_t iCtl = (uintptr_t)pvUser % RT_ELEMENTS(pThis->aCts);
6680 PATACONTROLLER pCtl = &pThis->aCts[iCtl];
6681
6682 Assert((uintptr_t)pvUser < 2);
6683
6684 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
6685 if (rc == VINF_SUCCESS)
6686 {
6687 /* Writes to the other command block ports should be 8-bit only. If they
6688 * are not, the high bits are simply discarded. Undocumented, but observed
6689 * on a real PIIX4 system.
6690 */
6691 if (cb > 1)
6692 Log(("ataIOPortWrite1: suspect write to port %x val=%x size=%d\n", offPort, u32, cb));
6693
6694 rc = ataIOPortWriteU8(pDevIns, pCtl, offPort, u32, iCtl);
6695
6696 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6697 }
6698 return rc;
6699}
6700
6701
6702/**
6703 * @callback_method_impl{FNIOMIOPORTNEWIN,
6704 * Port I/O Handler for primary port range IN operations.}
6705 * @note offPort is an absolute port number!
6706 */
6707static DECLCALLBACK(VBOXSTRICTRC)
6708ataIOPortRead1Other(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6709{
6710 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6711 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6712
6713 Assert((uintptr_t)pvUser < 2);
6714
6715 VBOXSTRICTRC rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
6716 if (rc == VINF_SUCCESS)
6717 {
6718 /* Reads from the other command block registers should be 8-bit only.
6719 * If they are not, the low byte is propagated to the high bits.
6720 * Undocumented, but observed on a real PIIX4 system.
6721 */
6722 rc = ataIOPortReadU8(pDevIns, pCtl, offPort, pu32);
6723 if (cb > 1)
6724 {
6725 uint32_t pad;
6726
6727 /* Replicate the 8-bit result into the upper three bytes. */
6728 pad = *pu32 & 0xff;
6729 pad = pad | (pad << 8);
6730 pad = pad | (pad << 16);
6731 *pu32 = pad;
6732 Log(("ataIOPortRead1: suspect read from port %x size=%d\n", offPort, cb));
6733 }
6734 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6735 }
6736 return rc;
6737}
6738
6739
6740/**
6741 * @callback_method_impl{FNIOMIOPORTNEWOUT,
6742 * Port I/O Handler for secondary port range OUT operations.}
6743 * @note offPort is an absolute port number!
6744 */
6745static DECLCALLBACK(VBOXSTRICTRC)
6746ataIOPortWrite2(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
6747{
6748 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6749 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6750 int rc;
6751
6752 Assert((uintptr_t)pvUser < 2);
6753
6754 if (cb == 1)
6755 {
6756 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_WRITE);
6757 if (rc == VINF_SUCCESS)
6758 {
6759 rc = ataControlWrite(pDevIns, pCtl, u32, offPort);
6760 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6761 }
6762 }
6763 else
6764 {
6765 Log(("ataIOPortWrite2: ignoring write to port %x+%x size=%d!\n", offPort, pCtl->IOPortBase2, cb));
6766 rc = VINF_SUCCESS;
6767 }
6768 return rc;
6769}
6770
6771
6772/**
6773 * @callback_method_impl{FNIOMIOPORTNEWIN,
6774 * Port I/O Handler for secondary port range IN operations.}
6775 * @note offPort is an absolute port number!
6776 */
6777static DECLCALLBACK(VBOXSTRICTRC)
6778ataIOPortRead2(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
6779{
6780 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6781 PATACONTROLLER pCtl = &RT_SAFE_SUBSCRIPT(pThis->aCts, (uintptr_t)pvUser);
6782 int rc;
6783
6784 Assert((uintptr_t)pvUser < 2);
6785
6786 if (cb == 1)
6787 {
6788 rc = PDMDevHlpCritSectEnter(pDevIns, &pCtl->lock, VINF_IOM_R3_IOPORT_READ);
6789 if (rc == VINF_SUCCESS)
6790 {
6791 *pu32 = ataStatusRead(pCtl, offPort);
6792 PDMDevHlpCritSectLeave(pDevIns, &pCtl->lock);
6793 }
6794 }
6795 else
6796 {
6797 Log(("ataIOPortRead2: ignoring read from port %x+%x size=%d!\n", offPort, pCtl->IOPortBase2, cb));
6798 rc = VERR_IOM_IOPORT_UNUSED;
6799 }
6800 return rc;
6801}
6802
6803#ifdef IN_RING3
6804
6805/**
6806 * Detach notification.
6807 *
6808 * The DVD drive has been unplugged.
6809 *
6810 * @param pDevIns The device instance.
6811 * @param iLUN The logical unit which is being detached.
6812 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
6813 */
6814static DECLCALLBACK(void) ataR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
6815{
6816 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
6817 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
6818 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
6819 ("PIIX3IDE: Device does not support hotplugging\n")); RT_NOREF(fFlags);
6820
6821 /*
6822 * Locate the controller and stuff.
6823 */
6824 unsigned iController = iLUN / RT_ELEMENTS(pThis->aCts[0].aIfs);
6825 AssertReleaseMsg(iController < RT_ELEMENTS(pThis->aCts), ("iController=%d iLUN=%d\n", iController, iLUN));
6826 PATACONTROLLER pCtl = &pThis->aCts[iController];
6827 PATACONTROLLERR3 pCtlR3 = &pThisCC->aCts[iController];
6828
6829 unsigned iInterface = iLUN % RT_ELEMENTS(pThis->aCts[0].aIfs);
6830 PATADEVSTATE pIf = &pCtl->aIfs[iInterface];
6831 PATADEVSTATER3 pIfR3 = &pCtlR3->aIfs[iInterface];
6832
6833 /*
6834 * Zero some important members.
6835 */
6836 pIfR3->pDrvBase = NULL;
6837 pIfR3->pDrvMedia = NULL;
6838 pIfR3->pDrvMount = NULL;
6839 pIf->fPresent = false;
6840
6841 /*
6842 * In case there was a medium inserted.
6843 */
6844 ataR3MediumRemoved(pIf);
6845}
6846
6847
6848/**
6849 * Configure a LUN.
6850 *
6851 * @returns VBox status code.
6852 * @param pIf The ATA unit state, shared bits.
6853 * @param pIfR3 The ATA unit state, ring-3 bits.
6854 */
6855static int ataR3ConfigLun(PATADEVSTATE pIf, PATADEVSTATER3 pIfR3)
6856{
6857 /*
6858 * Query Block, Bios and Mount interfaces.
6859 */
6860 pIfR3->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pIfR3->pDrvBase, PDMIMEDIA);
6861 if (!pIfR3->pDrvMedia)
6862 {
6863 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pIf->iLUN));
6864 return VERR_PDM_MISSING_INTERFACE;
6865 }
6866
6867 pIfR3->pDrvMount = PDMIBASE_QUERY_INTERFACE(pIfR3->pDrvBase, PDMIMOUNT);
6868 pIf->fPresent = true;
6869
6870 /*
6871 * Validate type.
6872 */
6873 PDMMEDIATYPE enmType = pIfR3->pDrvMedia->pfnGetType(pIfR3->pDrvMedia);
6874 if ( enmType != PDMMEDIATYPE_CDROM
6875 && enmType != PDMMEDIATYPE_DVD
6876 && enmType != PDMMEDIATYPE_HARD_DISK)
6877 {
6878 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd-rom. enmType=%d\n", pIf->iLUN, enmType));
6879 return VERR_PDM_UNSUPPORTED_BLOCK_TYPE;
6880 }
6881 if ( ( enmType == PDMMEDIATYPE_DVD
6882 || enmType == PDMMEDIATYPE_CDROM)
6883 && !pIfR3->pDrvMount)
6884 {
6885 AssertMsgFailed(("Internal error: cdrom without a mountable interface, WTF???!\n"));
6886 return VERR_INTERNAL_ERROR;
6887 }
6888 pIf->fATAPI = enmType == PDMMEDIATYPE_DVD || enmType == PDMMEDIATYPE_CDROM;
6889 pIf->fATAPIPassthrough = pIf->fATAPI && pIfR3->pDrvMedia->pfnSendCmd != NULL;
6890
6891 /*
6892 * Allocate I/O buffer.
6893 */
6894 if (pIf->fATAPI)
6895 pIf->cbSector = 2048; /* Not required for ATAPI, one medium can have multiple sector sizes. */
6896 else
6897 {
6898 pIf->cbSector = pIfR3->pDrvMedia->pfnGetSectorSize(pIfR3->pDrvMedia);
6899 AssertLogRelMsgReturn(pIf->cbSector > 0 && pIf->cbSector <= ATA_MAX_SECTOR_SIZE,
6900 ("Unsupported sector size on LUN#%u: %#x (%d)\n", pIf->iLUN, pIf->cbSector, pIf->cbSector),
6901 VERR_OUT_OF_RANGE);
6902 }
6903
6904 if (pIf->cbIOBuffer)
6905 {
6906 /* Buffer is (probably) already allocated. Validate the fields,
6907 * because memory corruption can also overwrite pIf->cbIOBuffer. */
6908 if (pIf->fATAPI)
6909 AssertLogRelReturn(pIf->cbIOBuffer == _128K, VERR_BUFFER_OVERFLOW);
6910 else
6911 AssertLogRelReturn(pIf->cbIOBuffer == ATA_MAX_MULT_SECTORS * pIf->cbSector, VERR_BUFFER_OVERFLOW);
6912 }
6913 else
6914 {
6915 if (pIf->fATAPI)
6916 pIf->cbIOBuffer = _128K;
6917 else
6918 pIf->cbIOBuffer = ATA_MAX_MULT_SECTORS * pIf->cbSector;
6919 }
6920 AssertCompile(_128K <= ATA_MAX_IO_BUFFER_SIZE);
6921 AssertCompileSize(pIf->abIOBuffer, ATA_MAX_IO_BUFFER_SIZE);
6922 AssertLogRelMsgReturn(pIf->cbIOBuffer <= ATA_MAX_IO_BUFFER_SIZE,
6923 ("LUN#%u: cbIOBuffer=%#x (%u)\n", pIf->iLUN, pIf->cbIOBuffer, pIf->cbIOBuffer),
6924 VERR_BUFFER_OVERFLOW);
6925
6926 /*
6927 * Init geometry (only for non-CD/DVD media).
6928 */
6929 int rc = VINF_SUCCESS;
6930 uint32_t cRegions = pIfR3->pDrvMedia->pfnGetRegionCount(pIfR3->pDrvMedia);
6931 pIf->cTotalSectors = 0;
6932 for (uint32_t i = 0; i < cRegions; i++)
6933 {
6934 uint64_t cBlocks = 0;
6935 rc = pIfR3->pDrvMedia->pfnQueryRegionProperties(pIfR3->pDrvMedia, i, NULL, &cBlocks, NULL, NULL);
6936 AssertRC(rc);
6937 pIf->cTotalSectors += cBlocks;
6938 }
6939
6940 if (pIf->fATAPI)
6941 {
6942 pIf->PCHSGeometry.cCylinders = 0; /* dummy */
6943 pIf->PCHSGeometry.cHeads = 0; /* dummy */
6944 pIf->PCHSGeometry.cSectors = 0; /* dummy */
6945 LogRel(("PIIX3 ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n",
6946 pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled")));
6947 }
6948 else
6949 {
6950 rc = pIfR3->pDrvMedia->pfnBiosGetPCHSGeometry(pIfR3->pDrvMedia, &pIf->PCHSGeometry);
6951 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED)
6952 {
6953 pIf->PCHSGeometry.cCylinders = 0;
6954 pIf->PCHSGeometry.cHeads = 16; /*??*/
6955 pIf->PCHSGeometry.cSectors = 63; /*??*/
6956 }
6957 else if (rc == VERR_PDM_GEOMETRY_NOT_SET)
6958 {
6959 pIf->PCHSGeometry.cCylinders = 0; /* autodetect marker */
6960 rc = VINF_SUCCESS;
6961 }
6962 AssertRC(rc);
6963
6964 if ( pIf->PCHSGeometry.cCylinders == 0
6965 || pIf->PCHSGeometry.cHeads == 0
6966 || pIf->PCHSGeometry.cSectors == 0
6967 )
6968 {
6969 uint64_t cCylinders = pIf->cTotalSectors / (16 * 63);
6970 pIf->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
6971 pIf->PCHSGeometry.cHeads = 16;
6972 pIf->PCHSGeometry.cSectors = 63;
6973 /* Set the disk geometry information. Ignore errors. */
6974 pIfR3->pDrvMedia->pfnBiosSetPCHSGeometry(pIfR3->pDrvMedia, &pIf->PCHSGeometry);
6975 rc = VINF_SUCCESS;
6976 }
6977 LogRel(("PIIX3 ATA: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n",
6978 pIf->iLUN, pIf->PCHSGeometry.cCylinders, pIf->PCHSGeometry.cHeads, pIf->PCHSGeometry.cSectors,
6979 pIf->cTotalSectors));
6980
6981 if (pIfR3->pDrvMedia->pfnDiscard)
6982 LogRel(("PIIX3 ATA: LUN#%d: TRIM enabled\n", pIf->iLUN));
6983 }
6984 /* Initialize the translated geometry. */
6985 pIf->XCHSGeometry = pIf->PCHSGeometry;
6986
6987 /*
6988 * Check if SMP system to adjust the agressiveness of the busy yield hack (@bugref{1960}).
6989 *
6990 * The hack is an ancient (2006?) one for dealing with UNI CPU systems where EMT
6991 * would potentially monopolise the CPU and starve I/O threads. It causes the EMT to
6992 * yield it's timeslice if the guest polls the status register during I/O. On modern
6993 * multicore and multithreaded systems, yielding EMT too often may have adverse
6994 * effects (slow grub) so we aim at avoiding repeating the yield there too often.
6995 */
6996 RTCPUID cCpus = RTMpGetOnlineCount();
6997 if (cCpus <= 1)
6998 {
6999 pIf->cBusyStatusHackR3Rate = 1;
7000 pIf->cBusyStatusHackRZRate = 7;
7001 }
7002 else if (cCpus <= 2)
7003 {
7004 pIf->cBusyStatusHackR3Rate = 3;
7005 pIf->cBusyStatusHackRZRate = 15;
7006 }
7007 else if (cCpus <= 4)
7008 {
7009 pIf->cBusyStatusHackR3Rate = 15;
7010 pIf->cBusyStatusHackRZRate = 31;
7011 }
7012 else
7013 {
7014 pIf->cBusyStatusHackR3Rate = 127;
7015 pIf->cBusyStatusHackRZRate = 127;
7016 }
7017
7018 return rc;
7019}
7020
7021
7022/**
7023 * Attach command.
7024 *
7025 * This is called when we change block driver for the DVD drive.
7026 *
7027 * @returns VBox status code.
7028 * @param pDevIns The device instance.
7029 * @param iLUN The logical unit which is being detached.
7030 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
7031 */
7032static DECLCALLBACK(int) ataR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
7033{
7034 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7035 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7036
7037 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
7038 ("PIIX3IDE: Device does not support hotplugging\n"),
7039 VERR_INVALID_PARAMETER);
7040
7041 /*
7042 * Locate the controller and stuff.
7043 */
7044 unsigned const iController = iLUN / RT_ELEMENTS(pThis->aCts[0].aIfs);
7045 AssertReleaseMsg(iController < RT_ELEMENTS(pThis->aCts), ("iController=%d iLUN=%d\n", iController, iLUN));
7046 PATACONTROLLER pCtl = &pThis->aCts[iController];
7047 PATACONTROLLERR3 pCtlR3 = &pThisCC->aCts[iController];
7048
7049 unsigned const iInterface = iLUN % RT_ELEMENTS(pThis->aCts[0].aIfs);
7050 PATADEVSTATE pIf = &pCtl->aIfs[iInterface];
7051 PATADEVSTATER3 pIfR3 = &pCtlR3->aIfs[iInterface];
7052
7053 /* the usual paranoia */
7054 AssertRelease(!pIfR3->pDrvBase);
7055 AssertRelease(!pIfR3->pDrvMedia);
7056 Assert(pIf->iLUN == iLUN);
7057
7058 /*
7059 * Try attach the block device and get the interfaces,
7060 * required as well as optional.
7061 */
7062 int rc = PDMDevHlpDriverAttach(pDevIns, pIf->iLUN, &pIfR3->IBase, &pIfR3->pDrvBase, NULL);
7063 if (RT_SUCCESS(rc))
7064 {
7065 rc = ataR3ConfigLun(pIf, pIfR3);
7066 /*
7067 * In case there is a medium inserted.
7068 */
7069 ataR3MediumInserted(pIf);
7070 ataR3MediumTypeSet(pIf, ATA_MEDIA_TYPE_UNKNOWN);
7071 }
7072 else
7073 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", pIf->iLUN, rc));
7074
7075 if (RT_FAILURE(rc))
7076 {
7077 pIfR3->pDrvBase = NULL;
7078 pIfR3->pDrvMedia = NULL;
7079 pIfR3->pDrvMount = NULL;
7080 pIf->fPresent = false;
7081 }
7082 return rc;
7083}
7084
7085
7086/**
7087 * Resume notification.
7088 *
7089 * @returns VBox status code.
7090 * @param pDevIns The device instance data.
7091 */
7092static DECLCALLBACK(void) ataR3Resume(PPDMDEVINS pDevIns)
7093{
7094 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7095 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7096
7097 Log(("%s:\n", __FUNCTION__));
7098 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7099 {
7100 if (pThis->aCts[i].fRedo && pThis->aCts[i].fRedoIdle)
7101 {
7102 int rc = RTSemEventSignal(pThisCC->aCts[i].hSuspendIOSem);
7103 AssertRC(rc);
7104 }
7105 }
7106 return;
7107}
7108
7109
7110/**
7111 * Checks if all (both) the async I/O threads have quiesced.
7112 *
7113 * @returns true on success.
7114 * @returns false when one or more threads is still processing.
7115 * @param pDevIns Pointer to the PDM device instance.
7116 */
7117static bool ataR3AllAsyncIOIsIdle(PPDMDEVINS pDevIns)
7118{
7119 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7120 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7121
7122 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7123 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7124 {
7125 bool fRc = ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/);
7126 if (!fRc)
7127 {
7128 /* Make it signal PDM & itself when its done */
7129 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].AsyncIORequestLock, VERR_IGNORED);
7130 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].AsyncIORequestLock, rcLock);
7131
7132 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, true);
7133
7134 PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].AsyncIORequestLock);
7135
7136 fRc = ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/);
7137 if (!fRc)
7138 {
7139#if 0 /** @todo Need to do some time tracking here... */
7140 LogRel(("PIIX3 ATA: Ctl#%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",
7141 i, pThis->aCts[i].iSelectedIf, pThis->aCts[i].iAIOIf,
7142 pThis->aCts[i].aIfs[0].uATARegCommand, pThis->aCts[i].aIfs[1].uATARegCommand));
7143#endif
7144 return false;
7145 }
7146 }
7147 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, false);
7148 }
7149 return true;
7150}
7151
7152/**
7153 * Prepare state save and load operation.
7154 *
7155 * @returns VBox status code.
7156 * @param pDevIns Device instance of the device which registered the data unit.
7157 * @param pSSM SSM operation handle.
7158 */
7159static DECLCALLBACK(int) ataR3SaveLoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
7160{
7161 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7162 RT_NOREF(pSSM);
7163
7164 /* sanity - the suspend notification will wait on the async stuff. */
7165 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7166 AssertLogRelMsgReturn(ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/),
7167 ("i=%u\n", i),
7168 VERR_SSM_IDE_ASYNC_TIMEOUT);
7169 return VINF_SUCCESS;
7170}
7171
7172/**
7173 * @copydoc FNSSMDEVLIVEEXEC
7174 */
7175static DECLCALLBACK(int) ataR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
7176{
7177 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7178 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7179 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7180 RT_NOREF(uPass);
7181
7182 pHlp->pfnSSMPutU8(pSSM, (uint8_t)pThis->enmChipset);
7183 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7184 {
7185 pHlp->pfnSSMPutBool(pSSM, true); /* For controller enabled / disabled. */
7186 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7187 {
7188 pHlp->pfnSSMPutBool(pSSM, pThisCC->aCts[i].aIfs[j].pDrvBase != NULL);
7189 pHlp->pfnSSMPutStrZ(pSSM, pThis->aCts[i].aIfs[j].szSerialNumber);
7190 pHlp->pfnSSMPutStrZ(pSSM, pThis->aCts[i].aIfs[j].szFirmwareRevision);
7191 pHlp->pfnSSMPutStrZ(pSSM, pThis->aCts[i].aIfs[j].szModelNumber);
7192 }
7193 }
7194
7195 return VINF_SSM_DONT_CALL_AGAIN;
7196}
7197
7198/**
7199 * @copydoc FNSSMDEVSAVEEXEC
7200 */
7201static DECLCALLBACK(int) ataR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
7202{
7203 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7204 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7205
7206 ataR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
7207
7208 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7209 {
7210 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].iSelectedIf);
7211 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].iAIOIf);
7212 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].uAsyncIOState);
7213 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fChainedTransfer);
7214 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fReset);
7215 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fRedo);
7216 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fRedoIdle);
7217 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].fRedoDMALastDesc);
7218 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].BmDma, sizeof(pThis->aCts[i].BmDma));
7219 pHlp->pfnSSMPutGCPhys32(pSSM, pThis->aCts[i].GCPhysFirstDMADesc);
7220 pHlp->pfnSSMPutGCPhys32(pSSM, pThis->aCts[i].GCPhysLastDMADesc);
7221 pHlp->pfnSSMPutGCPhys32(pSSM, pThis->aCts[i].GCPhysRedoDMABuffer);
7222 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].cbRedoDMABuffer);
7223
7224 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7225 {
7226 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fLBA48);
7227 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fATAPI);
7228 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fIrqPending);
7229 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].cMultSectors);
7230 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cCylinders);
7231 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cHeads);
7232 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].XCHSGeometry.cSectors);
7233 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cSectorsPerIRQ);
7234 pHlp->pfnSSMPutU64(pSSM, pThis->aCts[i].aIfs[j].cTotalSectors);
7235 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegFeature);
7236 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegFeatureHOB);
7237 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegError);
7238 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegNSector);
7239 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegNSectorHOB);
7240 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegSector);
7241 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegSectorHOB);
7242 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegLCyl);
7243 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegLCylHOB);
7244 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegHCyl);
7245 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegHCylHOB);
7246 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegSelect);
7247 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegStatus);
7248 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegCommand);
7249 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATARegDevCtl);
7250 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uATATransferMode);
7251 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].uTxDir);
7252 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].iBeginTransfer);
7253 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].iSourceSink);
7254 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fDMA);
7255 pHlp->pfnSSMPutBool(pSSM, pThis->aCts[i].aIfs[j].fATAPITransfer);
7256 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbTotalTransfer);
7257 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbElementaryTransfer);
7258 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferCur);
7259 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferEnd);
7260 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferPIODataStart);
7261 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iIOBufferPIODataEnd);
7262 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].iATAPILBA);
7263 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbATAPISector);
7264 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].aIfs[j].abATAPICmd, sizeof(pThis->aCts[i].aIfs[j].abATAPICmd));
7265 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].aIfs[j].abATAPISense, sizeof(pThis->aCts[i].aIfs[j].abATAPISense));
7266 pHlp->pfnSSMPutU8(pSSM, pThis->aCts[i].aIfs[j].cNotifiedMediaChange);
7267 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].MediaEventStatus);
7268 pHlp->pfnSSMPutMem(pSSM, &pThis->aCts[i].aIfs[j].Led, sizeof(pThis->aCts[i].aIfs[j].Led));
7269 pHlp->pfnSSMPutU32(pSSM, pThis->aCts[i].aIfs[j].cbIOBuffer);
7270 if (pThis->aCts[i].aIfs[j].cbIOBuffer)
7271 pHlp->pfnSSMPutMem(pSSM, pThis->aCts[i].aIfs[j].abIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer);
7272 }
7273 }
7274
7275 return pHlp->pfnSSMPutU32(pSSM, UINT32_MAX); /* sanity/terminator */
7276}
7277
7278/**
7279 * Converts the LUN number into a message string.
7280 */
7281static const char *ataR3StringifyLun(unsigned iLun)
7282{
7283 switch (iLun)
7284 {
7285 case 0: return "primary master";
7286 case 1: return "primary slave";
7287 case 2: return "secondary master";
7288 case 3: return "secondary slave";
7289 default: AssertFailedReturn("unknown lun");
7290 }
7291}
7292
7293/**
7294 * FNSSMDEVLOADEXEC
7295 */
7296static DECLCALLBACK(int) ataR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
7297{
7298 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7299 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7300 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7301 int rc;
7302 uint32_t u32;
7303
7304 if ( uVersion != ATA_SAVED_STATE_VERSION
7305 && uVersion != ATA_SAVED_STATE_VERSION_VBOX_30
7306 && uVersion != ATA_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE
7307 && uVersion != ATA_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS
7308 && uVersion != ATA_SAVED_STATE_VERSION_WITH_BOOL_TYPE)
7309 {
7310 AssertMsgFailed(("uVersion=%d\n", uVersion));
7311 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
7312 }
7313
7314 /*
7315 * Verify the configuration.
7316 */
7317 if (uVersion > ATA_SAVED_STATE_VERSION_VBOX_30)
7318 {
7319 uint8_t u8Type;
7320 rc = pHlp->pfnSSMGetU8(pSSM, &u8Type);
7321 AssertRCReturn(rc, rc);
7322 if ((CHIPSET)u8Type != pThis->enmChipset)
7323 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch: enmChipset - saved=%u config=%u"), u8Type, pThis->enmChipset);
7324
7325 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7326 {
7327 bool fEnabled;
7328 rc = pHlp->pfnSSMGetBool(pSSM, &fEnabled);
7329 AssertRCReturn(rc, rc);
7330 if (!fEnabled)
7331 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Ctr#%u onfig mismatch: fEnabled != true"), i);
7332
7333 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7334 {
7335 ATADEVSTATE const *pIf = &pThis->aCts[i].aIfs[j];
7336 ATADEVSTATER3 const *pIfR3 = &pThisCC->aCts[i].aIfs[j];
7337
7338 bool fInUse;
7339 rc = pHlp->pfnSSMGetBool(pSSM, &fInUse);
7340 AssertRCReturn(rc, rc);
7341 if (fInUse != (pIfR3->pDrvBase != NULL))
7342 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS,
7343 N_("The %s VM is missing a %s device. Please make sure the source and target VMs have compatible storage configurations"),
7344 fInUse ? "target" : "source", ataR3StringifyLun(pIf->iLUN) );
7345
7346 char szSerialNumber[ATA_SERIAL_NUMBER_LENGTH+1];
7347 rc = pHlp->pfnSSMGetStrZ(pSSM, szSerialNumber, sizeof(szSerialNumber));
7348 AssertRCReturn(rc, rc);
7349 if (strcmp(szSerialNumber, pIf->szSerialNumber))
7350 LogRel(("PIIX3 ATA: LUN#%u config mismatch: Serial number - saved='%s' config='%s'\n",
7351 pIf->iLUN, szSerialNumber, pIf->szSerialNumber));
7352
7353 char szFirmwareRevision[ATA_FIRMWARE_REVISION_LENGTH+1];
7354 rc = pHlp->pfnSSMGetStrZ(pSSM, szFirmwareRevision, sizeof(szFirmwareRevision));
7355 AssertRCReturn(rc, rc);
7356 if (strcmp(szFirmwareRevision, pIf->szFirmwareRevision))
7357 LogRel(("PIIX3 ATA: LUN#%u config mismatch: Firmware revision - saved='%s' config='%s'\n",
7358 pIf->iLUN, szFirmwareRevision, pIf->szFirmwareRevision));
7359
7360 char szModelNumber[ATA_MODEL_NUMBER_LENGTH+1];
7361 rc = pHlp->pfnSSMGetStrZ(pSSM, szModelNumber, sizeof(szModelNumber));
7362 AssertRCReturn(rc, rc);
7363 if (strcmp(szModelNumber, pIf->szModelNumber))
7364 LogRel(("PIIX3 ATA: LUN#%u config mismatch: Model number - saved='%s' config='%s'\n",
7365 pIf->iLUN, szModelNumber, pIf->szModelNumber));
7366 }
7367 }
7368 }
7369 if (uPass != SSM_PASS_FINAL)
7370 return VINF_SUCCESS;
7371
7372 /*
7373 * Restore valid parts of the ATASTATE structure
7374 */
7375 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7376 {
7377 /* integrity check */
7378 if (!ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false))
7379 {
7380 AssertMsgFailed(("Async I/O for controller %d is active\n", i));
7381 return VERR_INTERNAL_ERROR_4;
7382 }
7383
7384 rc = pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].iSelectedIf);
7385 AssertRCReturn(rc, rc);
7386 AssertLogRelMsgStmt(pThis->aCts[i].iSelectedIf == (pThis->aCts[i].iSelectedIf & ATA_SELECTED_IF_MASK),
7387 ("iSelectedIf = %d\n", pThis->aCts[i].iSelectedIf),
7388 pThis->aCts[i].iSelectedIf &= ATA_SELECTED_IF_MASK);
7389 rc = pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].iAIOIf);
7390 AssertRCReturn(rc, rc);
7391 AssertLogRelMsgStmt(pThis->aCts[i].iAIOIf == (pThis->aCts[i].iAIOIf & ATA_SELECTED_IF_MASK),
7392 ("iAIOIf = %d\n", pThis->aCts[i].iAIOIf),
7393 pThis->aCts[i].iAIOIf &= ATA_SELECTED_IF_MASK);
7394 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].uAsyncIOState);
7395 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fChainedTransfer);
7396 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fReset);
7397 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fRedo);
7398 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fRedoIdle);
7399 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].fRedoDMALastDesc);
7400 pHlp->pfnSSMGetMem(pSSM, &pThis->aCts[i].BmDma, sizeof(pThis->aCts[i].BmDma));
7401 pHlp->pfnSSMGetGCPhys32(pSSM, &pThis->aCts[i].GCPhysFirstDMADesc);
7402 pHlp->pfnSSMGetGCPhys32(pSSM, &pThis->aCts[i].GCPhysLastDMADesc);
7403 pHlp->pfnSSMGetGCPhys32(pSSM, &pThis->aCts[i].GCPhysRedoDMABuffer);
7404 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].cbRedoDMABuffer);
7405
7406 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7407 {
7408 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fLBA48);
7409 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fATAPI);
7410 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fIrqPending);
7411 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].cMultSectors);
7412 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cCylinders);
7413 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cHeads);
7414 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].XCHSGeometry.cSectors);
7415 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cSectorsPerIRQ);
7416 pHlp->pfnSSMGetU64(pSSM, &pThis->aCts[i].aIfs[j].cTotalSectors);
7417 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegFeature);
7418 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegFeatureHOB);
7419 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegError);
7420 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegNSector);
7421 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegNSectorHOB);
7422 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegSector);
7423 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegSectorHOB);
7424 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegLCyl);
7425 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegLCylHOB);
7426 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegHCyl);
7427 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegHCylHOB);
7428 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegSelect);
7429 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegStatus);
7430 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegCommand);
7431 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATARegDevCtl);
7432 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uATATransferMode);
7433 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].uTxDir);
7434 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].iBeginTransfer);
7435 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].iSourceSink);
7436 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fDMA);
7437 pHlp->pfnSSMGetBool(pSSM, &pThis->aCts[i].aIfs[j].fATAPITransfer);
7438 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cbTotalTransfer);
7439 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cbElementaryTransfer);
7440 /* NB: cbPIOTransferLimit could be saved/restored but it's sufficient
7441 * to re-calculate it here, with a tiny risk that it could be
7442 * unnecessarily low for the current transfer only. Could be changed
7443 * when changing the saved state in the future.
7444 */
7445 pThis->aCts[i].aIfs[j].cbPIOTransferLimit = (pThis->aCts[i].aIfs[j].uATARegHCyl << 8) | pThis->aCts[i].aIfs[j].uATARegLCyl;
7446 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferCur);
7447 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferEnd);
7448 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferPIODataStart);
7449 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iIOBufferPIODataEnd);
7450 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].iATAPILBA);
7451 pHlp->pfnSSMGetU32(pSSM, &pThis->aCts[i].aIfs[j].cbATAPISector);
7452 pHlp->pfnSSMGetMem(pSSM, &pThis->aCts[i].aIfs[j].abATAPICmd, sizeof(pThis->aCts[i].aIfs[j].abATAPICmd));
7453 if (uVersion > ATA_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE)
7454 pHlp->pfnSSMGetMem(pSSM, pThis->aCts[i].aIfs[j].abATAPISense, sizeof(pThis->aCts[i].aIfs[j].abATAPISense));
7455 else
7456 {
7457 uint8_t uATAPISenseKey, uATAPIASC;
7458 memset(pThis->aCts[i].aIfs[j].abATAPISense, '\0', sizeof(pThis->aCts[i].aIfs[j].abATAPISense));
7459 pThis->aCts[i].aIfs[j].abATAPISense[0] = 0x70 | (1 << 7);
7460 pThis->aCts[i].aIfs[j].abATAPISense[7] = 10;
7461 pHlp->pfnSSMGetU8(pSSM, &uATAPISenseKey);
7462 pHlp->pfnSSMGetU8(pSSM, &uATAPIASC);
7463 pThis->aCts[i].aIfs[j].abATAPISense[2] = uATAPISenseKey & 0x0f;
7464 pThis->aCts[i].aIfs[j].abATAPISense[12] = uATAPIASC;
7465 }
7466 /** @todo triple-check this hack after passthrough is working */
7467 pHlp->pfnSSMGetU8(pSSM, &pThis->aCts[i].aIfs[j].cNotifiedMediaChange);
7468 if (uVersion > ATA_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
7469 pHlp->pfnSSMGetU32V(pSSM, &pThis->aCts[i].aIfs[j].MediaEventStatus);
7470 else
7471 pThis->aCts[i].aIfs[j].MediaEventStatus = ATA_EVENT_STATUS_UNCHANGED;
7472 pHlp->pfnSSMGetMem(pSSM, &pThis->aCts[i].aIfs[j].Led, sizeof(pThis->aCts[i].aIfs[j].Led));
7473
7474 uint32_t cbIOBuffer = 0;
7475 rc = pHlp->pfnSSMGetU32(pSSM, &cbIOBuffer);
7476 AssertRCReturn(rc, rc);
7477
7478 if (cbIOBuffer)
7479 {
7480 if (cbIOBuffer <= sizeof(pThis->aCts[i].aIfs[j].abIOBuffer))
7481 {
7482 if (pThis->aCts[i].aIfs[j].cbIOBuffer != cbIOBuffer)
7483 LogRel(("ATA: %u/%u: Restoring cbIOBuffer=%u; constructor set up %u!\n", i, j, cbIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer));
7484 pThis->aCts[i].aIfs[j].cbIOBuffer = cbIOBuffer;
7485 pHlp->pfnSSMGetMem(pSSM, pThis->aCts[i].aIfs[j].abIOBuffer, cbIOBuffer);
7486 }
7487 else
7488 {
7489 LogRel(("ATA: %u/%u: Restoring cbIOBuffer=%u, only prepared %u!\n", i, j, cbIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer));
7490 if (pHlp->pfnSSMHandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
7491 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS,
7492 N_("ATA: %u/%u: Restoring cbIOBuffer=%u, only prepared %u"),
7493 i, j, cbIOBuffer, pThis->aCts[i].aIfs[j].cbIOBuffer);
7494
7495 /* skip the buffer if we're loading for the debugger / animator. */
7496 pHlp->pfnSSMSkip(pSSM, cbIOBuffer);
7497 }
7498 }
7499 else
7500 AssertLogRelMsgStmt(pThis->aCts[i].aIfs[j].cbIOBuffer == 0,
7501 ("ATA: %u/%u: cbIOBuffer=%u restoring zero!\n", i, j, pThis->aCts[i].aIfs[j].cbIOBuffer),
7502 pThis->aCts[i].aIfs[j].cbIOBuffer = 0);
7503 }
7504 }
7505 if (uVersion <= ATA_SAVED_STATE_VERSION_VBOX_30)
7506 PDMDEVHLP_SSM_GET_ENUM8_RET(pHlp, pSSM, pThis->enmChipset, CHIPSET);
7507
7508 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
7509 if (RT_FAILURE(rc))
7510 return rc;
7511 if (u32 != ~0U)
7512 {
7513 AssertMsgFailed(("u32=%#x expected ~0\n", u32));
7514 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
7515 return rc;
7516 }
7517
7518 return VINF_SUCCESS;
7519}
7520
7521
7522/**
7523 * Callback employed by ataSuspend and ataR3PowerOff.
7524 *
7525 * @returns true if we've quiesced, false if we're still working.
7526 * @param pDevIns The device instance.
7527 */
7528static DECLCALLBACK(bool) ataR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)
7529{
7530 return ataR3AllAsyncIOIsIdle(pDevIns);
7531}
7532
7533
7534/**
7535 * Common worker for ataSuspend and ataR3PowerOff.
7536 */
7537static void ataR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
7538{
7539 if (!ataR3AllAsyncIOIsIdle(pDevIns))
7540 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncSuspendOrPowerOffDone);
7541}
7542
7543
7544/**
7545 * Power Off notification.
7546 *
7547 * @returns VBox status code.
7548 * @param pDevIns The device instance data.
7549 */
7550static DECLCALLBACK(void) ataR3PowerOff(PPDMDEVINS pDevIns)
7551{
7552 Log(("%s:\n", __FUNCTION__));
7553 ataR3SuspendOrPowerOff(pDevIns);
7554}
7555
7556
7557/**
7558 * Suspend notification.
7559 *
7560 * @returns VBox status code.
7561 * @param pDevIns The device instance data.
7562 */
7563static DECLCALLBACK(void) ataR3Suspend(PPDMDEVINS pDevIns)
7564{
7565 Log(("%s:\n", __FUNCTION__));
7566 ataR3SuspendOrPowerOff(pDevIns);
7567}
7568
7569
7570/**
7571 * Callback employed by ataR3Reset.
7572 *
7573 * @returns true if we've quiesced, false if we're still working.
7574 * @param pDevIns The device instance.
7575 */
7576static DECLCALLBACK(bool) ataR3IsAsyncResetDone(PPDMDEVINS pDevIns)
7577{
7578 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7579
7580 if (!ataR3AllAsyncIOIsIdle(pDevIns))
7581 return false;
7582
7583 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7584 {
7585 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].lock, VERR_INTERNAL_ERROR);
7586 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].lock, rcLock);
7587
7588 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7589 ataR3ResetDevice(pDevIns, &pThis->aCts[i], &pThis->aCts[i].aIfs[j]);
7590
7591 PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].lock);
7592 }
7593 return true;
7594}
7595
7596
7597/**
7598 * Common reset worker for ataR3Reset and ataR3Construct.
7599 *
7600 * @returns VBox status code.
7601 * @param pDevIns The device instance data.
7602 * @param fConstruct Indicates who is calling.
7603 */
7604static int ataR3ResetCommon(PPDMDEVINS pDevIns, bool fConstruct)
7605{
7606 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7607 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7608
7609 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7610 {
7611 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].lock, VERR_INTERNAL_ERROR);
7612 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].lock, rcLock);
7613
7614 pThis->aCts[i].iSelectedIf = 0;
7615 pThis->aCts[i].iAIOIf = 0;
7616 pThis->aCts[i].BmDma.u8Cmd = 0;
7617 /* Report that both drives present on the bus are in DMA mode. This
7618 * pretends that there is a BIOS that has set it up. Normal reset
7619 * default is 0x00. */
7620 pThis->aCts[i].BmDma.u8Status = (pThisCC->aCts[i].aIfs[0].pDrvBase != NULL ? BM_STATUS_D0DMA : 0)
7621 | (pThisCC->aCts[i].aIfs[1].pDrvBase != NULL ? BM_STATUS_D1DMA : 0);
7622 pThis->aCts[i].BmDma.GCPhysAddr = 0;
7623
7624 pThis->aCts[i].fReset = true;
7625 pThis->aCts[i].fRedo = false;
7626 pThis->aCts[i].fRedoIdle = false;
7627 ataR3AsyncIOClearRequests(pDevIns, &pThis->aCts[i]);
7628 Log2(("%s: Ctl#%d: message to async I/O thread, reset controller\n", __FUNCTION__, i));
7629 ataHCAsyncIOPutRequest(pDevIns, &pThis->aCts[i], &g_ataResetARequest);
7630 ataHCAsyncIOPutRequest(pDevIns, &pThis->aCts[i], &g_ataResetCRequest);
7631
7632 PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].lock);
7633 }
7634
7635 int rcRet = VINF_SUCCESS;
7636 if (!fConstruct)
7637 {
7638 /*
7639 * Setup asynchronous notification completion if the requests haven't
7640 * completed yet.
7641 */
7642 if (!ataR3IsAsyncResetDone(pDevIns))
7643 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncResetDone);
7644 }
7645 else
7646 {
7647 /*
7648 * Wait for the requests for complete.
7649 *
7650 * Would be real nice if we could do it all from EMT(0) and not
7651 * involve the worker threads, then we could dispense with all the
7652 * waiting and semaphore ping-pong here...
7653 */
7654 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7655 {
7656 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7657 {
7658 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->aCts[i].AsyncIORequestLock, VERR_IGNORED);
7659 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->aCts[i].AsyncIORequestLock, rc);
7660
7661 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, true);
7662 rc = RTThreadUserReset(pThisCC->aCts[i].hAsyncIOThread);
7663 AssertRC(rc);
7664
7665 rc = PDMDevHlpCritSectLeave(pDevIns, &pThis->aCts[i].AsyncIORequestLock);
7666 AssertRC(rc);
7667
7668 if (!ataR3AsyncIOIsIdle(pDevIns, &pThis->aCts[i], false /*fStrict*/))
7669 {
7670 rc = RTThreadUserWait(pThisCC->aCts[i].hAsyncIOThread, 30*1000 /*ms*/);
7671 if (RT_FAILURE(rc))
7672 rc = RTThreadUserWait(pThisCC->aCts[i].hAsyncIOThread, 1000 /*ms*/);
7673 if (RT_FAILURE(rc))
7674 {
7675 AssertRC(rc);
7676 rcRet = rc;
7677 }
7678 }
7679 }
7680 ASMAtomicWriteBool(&pThisCC->aCts[i].fSignalIdle, false);
7681 }
7682 if (RT_SUCCESS(rcRet))
7683 {
7684 rcRet = ataR3IsAsyncResetDone(pDevIns) ? VINF_SUCCESS : VERR_INTERNAL_ERROR;
7685 AssertRC(rcRet);
7686 }
7687 }
7688 return rcRet;
7689}
7690
7691/**
7692 * Reset notification.
7693 *
7694 * @param pDevIns The device instance data.
7695 */
7696static DECLCALLBACK(void) ataR3Reset(PPDMDEVINS pDevIns)
7697{
7698 ataR3ResetCommon(pDevIns, false /*fConstruct*/);
7699}
7700
7701/**
7702 * Destroy a driver instance.
7703 *
7704 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
7705 * resources can be freed correctly.
7706 *
7707 * @param pDevIns The device instance data.
7708 */
7709static DECLCALLBACK(int) ataR3Destruct(PPDMDEVINS pDevIns)
7710{
7711 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
7712 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7713 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATECC);
7714 int rc;
7715
7716 Log(("ataR3Destruct\n"));
7717
7718 /*
7719 * Tell the async I/O threads to terminate.
7720 */
7721 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7722 {
7723 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7724 {
7725 ASMAtomicWriteU32(&pThisCC->aCts[i].fShutdown, true);
7726 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aCts[i].hAsyncIOSem);
7727 AssertRC(rc);
7728 rc = RTSemEventSignal(pThisCC->aCts[i].hSuspendIOSem);
7729 AssertRC(rc);
7730 }
7731 }
7732
7733 /*
7734 * Wait for the threads to terminate before destroying their resources.
7735 */
7736 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7737 {
7738 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7739 {
7740 rc = RTThreadWait(pThisCC->aCts[i].hAsyncIOThread, 30000 /* 30 s*/, NULL);
7741 if (RT_SUCCESS(rc))
7742 pThisCC->aCts[i].hAsyncIOThread = NIL_RTTHREAD;
7743 else
7744 LogRel(("PIIX3 ATA Dtor: Ctl#%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x rc=%Rrc\n",
7745 i, pThis->aCts[i].iSelectedIf, pThis->aCts[i].iAIOIf,
7746 pThis->aCts[i].aIfs[0].uATARegCommand, pThis->aCts[i].aIfs[1].uATARegCommand, rc));
7747 }
7748 }
7749
7750 /*
7751 * Free resources.
7752 */
7753 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7754 {
7755 if (PDMDevHlpCritSectIsInitialized(pDevIns, &pThis->aCts[i].AsyncIORequestLock))
7756 PDMDevHlpCritSectDelete(pDevIns, &pThis->aCts[i].AsyncIORequestLock);
7757 if (pThis->aCts[i].hAsyncIOSem != NIL_SUPSEMEVENT)
7758 {
7759 PDMDevHlpSUPSemEventClose(pDevIns, pThis->aCts[i].hAsyncIOSem);
7760 pThis->aCts[i].hAsyncIOSem = NIL_SUPSEMEVENT;
7761 }
7762 if (pThisCC->aCts[i].hSuspendIOSem != NIL_RTSEMEVENT)
7763 {
7764 RTSemEventDestroy(pThisCC->aCts[i].hSuspendIOSem);
7765 pThisCC->aCts[i].hSuspendIOSem = NIL_RTSEMEVENT;
7766 }
7767
7768 /* try one final time */
7769 if (pThisCC->aCts[i].hAsyncIOThread != NIL_RTTHREAD)
7770 {
7771 rc = RTThreadWait(pThisCC->aCts[i].hAsyncIOThread, 1 /*ms*/, NULL);
7772 if (RT_SUCCESS(rc))
7773 {
7774 pThisCC->aCts[i].hAsyncIOThread = NIL_RTTHREAD;
7775 LogRel(("PIIX3 ATA Dtor: Ctl#%u actually completed.\n", i));
7776 }
7777 }
7778
7779 for (uint32_t iIf = 0; iIf < RT_ELEMENTS(pThis->aCts[i].aIfs); iIf++)
7780 {
7781 if (pThisCC->aCts[i].aIfs[iIf].pTrackList)
7782 {
7783 ATAPIPassthroughTrackListDestroy(pThisCC->aCts[i].aIfs[iIf].pTrackList);
7784 pThisCC->aCts[i].aIfs[iIf].pTrackList = NULL;
7785 }
7786 }
7787 }
7788
7789 return VINF_SUCCESS;
7790}
7791
7792/**
7793 * Convert config value to DEVPCBIOSBOOT.
7794 *
7795 * @returns VBox status code.
7796 * @param pDevIns The device instance data.
7797 * @param pCfg Configuration handle.
7798 * @param penmChipset Where to store the chipset type.
7799 */
7800static int ataR3ControllerFromCfg(PPDMDEVINS pDevIns, PCFGMNODE pCfg, CHIPSET *penmChipset)
7801{
7802 char szType[20];
7803
7804 int rc = pDevIns->pHlpR3->pfnCFGMQueryStringDef(pCfg, "Type", &szType[0], sizeof(szType), "PIIX4");
7805 if (RT_FAILURE(rc))
7806 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
7807 N_("Configuration error: Querying \"Type\" as a string failed"));
7808 if (!strcmp(szType, "PIIX3"))
7809 *penmChipset = CHIPSET_PIIX3;
7810 else if (!strcmp(szType, "PIIX4"))
7811 *penmChipset = CHIPSET_PIIX4;
7812 else if (!strcmp(szType, "ICH6"))
7813 *penmChipset = CHIPSET_ICH6;
7814 else
7815 {
7816 PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
7817 N_("Configuration error: The \"Type\" value \"%s\" is unknown"),
7818 szType);
7819 rc = VERR_INTERNAL_ERROR;
7820 }
7821 return rc;
7822}
7823
7824/**
7825 * @interface_method_impl{PDMDEVREG,pfnConstruct}
7826 */
7827static DECLCALLBACK(int) ataR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
7828{
7829 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
7830 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
7831 PATASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PATASTATER3);
7832 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
7833 PPDMIBASE pBase;
7834 int rc;
7835 uint32_t msDelayIRQ;
7836
7837 Assert(iInstance == 0);
7838
7839 /*
7840 * Initialize NIL handle values (for the destructor).
7841 */
7842 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7843 {
7844 pThis->aCts[i].iCtl = i;
7845 pThis->aCts[i].hAsyncIOSem = NIL_SUPSEMEVENT;
7846 pThis->aCts[i].hIoPorts1First = NIL_IOMIOPORTHANDLE;
7847 pThis->aCts[i].hIoPorts1Other = NIL_IOMIOPORTHANDLE;
7848 pThis->aCts[i].hIoPorts2 = NIL_IOMIOPORTHANDLE;
7849 pThis->aCts[i].hIoPortsEmpty1 = NIL_IOMIOPORTHANDLE;
7850 pThis->aCts[i].hIoPortsEmpty2 = NIL_IOMIOPORTHANDLE;
7851
7852 pThisCC->aCts[i].iCtl = i;
7853 pThisCC->aCts[i].hSuspendIOSem = NIL_RTSEMEVENT;
7854 pThisCC->aCts[i].hAsyncIOThread = NIL_RTTHREAD;
7855 }
7856
7857 /*
7858 * Validate and read configuration.
7859 */
7860 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "IRQDelay|Type", "PrimaryMaster|PrimarySlave|SecondaryMaster|SecondarySlave");
7861
7862 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "IRQDelay", &msDelayIRQ, 0);
7863 if (RT_FAILURE(rc))
7864 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 configuration error: failed to read IRQDelay as integer"));
7865 Log(("%s: msDelayIRQ=%d\n", __FUNCTION__, msDelayIRQ));
7866 Assert(msDelayIRQ < 50);
7867
7868 CHIPSET enmChipset = CHIPSET_PIIX3;
7869 rc = ataR3ControllerFromCfg(pDevIns, pCfg, &enmChipset);
7870 if (RT_FAILURE(rc))
7871 return rc;
7872 pThis->enmChipset = enmChipset;
7873
7874 /*
7875 * Initialize data (most of it anyway).
7876 */
7877 /* Status LUN. */
7878 pThisCC->IBase.pfnQueryInterface = ataR3Status_QueryInterface;
7879 pThisCC->ILeds.pfnQueryStatusLed = ataR3Status_QueryStatusLed;
7880
7881 /* PCI configuration space. */
7882 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0];
7883 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev);
7884 PDMPciDevSetVendorId(pPciDev, 0x8086); /* Intel */
7885
7886 /*
7887 * When adding more IDE chipsets, don't forget to update pci_bios_init_device()
7888 * as it explicitly checks for PCI id for IDE controllers.
7889 */
7890 switch (enmChipset)
7891 {
7892 case CHIPSET_ICH6:
7893 PDMPciDevSetDeviceId(pPciDev, 0x269e); /* ICH6 IDE */
7894 /** @todo do we need it? Do we need anything else? */
7895 PDMPciDevSetByte(pPciDev, 0x48, 0x00); /* UDMACTL */
7896 PDMPciDevSetByte(pPciDev, 0x4A, 0x00); /* UDMATIM */
7897 PDMPciDevSetByte(pPciDev, 0x4B, 0x00);
7898 {
7899 /*
7900 * See www.intel.com/Assets/PDF/manual/298600.pdf p. 30
7901 * Report
7902 * WR_Ping-Pong_EN: must be set
7903 * PCR0, PCR1: 80-pin primary cable reporting for both disks
7904 * SCR0, SCR1: 80-pin secondary cable reporting for both disks
7905 */
7906 uint16_t u16Config = (1<<10) | (1<<7) | (1<<6) | (1<<5) | (1<<4);
7907 PDMPciDevSetByte(pPciDev, 0x54, u16Config & 0xff);
7908 PDMPciDevSetByte(pPciDev, 0x55, u16Config >> 8);
7909 }
7910 break;
7911 case CHIPSET_PIIX4:
7912 PDMPciDevSetDeviceId(pPciDev, 0x7111); /* PIIX4 IDE */
7913 PDMPciDevSetRevisionId(pPciDev, 0x01); /* PIIX4E */
7914 PDMPciDevSetByte(pPciDev, 0x48, 0x00); /* UDMACTL */
7915 PDMPciDevSetByte(pPciDev, 0x4A, 0x00); /* UDMATIM */
7916 PDMPciDevSetByte(pPciDev, 0x4B, 0x00);
7917 break;
7918 case CHIPSET_PIIX3:
7919 PDMPciDevSetDeviceId(pPciDev, 0x7010); /* PIIX3 IDE */
7920 break;
7921 default:
7922 AssertMsgFailed(("Unsupported IDE chipset type: %d\n", enmChipset));
7923 }
7924
7925 /** @todo
7926 * This is the job of the BIOS / EFI!
7927 *
7928 * The same is done in DevPCI.cpp / pci_bios_init_device() but there is no
7929 * corresponding function in DevPciIch9.cpp. The EFI has corresponding code
7930 * in OvmfPkg/Library/PlatformBdsLib/BdsPlatform.c: NotifyDev() but this
7931 * function assumes that the IDE controller is located at PCI 00:01.1 which
7932 * is not true if the ICH9 chipset is used.
7933 */
7934 PDMPciDevSetWord(pPciDev, 0x40, 0x8000); /* enable IDE0 */
7935 PDMPciDevSetWord(pPciDev, 0x42, 0x8000); /* enable IDE1 */
7936
7937 PDMPciDevSetCommand( pPciDev, PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS | PCI_COMMAND_BUSMASTER);
7938 PDMPciDevSetClassProg( pPciDev, 0x8a); /* programming interface = PCI_IDE bus-master is supported */
7939 PDMPciDevSetClassSub( pPciDev, 0x01); /* class_sub = PCI_IDE */
7940 PDMPciDevSetClassBase( pPciDev, 0x01); /* class_base = PCI_mass_storage */
7941 PDMPciDevSetHeaderType(pPciDev, 0x00);
7942
7943 pThisCC->pDevIns = pDevIns;
7944 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7945 {
7946 pThisCC->aCts[i].pDevIns = pDevIns;
7947 pThisCC->aCts[i].iCtl = i;
7948 pThis->aCts[i].iCtl = i;
7949 pThis->aCts[i].msDelayIRQ = msDelayIRQ;
7950 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
7951 {
7952 PATADEVSTATE pIf = &pThis->aCts[i].aIfs[j];
7953 PATADEVSTATER3 pIfR3 = &pThisCC->aCts[i].aIfs[j];
7954
7955 pIfR3->iLUN = pIf->iLUN = i * RT_ELEMENTS(pThis->aCts) + j;
7956 pIfR3->iCtl = pIf->iCtl = i;
7957 pIfR3->iDev = pIf->iDev = j;
7958 pIfR3->pDevIns = pDevIns;
7959 pIfR3->IBase.pfnQueryInterface = ataR3QueryInterface;
7960 pIfR3->IMountNotify.pfnMountNotify = ataR3MountNotify;
7961 pIfR3->IMountNotify.pfnUnmountNotify = ataR3UnmountNotify;
7962 pIfR3->IPort.pfnQueryDeviceLocation = ataR3QueryDeviceLocation;
7963 pIf->Led.u32Magic = PDMLED_MAGIC;
7964 }
7965 }
7966
7967 Assert(RT_ELEMENTS(pThis->aCts) == 2);
7968 pThis->aCts[0].irq = 14;
7969 pThis->aCts[0].IOPortBase1 = 0x1f0;
7970 pThis->aCts[0].IOPortBase2 = 0x3f6;
7971 pThis->aCts[1].irq = 15;
7972 pThis->aCts[1].IOPortBase1 = 0x170;
7973 pThis->aCts[1].IOPortBase2 = 0x376;
7974
7975 /*
7976 * Set the default critical section to NOP as we lock on controller level.
7977 */
7978 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
7979 AssertRCReturn(rc, rc);
7980
7981 /*
7982 * Register the PCI device.
7983 */
7984 rc = PDMDevHlpPCIRegisterEx(pDevIns, pPciDev, PDMPCIDEVREG_F_NOT_MANDATORY_NO, 1 /*uPciDevNo*/, 1 /*uPciDevFn*/, "piix3ide");
7985 if (RT_FAILURE(rc))
7986 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register PCI device"));
7987
7988 /* Region #4: I/O ports for the two bus-master DMA controllers. */
7989 rc = PDMDevHlpPCIIORegionCreateIo(pDevIns, 4 /*iPciRegion*/, 0x10 /*cPorts*/,
7990 ataBMDMAIOPortWrite, ataBMDMAIOPortRead, NULL /*pvUser*/, "ATA Bus Master DMA",
7991 NULL /*paExtDescs*/, &pThis->hIoPortsBmDma);
7992 AssertRCReturn(rc, rc);
7993
7994 /*
7995 * Register stats, create critical sections.
7996 */
7997 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
7998 {
7999 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)
8000 {
8001 PATADEVSTATE pIf = &pThis->aCts[i].aIfs[j];
8002 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATADMA, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8003 "Number of ATA DMA transfers.", "/Devices/IDE%d/ATA%d/Unit%d/DMA", iInstance, i, j);
8004 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATAPIO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8005 "Number of ATA PIO transfers.", "/Devices/IDE%d/ATA%d/Unit%d/PIO", iInstance, i, j);
8006 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATAPIDMA, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8007 "Number of ATAPI DMA transfers.", "/Devices/IDE%d/ATA%d/Unit%d/AtapiDMA", iInstance, i, j);
8008 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatATAPIPIO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8009 "Number of ATAPI PIO transfers.", "/Devices/IDE%d/ATA%d/Unit%d/AtapiPIO", iInstance, i, j);
8010#ifdef VBOX_WITH_STATISTICS /** @todo release too. */
8011 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatReads, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8012 "Profiling of the read operations.", "/Devices/IDE%d/ATA%d/Unit%d/Reads", iInstance, i, j);
8013#endif
8014 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
8015 "Amount of data read.", "/Devices/IDE%d/ATA%d/Unit%d/ReadBytes", iInstance, i, j);
8016#ifdef VBOX_INSTRUMENT_DMA_WRITES
8017 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatInstrVDWrites,STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8018 "Profiling of the VD DMA write operations.", "/Devices/IDE%d/ATA%d/Unit%d/InstrVDWrites", iInstance, i, j);
8019#endif
8020#ifdef VBOX_WITH_STATISTICS
8021 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatWrites, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8022 "Profiling of the write operations.", "/Devices/IDE%d/ATA%d/Unit%d/Writes", iInstance, i, j);
8023#endif
8024 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
8025 "Amount of data written.", "/Devices/IDE%d/ATA%d/Unit%d/WrittenBytes", iInstance, i, j);
8026#ifdef VBOX_WITH_STATISTICS
8027 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatFlushes, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8028 "Profiling of the flush operations.", "/Devices/IDE%d/ATA%d/Unit%d/Flushes", iInstance, i, j);
8029#endif
8030 PDMDevHlpSTAMRegisterF(pDevIns, &pIf->StatStatusYields, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8031 "Profiling of status polling yields.", "/Devices/IDE%d/ATA%d/Unit%d/StatusYields", iInstance, i, j);
8032 }
8033#ifdef VBOX_WITH_STATISTICS /** @todo release too. */
8034 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncOps, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
8035 "The number of async operations.", "/Devices/IDE%d/ATA%d/Async/Operations", iInstance, i);
8036 /** @todo STAMUNIT_MICROSECS */
8037 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncMinWait, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
8038 "Minimum wait in microseconds.", "/Devices/IDE%d/ATA%d/Async/MinWait", iInstance, i);
8039 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncMaxWait, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
8040 "Maximum wait in microseconds.", "/Devices/IDE%d/ATA%d/Async/MaxWait", iInstance, i);
8041 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncTimeUS, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
8042 "Total time spent in microseconds.", "/Devices/IDE%d/ATA%d/Async/TotalTimeUS", iInstance, i);
8043 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatAsyncTime, STAMTYPE_PROFILE_ADV, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8044 "Profiling of async operations.", "/Devices/IDE%d/ATA%d/Async/Time", iInstance, i);
8045 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aCts[i].StatLockWait, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
8046 "Profiling of locks.", "/Devices/IDE%d/ATA%d/Async/LockWait", iInstance, i);
8047#endif /* VBOX_WITH_STATISTICS */
8048
8049 /* Initialize per-controller critical section. */
8050 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->aCts[i].lock, RT_SRC_POS, "ATA#%u-Ctl", i);
8051 AssertLogRelRCReturn(rc, rc);
8052
8053 /* Initialize per-controller async I/O request critical section. */
8054 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->aCts[i].AsyncIORequestLock, RT_SRC_POS, "ATA#%u-Req", i);
8055 AssertLogRelRCReturn(rc, rc);
8056 }
8057
8058 /*
8059 * Attach status driver (optional).
8060 */
8061 rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThisCC->IBase, &pBase, "Status Port");
8062 if (RT_SUCCESS(rc))
8063 {
8064 pThisCC->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS);
8065 pThisCC->pMediaNotify = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIANOTIFY);
8066 }
8067 else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
8068 {
8069 AssertMsgFailed(("Failed to attach to status driver. rc=%Rrc\n", rc));
8070 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot attach to status driver"));
8071 }
8072
8073 /*
8074 * Attach the units.
8075 */
8076 uint32_t cbTotalBuffer = 0;
8077 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
8078 {
8079 PATACONTROLLER pCtl = &pThis->aCts[i];
8080 PATACONTROLLERR3 pCtlR3 = &pThisCC->aCts[i];
8081
8082 /*
8083 * Start the worker thread.
8084 */
8085 pCtl->uAsyncIOState = ATA_AIO_NEW;
8086 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pCtl->hAsyncIOSem);
8087 AssertLogRelRCReturn(rc, rc);
8088 rc = RTSemEventCreate(&pCtlR3->hSuspendIOSem);
8089 AssertLogRelRCReturn(rc, rc);
8090
8091 ataR3AsyncIOClearRequests(pDevIns, pCtl);
8092 rc = RTThreadCreateF(&pCtlR3->hAsyncIOThread, ataR3AsyncIOThread, pCtlR3, 0,
8093 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "ATA-%u", i);
8094 AssertLogRelRCReturn(rc, rc);
8095 Assert( pCtlR3->hAsyncIOThread != NIL_RTTHREAD && pCtl->hAsyncIOSem != NIL_SUPSEMEVENT
8096 && pCtlR3->hSuspendIOSem != NIL_RTSEMEVENT && PDMDevHlpCritSectIsInitialized(pDevIns, &pCtl->AsyncIORequestLock));
8097 Log(("%s: controller %d AIO thread id %#x; sem %p susp_sem %p\n", __FUNCTION__, i, pCtlR3->hAsyncIOThread, pCtl->hAsyncIOSem, pCtlR3->hSuspendIOSem));
8098
8099 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
8100 {
8101 static const char *s_apszDescs[RT_ELEMENTS(pThis->aCts)][RT_ELEMENTS(pCtl->aIfs)] =
8102 {
8103 { "Primary Master", "Primary Slave" },
8104 { "Secondary Master", "Secondary Slave" }
8105 };
8106
8107 /*
8108 * Try attach the block device and get the interfaces,
8109 * required as well as optional.
8110 */
8111 PATADEVSTATE pIf = &pCtl->aIfs[j];
8112 PATADEVSTATER3 pIfR3 = &pCtlR3->aIfs[j];
8113
8114 rc = PDMDevHlpDriverAttach(pDevIns, pIf->iLUN, &pIfR3->IBase, &pIfR3->pDrvBase, s_apszDescs[i][j]);
8115 if (RT_SUCCESS(rc))
8116 {
8117 rc = ataR3ConfigLun(pIf, pIfR3);
8118 if (RT_SUCCESS(rc))
8119 {
8120 /*
8121 * Init vendor product data.
8122 */
8123 static const char *s_apszCFGMKeys[RT_ELEMENTS(pThis->aCts)][RT_ELEMENTS(pCtl->aIfs)] =
8124 {
8125 { "PrimaryMaster", "PrimarySlave" },
8126 { "SecondaryMaster", "SecondarySlave" }
8127 };
8128
8129 /* Generate a default serial number. */
8130 char szSerial[ATA_SERIAL_NUMBER_LENGTH+1];
8131 RTUUID Uuid;
8132 if (pIfR3->pDrvMedia)
8133 rc = pIfR3->pDrvMedia->pfnGetUuid(pIfR3->pDrvMedia, &Uuid);
8134 else
8135 RTUuidClear(&Uuid);
8136
8137 if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
8138 {
8139 /* Generate a predictable serial for drives which don't have a UUID. */
8140 RTStrPrintf(szSerial, sizeof(szSerial), "VB%x-%04x%04x",
8141 pIf->iLUN + pDevIns->iInstance * 32,
8142 pThis->aCts[i].IOPortBase1, pThis->aCts[i].IOPortBase2);
8143 }
8144 else
8145 RTStrPrintf(szSerial, sizeof(szSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
8146
8147 /* Get user config if present using defaults otherwise. */
8148 PCFGMNODE pCfgNode = pHlp->pfnCFGMGetChild(pCfg, s_apszCFGMKeys[i][j]);
8149 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "SerialNumber", pIf->szSerialNumber, sizeof(pIf->szSerialNumber),
8150 szSerial);
8151 if (RT_FAILURE(rc))
8152 {
8153 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8154 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8155 N_("PIIX3 configuration error: \"SerialNumber\" is longer than 20 bytes"));
8156 return PDMDEV_SET_ERROR(pDevIns, rc,
8157 N_("PIIX3 configuration error: failed to read \"SerialNumber\" as string"));
8158 }
8159
8160 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "FirmwareRevision", pIf->szFirmwareRevision,
8161 sizeof(pIf->szFirmwareRevision), "1.0");
8162 if (RT_FAILURE(rc))
8163 {
8164 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8165 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8166 N_("PIIX3 configuration error: \"FirmwareRevision\" is longer than 8 bytes"));
8167 return PDMDEV_SET_ERROR(pDevIns, rc,
8168 N_("PIIX3 configuration error: failed to read \"FirmwareRevision\" as string"));
8169 }
8170
8171 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ModelNumber", pIf->szModelNumber, sizeof(pIf->szModelNumber),
8172 pIf->fATAPI ? "VBOX CD-ROM" : "VBOX HARDDISK");
8173 if (RT_FAILURE(rc))
8174 {
8175 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8176 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8177 N_("PIIX3 configuration error: \"ModelNumber\" is longer than 40 bytes"));
8178 return PDMDEV_SET_ERROR(pDevIns, rc,
8179 N_("PIIX3 configuration error: failed to read \"ModelNumber\" as string"));
8180 }
8181
8182 /* There are three other identification strings for CD drives used for INQUIRY */
8183 if (pIf->fATAPI)
8184 {
8185 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ATAPIVendorId", pIf->szInquiryVendorId,
8186 sizeof(pIf->szInquiryVendorId), "VBOX");
8187 if (RT_FAILURE(rc))
8188 {
8189 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8190 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8191 N_("PIIX3 configuration error: \"ATAPIVendorId\" is longer than 16 bytes"));
8192 return PDMDEV_SET_ERROR(pDevIns, rc,
8193 N_("PIIX3 configuration error: failed to read \"ATAPIVendorId\" as string"));
8194 }
8195
8196 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ATAPIProductId", pIf->szInquiryProductId,
8197 sizeof(pIf->szInquiryProductId), "CD-ROM");
8198 if (RT_FAILURE(rc))
8199 {
8200 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8201 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8202 N_("PIIX3 configuration error: \"ATAPIProductId\" is longer than 16 bytes"));
8203 return PDMDEV_SET_ERROR(pDevIns, rc,
8204 N_("PIIX3 configuration error: failed to read \"ATAPIProductId\" as string"));
8205 }
8206
8207 rc = pHlp->pfnCFGMQueryStringDef(pCfgNode, "ATAPIRevision", pIf->szInquiryRevision,
8208 sizeof(pIf->szInquiryRevision), "1.0");
8209 if (RT_FAILURE(rc))
8210 {
8211 if (rc == VERR_CFGM_NOT_ENOUGH_SPACE)
8212 return PDMDEV_SET_ERROR(pDevIns, VERR_INVALID_PARAMETER,
8213 N_("PIIX3 configuration error: \"ATAPIRevision\" is longer than 4 bytes"));
8214 return PDMDEV_SET_ERROR(pDevIns, rc,
8215 N_("PIIX3 configuration error: failed to read \"ATAPIRevision\" as string"));
8216 }
8217
8218 rc = pHlp->pfnCFGMQueryBoolDef(pCfgNode, "OverwriteInquiry", &pIf->fOverwriteInquiry, true);
8219 if (RT_FAILURE(rc))
8220 return PDMDEV_SET_ERROR(pDevIns, rc,
8221 N_("PIIX3 configuration error: failed to read \"OverwriteInquiry\" as boolean"));
8222 }
8223 }
8224 }
8225 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
8226 {
8227 pIfR3->pDrvBase = NULL;
8228 pIfR3->pDrvMedia = NULL;
8229 pIf->cbIOBuffer = 0;
8230 pIf->fPresent = false;
8231 LogRel(("PIIX3 ATA: LUN#%d: no unit\n", pIf->iLUN));
8232 }
8233 else
8234 {
8235 switch (rc)
8236 {
8237 case VERR_ACCESS_DENIED:
8238 /* Error already cached by DrvHostBase */
8239 return rc;
8240 default:
8241 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
8242 N_("PIIX3 cannot attach drive to the %s"),
8243 s_apszDescs[i][j]);
8244 }
8245 }
8246 cbTotalBuffer += pIf->cbIOBuffer;
8247 }
8248 }
8249
8250 /*
8251 * Register the I/O ports.
8252 * The ports are all hardcoded and enforced by the PIIX3 host bridge controller.
8253 */
8254 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
8255 {
8256 Assert(pThis->aCts[i].aIfs[0].fPresent == (pThisCC->aCts[i].aIfs[0].pDrvMedia != NULL));
8257 Assert(pThis->aCts[i].aIfs[1].fPresent == (pThisCC->aCts[i].aIfs[1].pDrvMedia != NULL));
8258
8259 if (!pThisCC->aCts[i].aIfs[0].pDrvMedia && !pThisCC->aCts[i].aIfs[1].pDrvMedia)
8260 {
8261 /* No device present on this ATA bus; requires special handling. */
8262 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase1, 8 /*cPorts*/, IOM_IOPORT_F_ABS,
8263 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8264 "ATA I/O Base 1 - Empty Bus", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPortsEmpty1);
8265 AssertLogRelRCReturn(rc, rc);
8266 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase2, 1 /*cPorts*/, IOM_IOPORT_F_ABS,
8267 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8268 "ATA I/O Base 2 - Empty Bus", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPortsEmpty2);
8269 AssertLogRelRCReturn(rc, rc);
8270 }
8271 else
8272 {
8273 /* At least one device present, register regular handlers. */
8274 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase1, 1 /*cPorts*/, IOM_IOPORT_F_ABS,
8275 ataIOPortWrite1Data, ataIOPortRead1Data,
8276 ataIOPortWriteStr1Data, ataIOPortReadStr1Data, (RTHCPTR)(uintptr_t)i,
8277 "ATA I/O Base 1 - Data", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPorts1First);
8278 AssertLogRelRCReturn(rc, rc);
8279 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7 /*cPorts*/, IOM_IOPORT_F_ABS,
8280 ataIOPortWrite1Other, ataIOPortRead1Other, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8281 "ATA I/O Base 1 - Other", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPorts1Other);
8282 AssertLogRelRCReturn(rc, rc);
8283
8284
8285 rc = PDMDevHlpIoPortCreateExAndMap(pDevIns, pThis->aCts[i].IOPortBase2, 1 /*cPorts*/, IOM_IOPORT_F_ABS,
8286 ataIOPortWrite2, ataIOPortRead2, NULL, NULL, (RTHCPTR)(uintptr_t)i,
8287 "ATA I/O Base 2", NULL /*paExtDescs*/, &pThis->aCts[i].hIoPorts2);
8288 AssertLogRelRCReturn(rc, rc);
8289 }
8290 }
8291
8292 rc = PDMDevHlpSSMRegisterEx(pDevIns, ATA_SAVED_STATE_VERSION, sizeof(*pThis) + cbTotalBuffer, NULL,
8293 NULL, ataR3LiveExec, NULL,
8294 ataR3SaveLoadPrep, ataR3SaveExec, NULL,
8295 ataR3SaveLoadPrep, ataR3LoadExec, NULL);
8296 if (RT_FAILURE(rc))
8297 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register save state handlers"));
8298
8299 /*
8300 * Initialize the device state.
8301 */
8302 return ataR3ResetCommon(pDevIns, true /*fConstruct*/);
8303}
8304
8305#else /* !IN_RING3 */
8306
8307/**
8308 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
8309 */
8310static DECLCALLBACK(int) ataRZConstruct(PPDMDEVINS pDevIns)
8311{
8312 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
8313 PATASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PATASTATE);
8314
8315 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
8316 AssertRCReturn(rc, rc);
8317
8318 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPortsBmDma, ataBMDMAIOPortWrite, ataBMDMAIOPortRead, NULL /*pvUser*/);
8319 AssertRCReturn(rc, rc);
8320
8321 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
8322 {
8323 if (pThis->aCts[i].hIoPorts1First != NIL_IOMIOPORTHANDLE)
8324 {
8325 rc = PDMDevHlpIoPortSetUpContextEx(pDevIns, pThis->aCts[i].hIoPorts1First,
8326 ataIOPortWrite1Data, ataIOPortRead1Data,
8327 ataIOPortWriteStr1Data, ataIOPortReadStr1Data, (RTHCPTR)(uintptr_t)i);
8328 AssertLogRelRCReturn(rc, rc);
8329 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPorts1Other,
8330 ataIOPortWrite1Other, ataIOPortRead1Other, (RTHCPTR)(uintptr_t)i);
8331 AssertLogRelRCReturn(rc, rc);
8332 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPorts2,
8333 ataIOPortWrite2, ataIOPortRead2, (RTHCPTR)(uintptr_t)i);
8334 AssertLogRelRCReturn(rc, rc);
8335 }
8336 else
8337 {
8338 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPortsEmpty1,
8339 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, (void *)(uintptr_t)i /*pvUser*/);
8340 AssertRCReturn(rc, rc);
8341
8342 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->aCts[i].hIoPortsEmpty2,
8343 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, (void *)(uintptr_t)i /*pvUser*/);
8344 AssertRCReturn(rc, rc);
8345 }
8346 }
8347
8348 return VINF_SUCCESS;
8349}
8350
8351
8352#endif /* !IN_RING3 */
8353
8354/**
8355 * The device registration structure.
8356 */
8357const PDMDEVREG g_DevicePIIX3IDE =
8358{
8359 /* .u32Version = */ PDM_DEVREG_VERSION,
8360 /* .uReserved0 = */ 0,
8361 /* .szName = */ "piix3ide",
8362 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE
8363 | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION
8364 | PDM_DEVREG_FLAGS_FIRST_RESET_NOTIFICATION,
8365 /* .fClass = */ PDM_DEVREG_CLASS_STORAGE,
8366 /* .cMaxInstances = */ 1,
8367 /* .uSharedVersion = */ 42,
8368 /* .cbInstanceShared = */ sizeof(ATASTATE),
8369 /* .cbInstanceCC = */ sizeof(ATASTATECC),
8370 /* .cbInstanceRC = */ sizeof(ATASTATERC),
8371 /* .cMaxPciDevices = */ 1,
8372 /* .cMaxMsixVectors = */ 0,
8373 /* .pszDescription = */ "Intel PIIX3 ATA controller.\n"
8374 " LUN #0 is primary master.\n"
8375 " LUN #1 is primary slave.\n"
8376 " LUN #2 is secondary master.\n"
8377 " LUN #3 is secondary slave.\n"
8378 " LUN #999 is the LED/Status connector.",
8379#if defined(IN_RING3)
8380 /* .pszRCMod = */ "VBoxDDRC.rc",
8381 /* .pszR0Mod = */ "VBoxDDR0.r0",
8382 /* .pfnConstruct = */ ataR3Construct,
8383 /* .pfnDestruct = */ ataR3Destruct,
8384 /* .pfnRelocate = */ NULL,
8385 /* .pfnMemSetup = */ NULL,
8386 /* .pfnPowerOn = */ NULL,
8387 /* .pfnReset = */ ataR3Reset,
8388 /* .pfnSuspend = */ ataR3Suspend,
8389 /* .pfnResume = */ ataR3Resume,
8390 /* .pfnAttach = */ ataR3Attach,
8391 /* .pfnDetach = */ ataR3Detach,
8392 /* .pfnQueryInterface = */ NULL,
8393 /* .pfnInitComplete = */ NULL,
8394 /* .pfnPowerOff = */ ataR3PowerOff,
8395 /* .pfnSoftReset = */ NULL,
8396 /* .pfnReserved0 = */ NULL,
8397 /* .pfnReserved1 = */ NULL,
8398 /* .pfnReserved2 = */ NULL,
8399 /* .pfnReserved3 = */ NULL,
8400 /* .pfnReserved4 = */ NULL,
8401 /* .pfnReserved5 = */ NULL,
8402 /* .pfnReserved6 = */ NULL,
8403 /* .pfnReserved7 = */ NULL,
8404#elif defined(IN_RING0)
8405 /* .pfnEarlyConstruct = */ NULL,
8406 /* .pfnConstruct = */ ataRZConstruct,
8407 /* .pfnDestruct = */ NULL,
8408 /* .pfnFinalDestruct = */ NULL,
8409 /* .pfnRequest = */ NULL,
8410 /* .pfnReserved0 = */ NULL,
8411 /* .pfnReserved1 = */ NULL,
8412 /* .pfnReserved2 = */ NULL,
8413 /* .pfnReserved3 = */ NULL,
8414 /* .pfnReserved4 = */ NULL,
8415 /* .pfnReserved5 = */ NULL,
8416 /* .pfnReserved6 = */ NULL,
8417 /* .pfnReserved7 = */ NULL,
8418#elif defined(IN_RC)
8419 /* .pfnConstruct = */ ataRZConstruct,
8420 /* .pfnReserved0 = */ NULL,
8421 /* .pfnReserved1 = */ NULL,
8422 /* .pfnReserved2 = */ NULL,
8423 /* .pfnReserved3 = */ NULL,
8424 /* .pfnReserved4 = */ NULL,
8425 /* .pfnReserved5 = */ NULL,
8426 /* .pfnReserved6 = */ NULL,
8427 /* .pfnReserved7 = */ NULL,
8428#else
8429# error "Not in IN_RING3, IN_RING0 or IN_RC!"
8430#endif
8431 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
8432};
8433#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