VirtualBox

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

最後變更 在這個檔案從107606是 107487,由 vboxsync 提交於 2 月 前

Devices/Storage/DevATA.cpp: Enclose logging only code with LOG_ENABLED, bugref:3409

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

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