VirtualBox

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

Last change on this file was 107878, checked in by vboxsync, 4 months ago

DevATA: iCurLBA must be 64-bit; matching saved state adjustment (see bugref:5869).

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

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