VirtualBox

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

Last change on this file since 86679 was 86481, checked in by vboxsync, 4 years ago

AMD IOMMU: bugref:9654 ATA: Use PCI interfaces while reading/writing guest physical memory.

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

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