VirtualBox

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

Last change on this file since 98110 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

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