VirtualBox

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

Last change on this file since 87093 was 87048, checked in by vboxsync, 4 years ago

CUE, DevATA: Added support for MODE2/2352 tracks in CUE sheets and IDE/ATAPI emulation (see bugref:6975).

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