VirtualBox

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

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

VMM/PDM: Increased the PDMCRITSECT size by 64 bytes to make space for a self pointer and more statistics. bugref:6695

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