VirtualBox

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

Last change on this file since 81888 was 81870, checked in by vboxsync, 5 years ago

DevATA: Use RT_SAFE_SUBSCRIPT. bugref:9218

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