VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/ATAController.cpp@ 35560

Last change on this file since 35560 was 35560, checked in by vboxsync, 14 years ago

PDM: introduced fEject parameter to PDMIMOUNT::pfnUnmount which is false if we don't need to eject the medium during unmount

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 201.8 KB
Line 
1/* $Id: ATAController.cpp 35560 2011-01-14 13:37:32Z vboxsync $ */
2/** @file
3 * DevATA, DevAHCI - Shared ATA/ATAPI controller code (disk and cdrom).
4 *
5 * @todo Actually share this code?
6 */
7
8/*
9 * Copyright (C) 2006-2010 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#define LOG_GROUP LOG_GROUP_DEV_IDE
24#include <VBox/vmm/pdmdev.h>
25#include <iprt/assert.h>
26#include <iprt/string.h>
27#ifdef IN_RING3
28# include <iprt/uuid.h>
29# include <iprt/semaphore.h>
30# include <iprt/thread.h>
31# include <iprt/time.h>
32# include <iprt/alloc.h>
33#endif /* IN_RING3 */
34#include <iprt/critsect.h>
35#include <iprt/asm.h>
36#include <VBox/vmm/stam.h>
37#include <VBox/vmm/mm.h>
38#include <VBox/vmm/pgm.h>
39
40#include <VBox/scsi.h>
41
42#include "ATAController.h"
43#include "PIIX3ATABmDma.h"
44#include "ide.h"
45
46/**
47 * The SSM saved state version.
48 */
49#define ATA_CTL_SAVED_STATE_VERSION 3
50#define ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE 1
51#define ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS 2
52
53#ifndef VBOX_DEVICE_STRUCT_TESTCASE
54
55DECLINLINE(void) ataSetStatusValue(AHCIATADevState *s, uint8_t stat)
56{
57 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
58
59 /* Freeze status register contents while processing RESET. */
60 if (!pCtl->fReset)
61 {
62 s->uATARegStatus = stat;
63 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, s->iLUN, s->uATARegStatus));
64 }
65}
66
67
68DECLINLINE(void) ataSetStatus(AHCIATADevState *s, uint8_t stat)
69{
70 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
71
72 /* Freeze status register contents while processing RESET. */
73 if (!pCtl->fReset)
74 {
75 s->uATARegStatus |= stat;
76 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, s->iLUN, s->uATARegStatus));
77 }
78}
79
80
81DECLINLINE(void) ataUnsetStatus(AHCIATADevState *s, uint8_t stat)
82{
83 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
84
85 /* Freeze status register contents while processing RESET. */
86 if (!pCtl->fReset)
87 {
88 s->uATARegStatus &= ~stat;
89 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, s->iLUN, s->uATARegStatus));
90 }
91}
92
93#ifdef IN_RING3
94
95typedef void (*PBeginTransferFunc)(AHCIATADevState *);
96typedef bool (*PSourceSinkFunc)(AHCIATADevState *);
97
98static void ataReadWriteSectorsBT(AHCIATADevState *);
99static void ataPacketBT(AHCIATADevState *);
100static void atapiCmdBT(AHCIATADevState *);
101static void atapiPassthroughCmdBT(AHCIATADevState *);
102
103static bool ataIdentifySS(AHCIATADevState *);
104static bool ataFlushSS(AHCIATADevState *);
105static bool ataReadSectorsSS(AHCIATADevState *);
106static bool ataWriteSectorsSS(AHCIATADevState *);
107static bool ataExecuteDeviceDiagnosticSS(AHCIATADevState *);
108static bool ataPacketSS(AHCIATADevState *);
109static bool atapiGetConfigurationSS(AHCIATADevState *);
110static bool atapiGetEventStatusNotificationSS(AHCIATADevState *);
111static bool atapiIdentifySS(AHCIATADevState *);
112static bool atapiInquirySS(AHCIATADevState *);
113static bool atapiMechanismStatusSS(AHCIATADevState *);
114static bool atapiModeSenseErrorRecoverySS(AHCIATADevState *);
115static bool atapiModeSenseCDStatusSS(AHCIATADevState *);
116static bool atapiReadSS(AHCIATADevState *);
117static bool atapiReadCapacitySS(AHCIATADevState *);
118static bool atapiReadDiscInformationSS(AHCIATADevState *);
119static bool atapiReadTOCNormalSS(AHCIATADevState *);
120static bool atapiReadTOCMultiSS(AHCIATADevState *);
121static bool atapiReadTOCRawSS(AHCIATADevState *);
122static bool atapiReadTrackInformationSS(AHCIATADevState *);
123static bool atapiRequestSenseSS(AHCIATADevState *);
124static bool atapiPassthroughSS(AHCIATADevState *);
125
126/**
127 * Begin of transfer function indexes for g_apfnBeginTransFuncs.
128 */
129typedef enum ATAFNBT
130{
131 ATAFN_BT_NULL = 0,
132 ATAFN_BT_READ_WRITE_SECTORS,
133 ATAFN_BT_PACKET,
134 ATAFN_BT_ATAPI_CMD,
135 ATAFN_BT_ATAPI_PASSTHROUGH_CMD,
136 ATAFN_BT_MAX
137} ATAFNBT;
138
139/**
140 * Array of end transfer functions, the index is ATAFNET.
141 * Make sure ATAFNET and this array match!
142 */
143static const PBeginTransferFunc g_apfnBeginTransFuncs[ATAFN_BT_MAX] =
144{
145 NULL,
146 ataReadWriteSectorsBT,
147 ataPacketBT,
148 atapiCmdBT,
149 atapiPassthroughCmdBT,
150};
151
152/**
153 * Source/sink function indexes for g_apfnSourceSinkFuncs.
154 */
155typedef enum ATAFNSS
156{
157 ATAFN_SS_NULL = 0,
158 ATAFN_SS_IDENTIFY,
159 ATAFN_SS_FLUSH,
160 ATAFN_SS_READ_SECTORS,
161 ATAFN_SS_WRITE_SECTORS,
162 ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC,
163 ATAFN_SS_PACKET,
164 ATAFN_SS_ATAPI_GET_CONFIGURATION,
165 ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION,
166 ATAFN_SS_ATAPI_IDENTIFY,
167 ATAFN_SS_ATAPI_INQUIRY,
168 ATAFN_SS_ATAPI_MECHANISM_STATUS,
169 ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY,
170 ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS,
171 ATAFN_SS_ATAPI_READ,
172 ATAFN_SS_ATAPI_READ_CAPACITY,
173 ATAFN_SS_ATAPI_READ_DISC_INFORMATION,
174 ATAFN_SS_ATAPI_READ_TOC_NORMAL,
175 ATAFN_SS_ATAPI_READ_TOC_MULTI,
176 ATAFN_SS_ATAPI_READ_TOC_RAW,
177 ATAFN_SS_ATAPI_READ_TRACK_INFORMATION,
178 ATAFN_SS_ATAPI_REQUEST_SENSE,
179 ATAFN_SS_ATAPI_PASSTHROUGH,
180 ATAFN_SS_MAX
181} ATAFNSS;
182
183/**
184 * Array of source/sink functions, the index is ATAFNSS.
185 * Make sure ATAFNSS and this array match!
186 */
187static const PSourceSinkFunc g_apfnSourceSinkFuncs[ATAFN_SS_MAX] =
188{
189 NULL,
190 ataIdentifySS,
191 ataFlushSS,
192 ataReadSectorsSS,
193 ataWriteSectorsSS,
194 ataExecuteDeviceDiagnosticSS,
195 ataPacketSS,
196 atapiGetConfigurationSS,
197 atapiGetEventStatusNotificationSS,
198 atapiIdentifySS,
199 atapiInquirySS,
200 atapiMechanismStatusSS,
201 atapiModeSenseErrorRecoverySS,
202 atapiModeSenseCDStatusSS,
203 atapiReadSS,
204 atapiReadCapacitySS,
205 atapiReadDiscInformationSS,
206 atapiReadTOCNormalSS,
207 atapiReadTOCMultiSS,
208 atapiReadTOCRawSS,
209 atapiReadTrackInformationSS,
210 atapiRequestSenseSS,
211 atapiPassthroughSS
212};
213
214
215static const AHCIATARequest ataDMARequest = { AHCIATA_AIO_DMA, };
216static const AHCIATARequest ataPIORequest = { AHCIATA_AIO_PIO, };
217static const AHCIATARequest ataResetARequest = { AHCIATA_AIO_RESET_ASSERTED, };
218static const AHCIATARequest ataResetCRequest = { AHCIATA_AIO_RESET_CLEARED, };
219
220
221static void ataAsyncIOClearRequests(PAHCIATACONTROLLER pCtl)
222{
223 int rc;
224
225 rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
226 AssertRC(rc);
227 pCtl->AsyncIOReqHead = 0;
228 pCtl->AsyncIOReqTail = 0;
229 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex);
230 AssertRC(rc);
231}
232
233
234static void ataAsyncIOPutRequest(PAHCIATACONTROLLER pCtl, const AHCIATARequest *pReq)
235{
236 int rc;
237
238 rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
239 AssertRC(rc);
240 Assert((pCtl->AsyncIOReqHead + 1) % RT_ELEMENTS(pCtl->aAsyncIORequests) != pCtl->AsyncIOReqTail);
241 memcpy(&pCtl->aAsyncIORequests[pCtl->AsyncIOReqHead], pReq, sizeof(*pReq));
242 pCtl->AsyncIOReqHead++;
243 pCtl->AsyncIOReqHead %= RT_ELEMENTS(pCtl->aAsyncIORequests);
244 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex);
245 AssertRC(rc);
246 rc = PDMR3CritSectScheduleExitEvent(&pCtl->lock, pCtl->AsyncIOSem);
247 if (RT_FAILURE(rc))
248 {
249 rc = RTSemEventSignal(pCtl->AsyncIOSem);
250 AssertRC(rc);
251 }
252}
253
254
255static const AHCIATARequest *ataAsyncIOGetCurrentRequest(PAHCIATACONTROLLER pCtl)
256{
257 int rc;
258 const AHCIATARequest *pReq;
259
260 rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
261 AssertRC(rc);
262 if (pCtl->AsyncIOReqHead != pCtl->AsyncIOReqTail)
263 pReq = &pCtl->aAsyncIORequests[pCtl->AsyncIOReqTail];
264 else
265 pReq = NULL;
266 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex);
267 AssertRC(rc);
268 return pReq;
269}
270
271
272/**
273 * Remove the request with the given type, as it's finished. The request
274 * is not removed blindly, as this could mean a RESET request that is not
275 * yet processed (but has cleared the request queue) is lost.
276 *
277 * @param pCtl Controller for which to remove the request.
278 * @param ReqType Type of the request to remove.
279 */
280static void ataAsyncIORemoveCurrentRequest(PAHCIATACONTROLLER pCtl, AHCIATAAIO ReqType)
281{
282 int rc;
283
284 rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
285 AssertRC(rc);
286 if (pCtl->AsyncIOReqHead != pCtl->AsyncIOReqTail && pCtl->aAsyncIORequests[pCtl->AsyncIOReqTail].ReqType == ReqType)
287 {
288 pCtl->AsyncIOReqTail++;
289 pCtl->AsyncIOReqTail %= RT_ELEMENTS(pCtl->aAsyncIORequests);
290 }
291 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex);
292 AssertRC(rc);
293}
294
295
296/**
297 * Dump the request queue for a particular controller. First dump the queue
298 * contents, then the already processed entries, as long as they haven't been
299 * overwritten.
300 *
301 * @param pCtl Controller for which to dump the queue.
302 */
303static void ataAsyncIODumpRequests(PAHCIATACONTROLLER pCtl)
304{
305 int rc;
306 uint8_t curr;
307
308 rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
309 AssertRC(rc);
310 LogRel(("AHCI ATA: Ctl: request queue dump (topmost is current):\n"));
311 curr = pCtl->AsyncIOReqTail;
312 do
313 {
314 if (curr == pCtl->AsyncIOReqHead)
315 LogRel(("AHCI ATA: Ctl: processed requests (topmost is oldest):\n"));
316 switch (pCtl->aAsyncIORequests[curr].ReqType)
317 {
318 case AHCIATA_AIO_NEW:
319 LogRel(("new transfer request, iIf=%d iBeginTransfer=%d iSourceSink=%d cbTotalTransfer=%d uTxDir=%d\n", pCtl->aAsyncIORequests[curr].u.t.iIf, pCtl->aAsyncIORequests[curr].u.t.iBeginTransfer, pCtl->aAsyncIORequests[curr].u.t.iSourceSink, pCtl->aAsyncIORequests[curr].u.t.cbTotalTransfer, pCtl->aAsyncIORequests[curr].u.t.uTxDir));
320 break;
321 case AHCIATA_AIO_DMA:
322 LogRel(("dma transfer finished\n"));
323 break;
324 case AHCIATA_AIO_PIO:
325 LogRel(("pio transfer finished\n"));
326 break;
327 case AHCIATA_AIO_RESET_ASSERTED:
328 LogRel(("reset asserted request\n"));
329 break;
330 case AHCIATA_AIO_RESET_CLEARED:
331 LogRel(("reset cleared request\n"));
332 break;
333 case AHCIATA_AIO_ABORT:
334 LogRel(("abort request, iIf=%d fResetDrive=%d\n", pCtl->aAsyncIORequests[curr].u.a.iIf, pCtl->aAsyncIORequests[curr].u.a.fResetDrive));
335 break;
336 default:
337 LogRel(("unknown request %d\n", pCtl->aAsyncIORequests[curr].ReqType));
338 }
339 curr = (curr + 1) % RT_ELEMENTS(pCtl->aAsyncIORequests);
340 } while (curr != pCtl->AsyncIOReqTail);
341 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex);
342 AssertRC(rc);
343}
344
345
346/**
347 * Checks whether the request queue for a particular controller is empty
348 * or whether a particular controller is idle.
349 *
350 * @param pCtl Controller for which to check the queue.
351 * @param fStrict If set then the controller is checked to be idle.
352 */
353static bool ataAsyncIOIsIdle(PAHCIATACONTROLLER pCtl, bool fStrict)
354{
355 int rc;
356 bool fIdle;
357
358 if (pCtl->AsyncIORequestMutex == NIL_RTSEMMUTEX)
359 return true;
360
361 rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
362 AssertRC(rc);
363 fIdle = pCtl->fRedoIdle;
364 if (!fIdle)
365 fIdle = (pCtl->AsyncIOReqHead == pCtl->AsyncIOReqTail);
366 if (fStrict)
367 fIdle &= (pCtl->uAsyncIOState == AHCIATA_AIO_NEW);
368 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex);
369 AssertRC(rc);
370 return fIdle;
371}
372
373
374/**
375 * Send a transfer request to the async I/O thread.
376 *
377 * @param s Pointer to the ATA device state data.
378 * @param cbTotalTransfer Data transfer size.
379 * @param uTxDir Data transfer direction.
380 * @param iBeginTransfer Index of BeginTransfer callback.
381 * @param iSourceSink Index of SourceSink callback.
382 * @param fChainedTransfer Whether this is a transfer that is part of the previous command/transfer.
383 */
384static void ataStartTransfer(AHCIATADevState *s, uint32_t cbTotalTransfer, uint8_t uTxDir, ATAFNBT iBeginTransfer, ATAFNSS iSourceSink, bool fChainedTransfer)
385{
386 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
387 AHCIATARequest Req;
388
389 Assert(PDMCritSectIsOwner(&pCtl->lock));
390
391 /* Do not issue new requests while the RESET line is asserted. */
392 if (pCtl->fReset)
393 {
394 Log2(("%s: Ctl: suppressed new request as RESET is active\n", __FUNCTION__));
395 return;
396 }
397
398 /* If the controller is already doing something else right now, ignore
399 * the command that is being submitted. Some broken guests issue commands
400 * twice (e.g. the Linux kernel that comes with Acronis True Image 8). */
401 if (!fChainedTransfer && !ataAsyncIOIsIdle(pCtl, true))
402 {
403 Log(("%s: Ctl: ignored command %#04x, controller state %d\n", __FUNCTION__, s->uATARegCommand, pCtl->uAsyncIOState));
404 LogRel(("IDE: guest issued command %#04x while controller busy\n", s->uATARegCommand));
405 return;
406 }
407
408 Req.ReqType = AHCIATA_AIO_NEW;
409 if (fChainedTransfer)
410 Req.u.t.iIf = pCtl->iAIOIf;
411 else
412 Req.u.t.iIf = pCtl->iSelectedIf;
413 Req.u.t.cbTotalTransfer = cbTotalTransfer;
414 Req.u.t.uTxDir = uTxDir;
415 Req.u.t.iBeginTransfer = iBeginTransfer;
416 Req.u.t.iSourceSink = iSourceSink;
417 ataSetStatusValue(s, ATA_STAT_BUSY);
418 pCtl->fChainedTransfer = fChainedTransfer;
419
420 /*
421 * Kick the worker thread into action.
422 */
423 Log2(("%s: Ctl: message to async I/O thread, new request\n", __FUNCTION__));
424 ataAsyncIOPutRequest(pCtl, &Req);
425}
426
427
428/**
429 * Send an abort command request to the async I/O thread.
430 *
431 * @param s Pointer to the ATA device state data.
432 * @param fResetDrive Whether to reset the drive or just abort a command.
433 */
434static void ataAbortCurrentCommand(AHCIATADevState *s, bool fResetDrive)
435{
436 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
437 AHCIATARequest Req;
438
439 Assert(PDMCritSectIsOwner(&pCtl->lock));
440
441 /* Do not issue new requests while the RESET line is asserted. */
442 if (pCtl->fReset)
443 {
444 Log2(("%s: Ctl: suppressed aborting command as RESET is active\n", __FUNCTION__));
445 return;
446 }
447
448 Req.ReqType = AHCIATA_AIO_ABORT;
449 Req.u.a.iIf = pCtl->iSelectedIf;
450 Req.u.a.fResetDrive = fResetDrive;
451 ataSetStatus(s, ATA_STAT_BUSY);
452 Log2(("%s: Ctl: message to async I/O thread, abort command on LUN#%d\n", __FUNCTION__, s->iLUN));
453 ataAsyncIOPutRequest(pCtl, &Req);
454}
455
456
457static void ataSetIRQ(AHCIATADevState *s)
458{
459 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
460 PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
461
462 if (!(s->uATARegDevCtl & ATA_DEVCTL_DISABLE_IRQ))
463 {
464 Log2(("%s: LUN#%d asserting IRQ\n", __FUNCTION__, s->iLUN));
465 /* The BMDMA unit unconditionally sets BM_STATUS_INT if the interrupt
466 * line is asserted. It monitors the line for a rising edge. */
467 if (!s->fIrqPending)
468 pCtl->BmDma.u8Status |= BM_STATUS_INT;
469 /* Only actually set the IRQ line if updating the currently selected drive. */
470 if (s == &pCtl->aIfs[pCtl->iSelectedIf])
471 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 1);
472 }
473 s->fIrqPending = true;
474}
475
476#endif /* IN_RING3 */
477
478static void ataUnsetIRQ(AHCIATADevState *s)
479{
480 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
481 PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
482
483 if (!(s->uATARegDevCtl & ATA_DEVCTL_DISABLE_IRQ))
484 {
485 Log2(("%s: LUN#%d deasserting IRQ\n", __FUNCTION__, s->iLUN));
486 /* Only actually unset the IRQ line if updating the currently selected drive. */
487 if (s == &pCtl->aIfs[pCtl->iSelectedIf])
488 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 0);
489 }
490 s->fIrqPending = false;
491}
492
493#ifdef IN_RING3
494
495static void ataPIOTransferStart(AHCIATADevState *s, uint32_t start, uint32_t size)
496{
497 Log2(("%s: LUN#%d start %d size %d\n", __FUNCTION__, s->iLUN, start, size));
498 s->iIOBufferPIODataStart = start;
499 s->iIOBufferPIODataEnd = start + size;
500 ataSetStatus(s, ATA_STAT_DRQ);
501}
502
503
504static void ataPIOTransferStop(AHCIATADevState *s)
505{
506 Log2(("%s: LUN#%d\n", __FUNCTION__, s->iLUN));
507 if (s->fATAPITransfer)
508 {
509 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
510 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
511 ataSetIRQ(s);
512 s->fATAPITransfer = false;
513 }
514 s->cbTotalTransfer = 0;
515 s->cbElementaryTransfer = 0;
516 s->iIOBufferPIODataStart = 0;
517 s->iIOBufferPIODataEnd = 0;
518 s->iBeginTransfer = ATAFN_BT_NULL;
519 s->iSourceSink = ATAFN_SS_NULL;
520}
521
522
523static void ataPIOTransferLimitATAPI(AHCIATADevState *s)
524{
525 uint32_t cbLimit, cbTransfer;
526
527 cbLimit = s->uATARegLCyl | (s->uATARegHCyl << 8);
528 /* Use maximum transfer size if the guest requested 0. Avoids a hang. */
529 if (cbLimit == 0)
530 cbLimit = 0xfffe;
531 Log2(("%s: byte count limit=%d\n", __FUNCTION__, cbLimit));
532 if (cbLimit == 0xffff)
533 cbLimit--;
534 cbTransfer = RT_MIN(s->cbTotalTransfer, s->iIOBufferEnd - s->iIOBufferCur);
535 if (cbTransfer > cbLimit)
536 {
537 /* Byte count limit for clipping must be even in this case */
538 if (cbLimit & 1)
539 cbLimit--;
540 cbTransfer = cbLimit;
541 }
542 s->uATARegLCyl = cbTransfer;
543 s->uATARegHCyl = cbTransfer >> 8;
544 s->cbElementaryTransfer = cbTransfer;
545}
546
547
548static uint32_t ataGetNSectors(AHCIATADevState *s)
549{
550 /* 0 means either 256 (LBA28) or 65536 (LBA48) sectors. */
551 if (s->fLBA48)
552 {
553 if (!s->uATARegNSector && !s->uATARegNSectorHOB)
554 return 65536;
555 else
556 return s->uATARegNSectorHOB << 8 | s->uATARegNSector;
557 }
558 else
559 {
560 if (!s->uATARegNSector)
561 return 256;
562 else
563 return s->uATARegNSector;
564 }
565}
566
567
568static void ataPadString(uint8_t *pbDst, const char *pbSrc, uint32_t cbSize)
569{
570 for (uint32_t i = 0; i < cbSize; i++)
571 {
572 if (*pbSrc)
573 pbDst[i ^ 1] = *pbSrc++;
574 else
575 pbDst[i ^ 1] = ' ';
576 }
577}
578
579
580static void ataSCSIPadStr(uint8_t *pbDst, const char *pbSrc, uint32_t cbSize)
581{
582 for (uint32_t i = 0; i < cbSize; i++)
583 {
584 if (*pbSrc)
585 pbDst[i] = *pbSrc++;
586 else
587 pbDst[i] = ' ';
588 }
589}
590
591
592DECLINLINE(void) ataH2BE_U16(uint8_t *pbBuf, uint16_t val)
593{
594 pbBuf[0] = val >> 8;
595 pbBuf[1] = val;
596}
597
598
599DECLINLINE(void) ataH2BE_U24(uint8_t *pbBuf, uint32_t val)
600{
601 pbBuf[0] = val >> 16;
602 pbBuf[1] = val >> 8;
603 pbBuf[2] = val;
604}
605
606
607DECLINLINE(void) ataH2BE_U32(uint8_t *pbBuf, uint32_t val)
608{
609 pbBuf[0] = val >> 24;
610 pbBuf[1] = val >> 16;
611 pbBuf[2] = val >> 8;
612 pbBuf[3] = val;
613}
614
615
616DECLINLINE(uint16_t) ataBE2H_U16(const uint8_t *pbBuf)
617{
618 return (pbBuf[0] << 8) | pbBuf[1];
619}
620
621
622DECLINLINE(uint32_t) ataBE2H_U24(const uint8_t *pbBuf)
623{
624 return (pbBuf[0] << 16) | (pbBuf[1] << 8) | pbBuf[2];
625}
626
627
628DECLINLINE(uint32_t) ataBE2H_U32(const uint8_t *pbBuf)
629{
630 return (pbBuf[0] << 24) | (pbBuf[1] << 16) | (pbBuf[2] << 8) | pbBuf[3];
631}
632
633
634DECLINLINE(void) ataLBA2MSF(uint8_t *pbBuf, uint32_t iATAPILBA)
635{
636 iATAPILBA += 150;
637 pbBuf[0] = (iATAPILBA / 75) / 60;
638 pbBuf[1] = (iATAPILBA / 75) % 60;
639 pbBuf[2] = iATAPILBA % 75;
640}
641
642
643DECLINLINE(uint32_t) ataMSF2LBA(const uint8_t *pbBuf)
644{
645 return (pbBuf[0] * 60 + pbBuf[1]) * 75 + pbBuf[2];
646}
647
648static uint32_t ataChecksum(void *ptr, size_t count)
649{
650 uint8_t u8Sum = 0xa5;
651 uint8_t *p = (uint8_t*)ptr;
652 size_t i;
653
654 for (i = 0; i < count; i++)
655 {
656 u8Sum += *p++;
657 }
658
659 return (uint8_t)-(int32_t)u8Sum;
660}
661
662static void ataCmdOK(AHCIATADevState *s, uint8_t status)
663{
664 s->uATARegError = 0; /* Not needed by ATA spec, but cannot hurt. */
665 ataSetStatusValue(s, ATA_STAT_READY | status);
666}
667
668
669static void ataCmdError(AHCIATADevState *s, uint8_t uErrorCode)
670{
671 Log(("%s: code=%#x\n", __FUNCTION__, uErrorCode));
672 s->uATARegError = uErrorCode;
673 ataSetStatusValue(s, ATA_STAT_READY | ATA_STAT_ERR);
674 s->cbTotalTransfer = 0;
675 s->cbElementaryTransfer = 0;
676 s->iIOBufferCur = 0;
677 s->iIOBufferEnd = 0;
678 s->uTxDir = PDMBLOCKTXDIR_NONE;
679 s->iBeginTransfer = ATAFN_BT_NULL;
680 s->iSourceSink = ATAFN_SS_NULL;
681}
682
683
684static bool ataIdentifySS(AHCIATADevState *s)
685{
686 uint16_t *p;
687 char aSerial[20];
688 int rc;
689 RTUUID Uuid;
690
691 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
692 Assert(s->cbElementaryTransfer == 512);
693 rc = s->pDrvBlock ? s->pDrvBlock->pfnGetUuid(s->pDrvBlock, &Uuid) : RTUuidClear(&Uuid);
694 if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
695 {
696 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
697 /* Generate a predictable serial for drives which don't have a UUID. */
698 RTStrPrintf(aSerial, sizeof(aSerial), "VB%x-%04x%04x",
699 s->iLUN + ATADEVSTATE_2_DEVINS(s)->iInstance * 32,
700 pCtl->IOPortBase1, pCtl->IOPortBase2);
701 }
702 else
703 RTStrPrintf(aSerial, sizeof(aSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
704
705 p = (uint16_t *)s->CTXALLSUFF(pbIOBuffer);
706 memset(p, 0, 512);
707 p[0] = RT_H2LE_U16(0x0040);
708 p[1] = RT_H2LE_U16(RT_MIN(s->PCHSGeometry.cCylinders, 16383));
709 p[3] = RT_H2LE_U16(s->PCHSGeometry.cHeads);
710 /* Block size; obsolete, but required for the BIOS. */
711 p[5] = RT_H2LE_U16(512);
712 p[6] = RT_H2LE_U16(s->PCHSGeometry.cSectors);
713 ataPadString((uint8_t *)(p + 10), aSerial, 20); /* serial number */
714 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
715 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
716 p[22] = RT_H2LE_U16(0); /* ECC bytes per sector */
717 ataPadString((uint8_t *)(p + 23), "1.0", 8); /* firmware version */
718 ataPadString((uint8_t *)(p + 27), "VBOX HARDDISK", 40); /* model */
719#if ATA_MAX_MULT_SECTORS > 1
720 p[47] = RT_H2LE_U16(0x8000 | ATA_MAX_MULT_SECTORS);
721#endif
722 p[48] = RT_H2LE_U16(1); /* dword I/O, used by the BIOS */
723 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
724 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
725 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
726 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
727 p[53] = RT_H2LE_U16(1 | 1 << 1 | 1 << 2); /* words 54-58,64-70,88 valid */
728 p[54] = RT_H2LE_U16(RT_MIN(s->PCHSGeometry.cCylinders, 16383));
729 p[55] = RT_H2LE_U16(s->PCHSGeometry.cHeads);
730 p[56] = RT_H2LE_U16(s->PCHSGeometry.cSectors);
731 p[57] = RT_H2LE_U16( RT_MIN(s->PCHSGeometry.cCylinders, 16383)
732 * s->PCHSGeometry.cHeads
733 * s->PCHSGeometry.cSectors);
734 p[58] = RT_H2LE_U16( RT_MIN(s->PCHSGeometry.cCylinders, 16383)
735 * s->PCHSGeometry.cHeads
736 * s->PCHSGeometry.cSectors >> 16);
737 if (s->cMultSectors)
738 p[59] = RT_H2LE_U16(0x100 | s->cMultSectors);
739 if (s->cTotalSectors <= (1 << 28) - 1)
740 {
741 p[60] = RT_H2LE_U16(s->cTotalSectors);
742 p[61] = RT_H2LE_U16(s->cTotalSectors >> 16);
743 }
744 else
745 {
746 /* Report maximum number of sectors possible with LBA28 */
747 p[60] = RT_H2LE_U16(((1 << 28) - 1) & 0xffff);
748 p[61] = RT_H2LE_U16(((1 << 28) - 1) >> 16);
749 }
750 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, s->uATATransferMode)); /* MDMA modes supported / mode enabled */
751 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
752 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
753 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
754 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
755 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
756 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
757 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
758 p[82] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* supports power management, write cache and look-ahead */
759 if (s->cTotalSectors <= (1 << 28) - 1)
760 p[83] = RT_H2LE_U16(1 << 14 | 1 << 12); /* supports FLUSH CACHE */
761 else
762 p[83] = RT_H2LE_U16(1 << 14 | 1 << 10 | 1 << 12 | 1 << 13); /* supports LBA48, FLUSH CACHE and FLUSH CACHE EXT */
763 p[84] = RT_H2LE_U16(1 << 14);
764 p[85] = RT_H2LE_U16(1 << 3 | 1 << 5 | 1 << 6); /* enabled power management, write cache and look-ahead */
765 if (s->cTotalSectors <= (1 << 28) - 1)
766 p[86] = RT_H2LE_U16(1 << 12); /* enabled FLUSH CACHE */
767 else
768 p[86] = RT_H2LE_U16(1 << 10 | 1 << 12 | 1 << 13); /* enabled LBA48, FLUSH CACHE and FLUSH CACHE EXT */
769 p[87] = RT_H2LE_U16(1 << 14);
770 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, s->uATATransferMode)); /* UDMA modes supported / mode enabled */
771 p[93] = RT_H2LE_U16((1 | 1 << 1) << ((s->iLUN & 1) == 0 ? 0 : 8) | 1 << 13 | 1 << 14);
772 if (s->cTotalSectors > (1 << 28) - 1)
773 {
774 p[100] = RT_H2LE_U16(s->cTotalSectors);
775 p[101] = RT_H2LE_U16(s->cTotalSectors >> 16);
776 p[102] = RT_H2LE_U16(s->cTotalSectors >> 32);
777 p[103] = RT_H2LE_U16(s->cTotalSectors >> 48);
778 }
779 uint32_t uCsum = ataChecksum(p, 510);
780 p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
781
782 s->iSourceSink = ATAFN_SS_NULL;
783 ataCmdOK(s, ATA_STAT_SEEK);
784 return false;
785}
786
787
788static bool ataFlushSS(AHCIATADevState *s)
789{
790 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
791 int rc;
792
793 Assert(s->uTxDir == PDMBLOCKTXDIR_NONE);
794 Assert(!s->cbElementaryTransfer);
795
796 PDMCritSectLeave(&pCtl->lock);
797
798 STAM_PROFILE_START(&s->StatFlushes, f);
799 rc = s->pDrvBlock->pfnFlush(s->pDrvBlock);
800 AssertRC(rc);
801 STAM_PROFILE_STOP(&s->StatFlushes, f);
802
803 STAM_PROFILE_START(&pCtl->StatLockWait, a);
804 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
805 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
806 ataCmdOK(s, 0);
807 return false;
808}
809
810
811static bool atapiIdentifySS(AHCIATADevState *s)
812{
813 uint16_t *p;
814 char aSerial[20];
815 RTUUID Uuid;
816 int rc;
817
818 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
819 Assert(s->cbElementaryTransfer == 512);
820 rc = s->pDrvBlock ? s->pDrvBlock->pfnGetUuid(s->pDrvBlock, &Uuid) : RTUuidClear(&Uuid);
821 if (RT_FAILURE(rc) || RTUuidIsNull(&Uuid))
822 {
823 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
824 /* Generate a predictable serial for drives which don't have a UUID. */
825 RTStrPrintf(aSerial, sizeof(aSerial), "VB%x-%04x%04x",
826 s->iLUN + ATADEVSTATE_2_DEVINS(s)->iInstance * 32,
827 pCtl->IOPortBase1, pCtl->IOPortBase2);
828 }
829 else
830 RTStrPrintf(aSerial, sizeof(aSerial), "VB%08x-%08x", Uuid.au32[0], Uuid.au32[3]);
831
832 p = (uint16_t *)s->CTXALLSUFF(pbIOBuffer);
833 memset(p, 0, 512);
834 /* Removable CDROM, 50us response, 12 byte packets */
835 p[0] = RT_H2LE_U16(2 << 14 | 5 << 8 | 1 << 7 | 2 << 5 | 0 << 0);
836 ataPadString((uint8_t *)(p + 10), aSerial, 20); /* serial number */
837 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */
838 p[21] = RT_H2LE_U16(512); /* XXX: retired, cache size in sectors */
839 ataPadString((uint8_t *)(p + 23), "1.0", 8); /* firmware version */
840 ataPadString((uint8_t *)(p + 27), "VBOX CD-ROM", 40); /* model */
841 p[49] = RT_H2LE_U16(1 << 11 | 1 << 9 | 1 << 8); /* DMA and LBA supported */
842 p[50] = RT_H2LE_U16(1 << 14); /* No drive specific standby timer minimum */
843 p[51] = RT_H2LE_U16(240); /* PIO transfer cycle */
844 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */
845 p[53] = RT_H2LE_U16(1 << 1 | 1 << 2); /* words 64-70,88 are valid */
846 p[63] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_MDMA, ATA_MDMA_MODE_MAX, s->uATATransferMode)); /* MDMA modes supported / mode enabled */
847 p[64] = RT_H2LE_U16(ATA_PIO_MODE_MAX > 2 ? (1 << (ATA_PIO_MODE_MAX - 2)) - 1 : 0); /* PIO modes beyond PIO2 supported */
848 p[65] = RT_H2LE_U16(120); /* minimum DMA multiword tx cycle time */
849 p[66] = RT_H2LE_U16(120); /* recommended DMA multiword tx cycle time */
850 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
851 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
852 p[73] = RT_H2LE_U16(0x003e); /* ATAPI CDROM major */
853 p[74] = RT_H2LE_U16(9); /* ATAPI CDROM minor */
854 p[75] = RT_H2LE_U16(1); /* queue depth 1 */
855 p[80] = RT_H2LE_U16(0x7e); /* support everything up to ATA/ATAPI-6 */
856 p[81] = RT_H2LE_U16(0x22); /* conforms to ATA/ATAPI-6 */
857 p[82] = RT_H2LE_U16(1 << 4 | 1 << 9); /* supports packet command set and DEVICE RESET */
858 p[83] = RT_H2LE_U16(1 << 14);
859 p[84] = RT_H2LE_U16(1 << 14);
860 p[85] = RT_H2LE_U16(1 << 4 | 1 << 9); /* enabled packet command set and DEVICE RESET */
861 p[86] = RT_H2LE_U16(0);
862 p[87] = RT_H2LE_U16(1 << 14);
863 p[88] = RT_H2LE_U16(ATA_TRANSFER_ID(ATA_MODE_UDMA, ATA_UDMA_MODE_MAX, s->uATATransferMode)); /* UDMA modes supported / mode enabled */
864 p[93] = RT_H2LE_U16((1 | 1 << 1) << ((s->iLUN & 1) == 0 ? 0 : 8) | 1 << 13 | 1 << 14);
865 uint32_t uCsum = ataChecksum(p, 510);
866 p[255] = RT_H2LE_U16(0xa5 | (uCsum << 8)); /* Integrity word */
867 s->iSourceSink = ATAFN_SS_NULL;
868 ataCmdOK(s, ATA_STAT_SEEK);
869 return false;
870}
871
872
873static void ataSetSignature(AHCIATADevState *s)
874{
875 s->uATARegSelect &= 0xf0; /* clear head */
876 /* put signature */
877 s->uATARegNSector = 1;
878 s->uATARegSector = 1;
879 if (s->fATAPI)
880 {
881 s->uATARegLCyl = 0x14;
882 s->uATARegHCyl = 0xeb;
883 }
884 else if (s->pDrvBlock)
885 {
886 s->uATARegLCyl = 0;
887 s->uATARegHCyl = 0;
888 }
889 else
890 {
891 s->uATARegLCyl = 0xff;
892 s->uATARegHCyl = 0xff;
893 }
894}
895
896
897static uint64_t ataGetSector(AHCIATADevState *s)
898{
899 uint64_t iLBA;
900 if (s->uATARegSelect & 0x40)
901 {
902 /* any LBA variant */
903 if (s->fLBA48)
904 {
905 /* LBA48 */
906 iLBA = ((uint64_t)s->uATARegHCylHOB << 40) |
907 ((uint64_t)s->uATARegLCylHOB << 32) |
908 ((uint64_t)s->uATARegSectorHOB << 24) |
909 ((uint64_t)s->uATARegHCyl << 16) |
910 ((uint64_t)s->uATARegLCyl << 8) |
911 s->uATARegSector;
912 }
913 else
914 {
915 /* LBA */
916 iLBA = ((s->uATARegSelect & 0x0f) << 24) | (s->uATARegHCyl << 16) |
917 (s->uATARegLCyl << 8) | s->uATARegSector;
918 }
919 }
920 else
921 {
922 /* CHS */
923 iLBA = ((s->uATARegHCyl << 8) | s->uATARegLCyl) * s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors +
924 (s->uATARegSelect & 0x0f) * s->PCHSGeometry.cSectors +
925 (s->uATARegSector - 1);
926 }
927 return iLBA;
928}
929
930static void ataSetSector(AHCIATADevState *s, uint64_t iLBA)
931{
932 uint32_t cyl, r;
933 if (s->uATARegSelect & 0x40)
934 {
935 /* any LBA variant */
936 if (s->fLBA48)
937 {
938 /* LBA48 */
939 s->uATARegHCylHOB = iLBA >> 40;
940 s->uATARegLCylHOB = iLBA >> 32;
941 s->uATARegSectorHOB = iLBA >> 24;
942 s->uATARegHCyl = iLBA >> 16;
943 s->uATARegLCyl = iLBA >> 8;
944 s->uATARegSector = iLBA;
945 }
946 else
947 {
948 /* LBA */
949 s->uATARegSelect = (s->uATARegSelect & 0xf0) | (iLBA >> 24);
950 s->uATARegHCyl = (iLBA >> 16);
951 s->uATARegLCyl = (iLBA >> 8);
952 s->uATARegSector = (iLBA);
953 }
954 }
955 else
956 {
957 /* CHS */
958 cyl = iLBA / (s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors);
959 r = iLBA % (s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors);
960 s->uATARegHCyl = cyl >> 8;
961 s->uATARegLCyl = cyl;
962 s->uATARegSelect = (s->uATARegSelect & 0xf0) | ((r / s->PCHSGeometry.cSectors) & 0x0f);
963 s->uATARegSector = (r % s->PCHSGeometry.cSectors) + 1;
964 }
965}
966
967
968static void ataWarningDiskFull(PPDMDEVINS pDevIns)
969{
970 int rc;
971 LogRel(("AHCI ATA: Host disk full\n"));
972 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_DISKFULL",
973 N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
974 AssertRC(rc);
975}
976
977static void ataWarningFileTooBig(PPDMDEVINS pDevIns)
978{
979 int rc;
980 LogRel(("AHCI ATA: File too big\n"));
981 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_FILETOOBIG",
982 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"));
983 AssertRC(rc);
984}
985
986static void ataWarningISCSI(PPDMDEVINS pDevIns)
987{
988 int rc;
989 LogRel(("AHCI ATA: iSCSI target unavailable\n"));
990 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_ISCSIDOWN",
991 N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
992 AssertRC(rc);
993}
994
995static bool ataIsRedoSetWarning(AHCIATADevState *s, int rc)
996{
997 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
998 Assert(!PDMCritSectIsOwner(&pCtl->lock));
999 if (rc == VERR_DISK_FULL)
1000 {
1001 pCtl->fRedoIdle = true;
1002 ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
1003 return true;
1004 }
1005 if (rc == VERR_FILE_TOO_BIG)
1006 {
1007 pCtl->fRedoIdle = true;
1008 ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
1009 return true;
1010 }
1011 if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1012 {
1013 pCtl->fRedoIdle = true;
1014 /* iSCSI connection abort (first error) or failure to reestablish
1015 * connection (second error). Pause VM. On resume we'll retry. */
1016 ataWarningISCSI(ATADEVSTATE_2_DEVINS(s));
1017 return true;
1018 }
1019 return false;
1020}
1021
1022
1023static int ataReadSectors(AHCIATADevState *s, uint64_t u64Sector, void *pvBuf,
1024 uint32_t cSectors, bool *pfRedo)
1025{
1026 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
1027 int rc;
1028
1029 PDMCritSectLeave(&pCtl->lock);
1030
1031 STAM_PROFILE_ADV_START(&s->StatReads, r);
1032 s->pLed->Asserted.s.fReading = s->pLed->Actual.s.fReading = 1;
1033 rc = s->pDrvBlock->pfnRead(s->pDrvBlock, u64Sector * 512, pvBuf, cSectors * 512);
1034 s->pLed->Actual.s.fReading = 0;
1035 STAM_PROFILE_ADV_STOP(&s->StatReads, r);
1036
1037 STAM_REL_COUNTER_ADD(s->pStatBytesRead, cSectors * 512);
1038
1039 if (RT_SUCCESS(rc))
1040 *pfRedo = false;
1041 else
1042 *pfRedo = ataIsRedoSetWarning(s, rc);
1043
1044 STAM_PROFILE_START(&pCtl->StatLockWait, a);
1045 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
1046 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1047 return rc;
1048}
1049
1050
1051static int ataWriteSectors(AHCIATADevState *s, uint64_t u64Sector,
1052 const void *pvBuf, uint32_t cSectors, bool *pfRedo)
1053{
1054 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
1055 int rc;
1056
1057 PDMCritSectLeave(&pCtl->lock);
1058
1059 STAM_PROFILE_ADV_START(&s->StatWrites, w);
1060 s->pLed->Asserted.s.fWriting = s->pLed->Actual.s.fWriting = 1;
1061 rc = s->pDrvBlock->pfnWrite(s->pDrvBlock, u64Sector * 512, pvBuf, cSectors * 512);
1062 s->pLed->Actual.s.fWriting = 0;
1063 STAM_PROFILE_ADV_STOP(&s->StatWrites, w);
1064
1065 STAM_REL_COUNTER_ADD(s->pStatBytesWritten, cSectors * 512);
1066
1067 if (RT_SUCCESS(rc))
1068 *pfRedo = false;
1069 else
1070 *pfRedo = ataIsRedoSetWarning(s, rc);
1071
1072 STAM_PROFILE_START(&pCtl->StatLockWait, a);
1073 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
1074 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1075 return rc;
1076}
1077
1078
1079static void ataReadWriteSectorsBT(AHCIATADevState *s)
1080{
1081 uint32_t cSectors;
1082
1083 cSectors = s->cbTotalTransfer / 512;
1084 if (cSectors > s->cSectorsPerIRQ)
1085 s->cbElementaryTransfer = s->cSectorsPerIRQ * 512;
1086 else
1087 s->cbElementaryTransfer = cSectors * 512;
1088 if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE)
1089 ataCmdOK(s, 0);
1090}
1091
1092
1093static bool ataReadSectorsSS(AHCIATADevState *s)
1094{
1095 int rc;
1096 uint32_t cSectors;
1097 uint64_t iLBA;
1098 bool fRedo;
1099
1100 cSectors = s->cbElementaryTransfer / 512;
1101 Assert(cSectors);
1102 iLBA = ataGetSector(s);
1103 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
1104 rc = ataReadSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors, &fRedo);
1105 if (RT_SUCCESS(rc))
1106 {
1107 ataSetSector(s, iLBA + cSectors);
1108 if (s->cbElementaryTransfer == s->cbTotalTransfer)
1109 s->iSourceSink = ATAFN_SS_NULL;
1110 ataCmdOK(s, ATA_STAT_SEEK);
1111 }
1112 else
1113 {
1114 if (fRedo)
1115 return true;
1116 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1117 LogRel(("AHCI ATA: LUN#%d: disk read error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
1118 s->iLUN, rc, iLBA, cSectors));
1119 ataCmdError(s, ID_ERR);
1120 }
1121 return false;
1122}
1123
1124
1125static bool ataWriteSectorsSS(AHCIATADevState *s)
1126{
1127 int rc;
1128 uint32_t cSectors;
1129 uint64_t iLBA;
1130 bool fRedo;
1131
1132 cSectors = s->cbElementaryTransfer / 512;
1133 Assert(cSectors);
1134 iLBA = ataGetSector(s);
1135 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
1136 rc = ataWriteSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors, &fRedo);
1137 if (RT_SUCCESS(rc))
1138 {
1139 ataSetSector(s, iLBA + cSectors);
1140 if (!s->cbTotalTransfer)
1141 s->iSourceSink = ATAFN_SS_NULL;
1142 ataCmdOK(s, ATA_STAT_SEEK);
1143 }
1144 else
1145 {
1146 if (fRedo)
1147 return true;
1148 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1149 LogRel(("AHCI ATA: LUN#%d: disk write error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
1150 s->iLUN, rc, iLBA, cSectors));
1151 ataCmdError(s, ID_ERR);
1152 }
1153 return false;
1154}
1155
1156
1157static void atapiCmdOK(AHCIATADevState *s)
1158{
1159 s->uATARegError = 0;
1160 ataSetStatusValue(s, ATA_STAT_READY);
1161 s->uATARegNSector = (s->uATARegNSector & ~7)
1162 | ((s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE) ? ATAPI_INT_REASON_IO : 0)
1163 | (!s->cbTotalTransfer ? ATAPI_INT_REASON_CD : 0);
1164 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
1165 memset(s->abATAPISense, '\0', sizeof(s->abATAPISense));
1166 s->abATAPISense[0] = 0x70 | (1 << 7);
1167 s->abATAPISense[7] = 10;
1168}
1169
1170
1171static void atapiCmdError(AHCIATADevState *s, const uint8_t *pabATAPISense, size_t cbATAPISense)
1172{
1173 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, pabATAPISense[2] & 0x0f, SCSISenseText(pabATAPISense[2] & 0x0f),
1174 pabATAPISense[12], pabATAPISense[13], SCSISenseExtText(pabATAPISense[12], pabATAPISense[13])));
1175 s->uATARegError = pabATAPISense[2] << 4;
1176 ataSetStatusValue(s, ATA_STAT_READY | ATA_STAT_ERR);
1177 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
1178 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
1179 memset(s->abATAPISense, '\0', sizeof(s->abATAPISense));
1180 memcpy(s->abATAPISense, pabATAPISense, RT_MIN(cbATAPISense, sizeof(s->abATAPISense)));
1181 s->cbTotalTransfer = 0;
1182 s->cbElementaryTransfer = 0;
1183 s->iIOBufferCur = 0;
1184 s->iIOBufferEnd = 0;
1185 s->uTxDir = PDMBLOCKTXDIR_NONE;
1186 s->iBeginTransfer = ATAFN_BT_NULL;
1187 s->iSourceSink = ATAFN_SS_NULL;
1188}
1189
1190
1191/** @todo deprecated function - doesn't provide enough info. Replace by direct
1192 * calls to atapiCmdError() with full data. */
1193static void atapiCmdErrorSimple(AHCIATADevState *s, uint8_t uATAPISenseKey, uint8_t uATAPIASC)
1194{
1195 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
1196 memset(abATAPISense, '\0', sizeof(abATAPISense));
1197 abATAPISense[0] = 0x70 | (1 << 7);
1198 abATAPISense[2] = uATAPISenseKey & 0x0f;
1199 abATAPISense[7] = 10;
1200 abATAPISense[12] = uATAPIASC;
1201 atapiCmdError(s, abATAPISense, sizeof(abATAPISense));
1202}
1203
1204
1205static void atapiCmdBT(AHCIATADevState *s)
1206{
1207 s->fATAPITransfer = true;
1208 s->cbElementaryTransfer = s->cbTotalTransfer;
1209 if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE)
1210 atapiCmdOK(s);
1211}
1212
1213
1214static void atapiPassthroughCmdBT(AHCIATADevState *s)
1215{
1216 /* @todo implement an algorithm for correctly determining the read and
1217 * write sector size without sending additional commands to the drive.
1218 * This should be doable by saving processing the configuration requests
1219 * and replies. */
1220#if 0
1221 if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE)
1222 {
1223 uint8_t cmd = s->aATAPICmd[0];
1224 if (cmd == SCSI_WRITE_10 || cmd == SCSI_WRITE_12 || cmd == SCSI_WRITE_AND_VERIFY_10)
1225 {
1226 uint8_t aModeSenseCmd[10];
1227 uint8_t aModeSenseResult[16];
1228 uint8_t uDummySense;
1229 uint32_t cbTransfer;
1230 int rc;
1231
1232 cbTransfer = sizeof(aModeSenseResult);
1233 aModeSenseCmd[0] = SCSI_MODE_SENSE_10;
1234 aModeSenseCmd[1] = 0x08; /* disable block descriptor = 1 */
1235 aModeSenseCmd[2] = (SCSI_PAGECONTROL_CURRENT << 6) | SCSI_MODEPAGE_WRITE_PARAMETER;
1236 aModeSenseCmd[3] = 0; /* subpage code */
1237 aModeSenseCmd[4] = 0; /* reserved */
1238 aModeSenseCmd[5] = 0; /* reserved */
1239 aModeSenseCmd[6] = 0; /* reserved */
1240 aModeSenseCmd[7] = cbTransfer >> 8;
1241 aModeSenseCmd[8] = cbTransfer & 0xff;
1242 aModeSenseCmd[9] = 0; /* control */
1243 rc = s->pDrvBlock->pfnSendCmd(s->pDrvBlock, aModeSenseCmd, PDMBLOCKTXDIR_FROM_DEVICE, aModeSenseResult, &cbTransfer, &uDummySense, 500);
1244 if (RT_FAILURE(rc))
1245 {
1246 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_NONE);
1247 return;
1248 }
1249 /* Select sector size based on the current data block type. */
1250 switch (aModeSenseResult[12] & 0x0f)
1251 {
1252 case 0:
1253 s->cbATAPISector = 2352;
1254 break;
1255 case 1:
1256 s->cbATAPISector = 2368;
1257 break;
1258 case 2:
1259 case 3:
1260 s->cbATAPISector = 2448;
1261 break;
1262 case 8:
1263 case 10:
1264 s->cbATAPISector = 2048;
1265 break;
1266 case 9:
1267 s->cbATAPISector = 2336;
1268 break;
1269 case 11:
1270 s->cbATAPISector = 2056;
1271 break;
1272 case 12:
1273 s->cbATAPISector = 2324;
1274 break;
1275 case 13:
1276 s->cbATAPISector = 2332;
1277 break;
1278 default:
1279 s->cbATAPISector = 0;
1280 }
1281 Log2(("%s: sector size %d\n", __FUNCTION__, s->cbATAPISector));
1282 s->cbTotalTransfer *= s->cbATAPISector;
1283 if (s->cbTotalTransfer == 0)
1284 s->uTxDir = PDMBLOCKTXDIR_NONE;
1285 }
1286 }
1287#endif
1288 atapiCmdBT(s);
1289}
1290
1291
1292static bool atapiReadSS(AHCIATADevState *s)
1293{
1294 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
1295 int rc = VINF_SUCCESS;
1296 uint32_t cbTransfer, cSectors;
1297
1298 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1299 cbTransfer = RT_MIN(s->cbTotalTransfer, s->cbIOBuffer);
1300 cSectors = cbTransfer / s->cbATAPISector;
1301 Assert(cSectors * s->cbATAPISector <= cbTransfer);
1302 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, s->iATAPILBA));
1303
1304 PDMCritSectLeave(&pCtl->lock);
1305
1306 STAM_PROFILE_ADV_START(&s->StatReads, r);
1307 s->pLed->Asserted.s.fReading = s->pLed->Actual.s.fReading = 1;
1308 switch (s->cbATAPISector)
1309 {
1310 case 2048:
1311 rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)s->iATAPILBA * s->cbATAPISector, s->CTXALLSUFF(pbIOBuffer), s->cbATAPISector * cSectors);
1312 break;
1313 case 2352:
1314 {
1315 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1316
1317 for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++)
1318 {
1319 /* sync bytes */
1320 *pbBuf++ = 0x00;
1321 memset(pbBuf, 0xff, 11);
1322 pbBuf += 11;
1323 /* MSF */
1324 ataLBA2MSF(pbBuf, i);
1325 pbBuf += 3;
1326 *pbBuf++ = 0x01; /* mode 1 data */
1327 /* data */
1328 rc = s->pDrvBlock->pfnRead(s->pDrvBlock, (uint64_t)i * 2048, pbBuf, 2048);
1329 if (RT_FAILURE(rc))
1330 break;
1331 pbBuf += 2048;
1332 /* ECC */
1333 memset(pbBuf, 0, 288);
1334 pbBuf += 288;
1335 }
1336 }
1337 break;
1338 default:
1339 break;
1340 }
1341 STAM_PROFILE_ADV_STOP(&s->StatReads, r);
1342
1343 STAM_PROFILE_START(&pCtl->StatLockWait, a);
1344 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
1345 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1346
1347 if (RT_SUCCESS(rc))
1348 {
1349 s->pLed->Actual.s.fReading = 0;
1350 STAM_REL_COUNTER_ADD(s->pStatBytesRead, s->cbATAPISector * cSectors);
1351
1352 /* The initial buffer end value has been set up based on the total
1353 * transfer size. But the I/O buffer size limits what can actually be
1354 * done in one transfer, so set the actual value of the buffer end. */
1355 s->cbElementaryTransfer = cbTransfer;
1356 if (cbTransfer >= s->cbTotalTransfer)
1357 s->iSourceSink = ATAFN_SS_NULL;
1358 atapiCmdOK(s);
1359 s->iATAPILBA += cSectors;
1360 }
1361 else
1362 {
1363 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1364 LogRel(("AHCI ATA: LUN#%d: CD-ROM read error, %d sectors at LBA %d\n", s->iLUN, cSectors, s->iATAPILBA));
1365 atapiCmdErrorSimple(s, SCSI_SENSE_MEDIUM_ERROR, SCSI_ASC_READ_ERROR);
1366 }
1367 return false;
1368}
1369
1370
1371static bool atapiPassthroughSS(AHCIATADevState *s)
1372{
1373 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
1374 int rc = VINF_SUCCESS;
1375 uint8_t abATAPISense[ATAPI_SENSE_SIZE];
1376 uint32_t cbTransfer;
1377 PSTAMPROFILEADV pProf = NULL;
1378
1379 cbTransfer = s->cbElementaryTransfer;
1380
1381 if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE)
1382 Log3(("ATAPI PT data write (%d): %.*Rhxs\n", cbTransfer, cbTransfer, s->CTXALLSUFF(pbIOBuffer)));
1383
1384 /* Simple heuristics: if there is at least one sector of data
1385 * to transfer, it's worth updating the LEDs. */
1386 if (cbTransfer >= 2048)
1387 {
1388 if (s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE)
1389 {
1390 s->pLed->Asserted.s.fReading = s->pLed->Actual.s.fReading = 1;
1391 pProf = &s->StatReads;
1392 }
1393 else
1394 {
1395 s->pLed->Asserted.s.fWriting = s->pLed->Actual.s.fWriting = 1;
1396 pProf = &s->StatWrites;
1397 }
1398 }
1399
1400 PDMCritSectLeave(&pCtl->lock);
1401
1402 memset(abATAPISense, '\0', sizeof(abATAPISense));
1403 if (pProf) { STAM_PROFILE_ADV_START(pProf, b); }
1404 if (cbTransfer > 100 * _1K)
1405 {
1406 /* Linux accepts commands with up to 100KB of data, but expects
1407 * us to handle commands with up to 128KB of data. The usual
1408 * imbalance of powers. */
1409 uint8_t aATAPICmd[ATAPI_PACKET_SIZE];
1410 uint32_t iATAPILBA, cSectors, cReqSectors, cbCurrTX;
1411 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1412
1413 switch (s->aATAPICmd[0])
1414 {
1415 case SCSI_READ_10:
1416 case SCSI_WRITE_10:
1417 case SCSI_WRITE_AND_VERIFY_10:
1418 iATAPILBA = ataBE2H_U32(s->aATAPICmd + 2);
1419 cSectors = ataBE2H_U16(s->aATAPICmd + 7);
1420 break;
1421 case SCSI_READ_12:
1422 case SCSI_WRITE_12:
1423 iATAPILBA = ataBE2H_U32(s->aATAPICmd + 2);
1424 cSectors = ataBE2H_U32(s->aATAPICmd + 6);
1425 break;
1426 case SCSI_READ_CD:
1427 iATAPILBA = ataBE2H_U32(s->aATAPICmd + 2);
1428 cSectors = ataBE2H_U24(s->aATAPICmd + 6) / s->cbATAPISector;
1429 break;
1430 case SCSI_READ_CD_MSF:
1431 iATAPILBA = ataMSF2LBA(s->aATAPICmd + 3);
1432 cSectors = ataMSF2LBA(s->aATAPICmd + 6) - iATAPILBA;
1433 break;
1434 default:
1435 AssertMsgFailed(("Don't know how to split command %#04x\n", s->aATAPICmd[0]));
1436 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1437 LogRel(("AHCI ATA: LUN#%d: CD-ROM passthrough split error\n", s->iLUN));
1438 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
1439 {
1440 STAM_PROFILE_START(&pCtl->StatLockWait, a);
1441 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
1442 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1443 }
1444 return false;
1445 }
1446 memcpy(aATAPICmd, s->aATAPICmd, ATAPI_PACKET_SIZE);
1447 cReqSectors = 0;
1448 for (uint32_t i = cSectors; i > 0; i -= cReqSectors)
1449 {
1450 if (i * s->cbATAPISector > 100 * _1K)
1451 cReqSectors = (100 * _1K) / s->cbATAPISector;
1452 else
1453 cReqSectors = i;
1454 cbCurrTX = s->cbATAPISector * cReqSectors;
1455 switch (s->aATAPICmd[0])
1456 {
1457 case SCSI_READ_10:
1458 case SCSI_WRITE_10:
1459 case SCSI_WRITE_AND_VERIFY_10:
1460 ataH2BE_U32(aATAPICmd + 2, iATAPILBA);
1461 ataH2BE_U16(aATAPICmd + 7, cReqSectors);
1462 break;
1463 case SCSI_READ_12:
1464 case SCSI_WRITE_12:
1465 ataH2BE_U32(aATAPICmd + 2, iATAPILBA);
1466 ataH2BE_U32(aATAPICmd + 6, cReqSectors);
1467 break;
1468 case SCSI_READ_CD:
1469 ataH2BE_U32(s->aATAPICmd + 2, iATAPILBA);
1470 ataH2BE_U24(s->aATAPICmd + 6, cbCurrTX);
1471 break;
1472 case SCSI_READ_CD_MSF:
1473 ataLBA2MSF(aATAPICmd + 3, iATAPILBA);
1474 ataLBA2MSF(aATAPICmd + 6, iATAPILBA + cReqSectors);
1475 break;
1476 }
1477 rc = s->pDrvBlock->pfnSendCmd(s->pDrvBlock, aATAPICmd, (PDMBLOCKTXDIR)s->uTxDir, pbBuf, &cbCurrTX, abATAPISense, sizeof(abATAPISense), 30000 /**< @todo timeout */);
1478 if (rc != VINF_SUCCESS)
1479 break;
1480 iATAPILBA += cReqSectors;
1481 pbBuf += s->cbATAPISector * cReqSectors;
1482 }
1483 }
1484 else
1485 rc = s->pDrvBlock->pfnSendCmd(s->pDrvBlock, s->aATAPICmd, (PDMBLOCKTXDIR)s->uTxDir, s->CTXALLSUFF(pbIOBuffer), &cbTransfer, abATAPISense, sizeof(abATAPISense), 30000 /**< @todo timeout */);
1486 if (pProf) { STAM_PROFILE_ADV_STOP(pProf, b); }
1487
1488 STAM_PROFILE_START(&pCtl->StatLockWait, a);
1489 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
1490 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1491
1492 /* Update the LEDs and the read/write statistics. */
1493 if (cbTransfer >= 2048)
1494 {
1495 if (s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE)
1496 {
1497 s->pLed->Actual.s.fReading = 0;
1498 STAM_REL_COUNTER_ADD(s->pStatBytesRead, cbTransfer);
1499 }
1500 else
1501 {
1502 s->pLed->Actual.s.fWriting = 0;
1503 STAM_REL_COUNTER_ADD(s->pStatBytesWritten, cbTransfer);
1504 }
1505 }
1506
1507 if (RT_SUCCESS(rc))
1508 {
1509 if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
1510 {
1511 Assert(cbTransfer <= s->cbTotalTransfer);
1512 /* Reply with the same amount of data as the real drive. */
1513 s->cbTotalTransfer = cbTransfer;
1514 /* The initial buffer end value has been set up based on the total
1515 * transfer size. But the I/O buffer size limits what can actually be
1516 * done in one transfer, so set the actual value of the buffer end. */
1517 s->cbElementaryTransfer = cbTransfer;
1518 if (s->aATAPICmd[0] == SCSI_INQUIRY)
1519 {
1520 /* Make sure that the real drive cannot be identified.
1521 * Motivation: changing the VM configuration should be as
1522 * invisible as possible to the guest. */
1523 Log3(("ATAPI PT inquiry data before (%d): %.*Rhxs\n", cbTransfer, cbTransfer, s->CTXALLSUFF(pbIOBuffer)));
1524 ataSCSIPadStr(s->CTXALLSUFF(pbIOBuffer) + 8, "VBOX", 8);
1525 ataSCSIPadStr(s->CTXALLSUFF(pbIOBuffer) + 16, "CD-ROM", 16);
1526 ataSCSIPadStr(s->CTXALLSUFF(pbIOBuffer) + 32, "1.0", 4);
1527 }
1528 if (cbTransfer)
1529 Log3(("ATAPI PT data read (%d): %.*Rhxs\n", cbTransfer, cbTransfer, s->CTXALLSUFF(pbIOBuffer)));
1530 }
1531 s->iSourceSink = ATAFN_SS_NULL;
1532 atapiCmdOK(s);
1533 }
1534 else
1535 {
1536 if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1537 {
1538 uint8_t u8Cmd = s->aATAPICmd[0];
1539 do
1540 {
1541 /* don't log superfluous errors */
1542 if ( rc == VERR_DEV_IO_ERROR
1543 && ( u8Cmd == SCSI_TEST_UNIT_READY
1544 || u8Cmd == SCSI_READ_CAPACITY
1545 || u8Cmd == SCSI_READ_TOC_PMA_ATIP))
1546 break;
1547 LogRel(("AHCI ATA: LUN#%d: CD-ROM passthrough command (%#04x) error %d %Rrc\n", s->iLUN, u8Cmd, abATAPISense[0] & 0x0f, rc));
1548 } while (0);
1549 }
1550 atapiCmdError(s, abATAPISense, sizeof(abATAPISense));
1551 }
1552 return false;
1553}
1554
1555
1556static bool atapiReadSectors(AHCIATADevState *s, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
1557{
1558 Assert(cSectors > 0);
1559 s->iATAPILBA = iATAPILBA;
1560 s->cbATAPISector = cbSector;
1561 ataStartTransfer(s, cSectors * cbSector, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ, true);
1562 return false;
1563}
1564
1565
1566static bool atapiReadCapacitySS(AHCIATADevState *s)
1567{
1568 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1569
1570 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1571 Assert(s->cbElementaryTransfer <= 8);
1572 ataH2BE_U32(pbBuf, s->cTotalSectors - 1);
1573 ataH2BE_U32(pbBuf + 4, 2048);
1574 s->iSourceSink = ATAFN_SS_NULL;
1575 atapiCmdOK(s);
1576 return false;
1577}
1578
1579
1580static bool atapiReadDiscInformationSS(AHCIATADevState *s)
1581{
1582 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1583
1584 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1585 Assert(s->cbElementaryTransfer <= 34);
1586 memset(pbBuf, '\0', 34);
1587 ataH2BE_U16(pbBuf, 32);
1588 pbBuf[2] = (0 << 4) | (3 << 2) | (2 << 0); /* not erasable, complete session, complete disc */
1589 pbBuf[3] = 1; /* number of first track */
1590 pbBuf[4] = 1; /* number of sessions (LSB) */
1591 pbBuf[5] = 1; /* first track number in last session (LSB) */
1592 pbBuf[6] = 1; /* last track number in last session (LSB) */
1593 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 */
1594 pbBuf[8] = 0; /* disc type = CD-ROM */
1595 pbBuf[9] = 0; /* number of sessions (MSB) */
1596 pbBuf[10] = 0; /* number of sessions (MSB) */
1597 pbBuf[11] = 0; /* number of sessions (MSB) */
1598 ataH2BE_U32(pbBuf + 16, 0x00ffffff); /* last session lead-in start time is not available */
1599 ataH2BE_U32(pbBuf + 20, 0x00ffffff); /* last possible start time for lead-out is not available */
1600 s->iSourceSink = ATAFN_SS_NULL;
1601 atapiCmdOK(s);
1602 return false;
1603}
1604
1605
1606static bool atapiReadTrackInformationSS(AHCIATADevState *s)
1607{
1608 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1609
1610 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1611 Assert(s->cbElementaryTransfer <= 36);
1612 /* Accept address/number type of 1 only, and only track 1 exists. */
1613 if ((s->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&s->aATAPICmd[2]) != 1)
1614 {
1615 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
1616 return false;
1617 }
1618 memset(pbBuf, '\0', 36);
1619 ataH2BE_U16(pbBuf, 34);
1620 pbBuf[2] = 1; /* track number (LSB) */
1621 pbBuf[3] = 1; /* session number (LSB) */
1622 pbBuf[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */
1623 pbBuf[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */
1624 pbBuf[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */
1625 ataH2BE_U32(pbBuf + 8, 0); /* track start address is 0 */
1626 ataH2BE_U32(pbBuf + 24, s->cTotalSectors); /* track size */
1627 pbBuf[32] = 0; /* track number (MSB) */
1628 pbBuf[33] = 0; /* session number (MSB) */
1629 s->iSourceSink = ATAFN_SS_NULL;
1630 atapiCmdOK(s);
1631 return false;
1632}
1633
1634
1635static bool atapiGetConfigurationSS(AHCIATADevState *s)
1636{
1637 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1638 uint16_t u16Sfn = ataBE2H_U16(&s->aATAPICmd[2]);
1639
1640 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1641 Assert(s->cbElementaryTransfer <= 32);
1642 /* Accept valid request types only, and only starting feature 0. */
1643 if ((s->aATAPICmd[1] & 0x03) == 3 || u16Sfn != 0)
1644 {
1645 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
1646 return false;
1647 }
1648 memset(pbBuf, '\0', 32);
1649 ataH2BE_U32(pbBuf, 16);
1650 /** @todo implement switching between CD-ROM and DVD-ROM profile (the only
1651 * way to differentiate them right now is based on the image size). Also
1652 * implement signalling "no current profile" if no medium is loaded. */
1653 ataH2BE_U16(pbBuf + 6, 0x08); /* current profile: read-only CD */
1654
1655 ataH2BE_U16(pbBuf + 8, 0); /* feature 0: list of profiles supported */
1656 pbBuf[10] = (0 << 2) | (1 << 1) | (1 || 0); /* version 0, persistent, current */
1657 pbBuf[11] = 8; /* additional bytes for profiles */
1658 /* The MMC-3 spec says that DVD-ROM read capability should be reported
1659 * before CD-ROM read capability. */
1660 ataH2BE_U16(pbBuf + 12, 0x10); /* profile: read-only DVD */
1661 pbBuf[14] = (0 << 0); /* NOT current profile */
1662 ataH2BE_U16(pbBuf + 16, 0x08); /* profile: read only CD */
1663 pbBuf[18] = (1 << 0); /* current profile */
1664 /* Other profiles we might want to add in the future: 0x40 (BD-ROM) and 0x50 (HDDVD-ROM) */
1665 s->iSourceSink = ATAFN_SS_NULL;
1666 atapiCmdOK(s);
1667 return false;
1668}
1669
1670
1671static bool atapiGetEventStatusNotificationSS(AHCIATADevState *s)
1672{
1673 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer);
1674
1675 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1676 Assert(s->cbElementaryTransfer <= 8);
1677
1678 if (!(s->aATAPICmd[1] & 1))
1679 {
1680 /* no asynchronous operation supported */
1681 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
1682 return false;
1683 }
1684
1685 uint32_t OldStatus, NewStatus;
1686 do
1687 {
1688 OldStatus = ASMAtomicReadU32(&s->MediaEventStatus);
1689 NewStatus = ATA_EVENT_STATUS_UNCHANGED;
1690 switch (OldStatus)
1691 {
1692 case ATA_EVENT_STATUS_MEDIA_NEW:
1693 /* mount */
1694 ataH2BE_U16(pbBuf + 0, 6);
1695 pbBuf[2] = 0x04; /* media */
1696 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
1697 pbBuf[4] = 0x02; /* new medium */
1698 pbBuf[5] = 0x02; /* medium present / door closed */
1699 pbBuf[6] = 0x00;
1700 pbBuf[7] = 0x00;
1701 break;
1702
1703 case ATA_EVENT_STATUS_MEDIA_CHANGED:
1704 case ATA_EVENT_STATUS_MEDIA_REMOVED:
1705 /* umount */
1706 ataH2BE_U16(pbBuf + 0, 6);
1707 pbBuf[2] = 0x04; /* media */
1708 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
1709 pbBuf[4] = 0x03; /* media removal */
1710 pbBuf[5] = 0x00; /* medium absent / door closed */
1711 pbBuf[6] = 0x00;
1712 pbBuf[7] = 0x00;
1713 if (OldStatus == ATA_EVENT_STATUS_MEDIA_CHANGED)
1714 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW;
1715 break;
1716
1717 case ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED: /* currently unused */
1718 ataH2BE_U16(pbBuf + 0, 6);
1719 pbBuf[2] = 0x04; /* media */
1720 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
1721 pbBuf[4] = 0x01; /* eject requested (eject button pressed) */
1722 pbBuf[5] = 0x02; /* medium present / door closed */
1723 pbBuf[6] = 0x00;
1724 pbBuf[7] = 0x00;
1725 break;
1726
1727 case ATA_EVENT_STATUS_UNCHANGED:
1728 default:
1729 ataH2BE_U16(pbBuf + 0, 6);
1730 pbBuf[2] = 0x01; /* operational change request / notification */
1731 pbBuf[3] = 0x5e; /* supported = busy|media|external|power|operational */
1732 pbBuf[4] = 0x00;
1733 pbBuf[5] = 0x00;
1734 pbBuf[6] = 0x00;
1735 pbBuf[7] = 0x00;
1736 break;
1737 }
1738 } while (!ASMAtomicCmpXchgU32(&s->MediaEventStatus, NewStatus, OldStatus));
1739
1740 s->iSourceSink = ATAFN_SS_NULL;
1741 atapiCmdOK(s);
1742 return false;
1743}
1744
1745
1746static bool atapiInquirySS(AHCIATADevState *s)
1747{
1748 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1749
1750 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1751 Assert(s->cbElementaryTransfer <= 36);
1752 pbBuf[0] = 0x05; /* CD-ROM */
1753 pbBuf[1] = 0x80; /* removable */
1754#if 1/*ndef VBOX*/ /** @todo implement MESN + AENC. (async notification on removal and stuff.) */
1755 pbBuf[2] = 0x00; /* ISO */
1756 pbBuf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
1757#else
1758 pbBuf[2] = 0x00; /* ISO */
1759 pbBuf[3] = 0x91; /* format 1, MESN=1, AENC=9 ??? */
1760#endif
1761 pbBuf[4] = 31; /* additional length */
1762 pbBuf[5] = 0; /* reserved */
1763 pbBuf[6] = 0; /* reserved */
1764 pbBuf[7] = 0; /* reserved */
1765 ataSCSIPadStr(pbBuf + 8, "VBOX", 8);
1766 ataSCSIPadStr(pbBuf + 16, "CD-ROM", 16);
1767 ataSCSIPadStr(pbBuf + 32, "1.0", 4);
1768 s->iSourceSink = ATAFN_SS_NULL;
1769 atapiCmdOK(s);
1770 return false;
1771}
1772
1773
1774static bool atapiModeSenseErrorRecoverySS(AHCIATADevState *s)
1775{
1776 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1777
1778 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1779 Assert(s->cbElementaryTransfer <= 16);
1780 ataH2BE_U16(&pbBuf[0], 16 + 6);
1781 pbBuf[2] = 0x70;
1782 pbBuf[3] = 0;
1783 pbBuf[4] = 0;
1784 pbBuf[5] = 0;
1785 pbBuf[6] = 0;
1786 pbBuf[7] = 0;
1787
1788 pbBuf[8] = 0x01;
1789 pbBuf[9] = 0x06;
1790 pbBuf[10] = 0x00;
1791 pbBuf[11] = 0x05;
1792 pbBuf[12] = 0x00;
1793 pbBuf[13] = 0x00;
1794 pbBuf[14] = 0x00;
1795 pbBuf[15] = 0x00;
1796 s->iSourceSink = ATAFN_SS_NULL;
1797 atapiCmdOK(s);
1798 return false;
1799}
1800
1801
1802static bool atapiModeSenseCDStatusSS(AHCIATADevState *s)
1803{
1804 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1805
1806 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1807 Assert(s->cbElementaryTransfer <= 40);
1808 ataH2BE_U16(&pbBuf[0], 38);
1809 pbBuf[2] = 0x70;
1810 pbBuf[3] = 0;
1811 pbBuf[4] = 0;
1812 pbBuf[5] = 0;
1813 pbBuf[6] = 0;
1814 pbBuf[7] = 0;
1815
1816 pbBuf[8] = 0x2a;
1817 pbBuf[9] = 30; /* page length */
1818 pbBuf[10] = 0x08; /* DVD-ROM read support */
1819 pbBuf[11] = 0x00; /* no write support */
1820 /* The following claims we support audio play. This is obviously false,
1821 * but the Linux generic CDROM support makes many features depend on this
1822 * capability. If it's not set, this causes many things to be disabled. */
1823 pbBuf[12] = 0x71; /* multisession support, mode 2 form 1/2 support, audio play */
1824 pbBuf[13] = 0x00; /* no subchannel reads supported */
1825 pbBuf[14] = (1 << 0) | (1 << 3) | (1 << 5); /* lock supported, eject supported, tray type loading mechanism */
1826 if (s->pDrvMount->pfnIsLocked(s->pDrvMount))
1827 pbBuf[14] |= 1 << 1; /* report lock state */
1828 pbBuf[15] = 0; /* no subchannel reads supported, no separate audio volume control, no changer etc. */
1829 ataH2BE_U16(&pbBuf[16], 5632); /* (obsolete) claim 32x speed support */
1830 ataH2BE_U16(&pbBuf[18], 2); /* number of audio volume levels */
1831 ataH2BE_U16(&pbBuf[20], s->cbIOBuffer / _1K); /* buffer size supported in Kbyte */
1832 ataH2BE_U16(&pbBuf[22], 5632); /* (obsolete) current read speed 32x */
1833 pbBuf[24] = 0; /* reserved */
1834 pbBuf[25] = 0; /* reserved for digital audio (see idx 15) */
1835 ataH2BE_U16(&pbBuf[26], 0); /* (obsolete) maximum write speed */
1836 ataH2BE_U16(&pbBuf[28], 0); /* (obsolete) current write speed */
1837 ataH2BE_U16(&pbBuf[30], 0); /* copy management revision supported 0=no CSS */
1838 pbBuf[32] = 0; /* reserved */
1839 pbBuf[33] = 0; /* reserved */
1840 pbBuf[34] = 0; /* reserved */
1841 pbBuf[35] = 1; /* rotation control CAV */
1842 ataH2BE_U16(&pbBuf[36], 0); /* current write speed */
1843 ataH2BE_U16(&pbBuf[38], 0); /* number of write speed performance descriptors */
1844 s->iSourceSink = ATAFN_SS_NULL;
1845 atapiCmdOK(s);
1846 return false;
1847}
1848
1849
1850static bool atapiRequestSenseSS(AHCIATADevState *s)
1851{
1852 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1853
1854 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1855 memset(pbBuf, '\0', s->cbElementaryTransfer);
1856 memcpy(pbBuf, s->abATAPISense, RT_MIN(s->cbElementaryTransfer, sizeof(s->abATAPISense)));
1857 s->iSourceSink = ATAFN_SS_NULL;
1858 atapiCmdOK(s);
1859 return false;
1860}
1861
1862
1863static bool atapiMechanismStatusSS(AHCIATADevState *s)
1864{
1865 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1866
1867 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1868 Assert(s->cbElementaryTransfer <= 8);
1869 ataH2BE_U16(pbBuf, 0);
1870 /* no current LBA */
1871 pbBuf[2] = 0;
1872 pbBuf[3] = 0;
1873 pbBuf[4] = 0;
1874 pbBuf[5] = 1;
1875 ataH2BE_U16(pbBuf + 6, 0);
1876 s->iSourceSink = ATAFN_SS_NULL;
1877 atapiCmdOK(s);
1878 return false;
1879}
1880
1881
1882static bool atapiReadTOCNormalSS(AHCIATADevState *s)
1883{
1884 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer), *q, iStartTrack;
1885 bool fMSF;
1886 uint32_t cbSize;
1887
1888 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1889 fMSF = (s->aATAPICmd[1] >> 1) & 1;
1890 iStartTrack = s->aATAPICmd[6];
1891 if (iStartTrack > 1 && iStartTrack != 0xaa)
1892 {
1893 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
1894 return false;
1895 }
1896 q = pbBuf + 2;
1897 *q++ = 1; /* first session */
1898 *q++ = 1; /* last session */
1899 if (iStartTrack <= 1)
1900 {
1901 *q++ = 0; /* reserved */
1902 *q++ = 0x14; /* ADR, control */
1903 *q++ = 1; /* track number */
1904 *q++ = 0; /* reserved */
1905 if (fMSF)
1906 {
1907 *q++ = 0; /* reserved */
1908 ataLBA2MSF(q, 0);
1909 q += 3;
1910 }
1911 else
1912 {
1913 /* sector 0 */
1914 ataH2BE_U32(q, 0);
1915 q += 4;
1916 }
1917 }
1918 /* lead out track */
1919 *q++ = 0; /* reserved */
1920 *q++ = 0x14; /* ADR, control */
1921 *q++ = 0xaa; /* track number */
1922 *q++ = 0; /* reserved */
1923 if (fMSF)
1924 {
1925 *q++ = 0; /* reserved */
1926 ataLBA2MSF(q, s->cTotalSectors);
1927 q += 3;
1928 }
1929 else
1930 {
1931 ataH2BE_U32(q, s->cTotalSectors);
1932 q += 4;
1933 }
1934 cbSize = q - pbBuf;
1935 ataH2BE_U16(pbBuf, cbSize - 2);
1936 if (cbSize < s->cbTotalTransfer)
1937 s->cbTotalTransfer = cbSize;
1938 s->iSourceSink = ATAFN_SS_NULL;
1939 atapiCmdOK(s);
1940 return false;
1941}
1942
1943
1944static bool atapiReadTOCMultiSS(AHCIATADevState *s)
1945{
1946 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer);
1947 bool fMSF;
1948
1949 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1950 Assert(s->cbElementaryTransfer <= 12);
1951 fMSF = (s->aATAPICmd[1] >> 1) & 1;
1952 /* multi session: only a single session defined */
1953/** @todo double-check this stuff against what a real drive says for a CD-ROM (not a CD-R) with only a single data session. Maybe solve the problem with "cdrdao read-toc" not being able to figure out whether numbers are in BCD or hex. */
1954 memset(pbBuf, 0, 12);
1955 pbBuf[1] = 0x0a;
1956 pbBuf[2] = 0x01;
1957 pbBuf[3] = 0x01;
1958 pbBuf[5] = 0x14; /* ADR, control */
1959 pbBuf[6] = 1; /* first track in last complete session */
1960 if (fMSF)
1961 {
1962 pbBuf[8] = 0; /* reserved */
1963 ataLBA2MSF(&pbBuf[9], 0);
1964 }
1965 else
1966 {
1967 /* sector 0 */
1968 ataH2BE_U32(pbBuf + 8, 0);
1969 }
1970 s->iSourceSink = ATAFN_SS_NULL;
1971 atapiCmdOK(s);
1972 return false;
1973}
1974
1975
1976static bool atapiReadTOCRawSS(AHCIATADevState *s)
1977{
1978 uint8_t *pbBuf = s->CTXALLSUFF(pbIOBuffer), *q, iStartTrack;
1979 bool fMSF;
1980 uint32_t cbSize;
1981
1982 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
1983 fMSF = (s->aATAPICmd[1] >> 1) & 1;
1984 iStartTrack = s->aATAPICmd[6];
1985
1986 q = pbBuf + 2;
1987 *q++ = 1; /* first session */
1988 *q++ = 1; /* last session */
1989
1990 *q++ = 1; /* session number */
1991 *q++ = 0x14; /* data track */
1992 *q++ = 0; /* track number */
1993 *q++ = 0xa0; /* first track in program area */
1994 *q++ = 0; /* min */
1995 *q++ = 0; /* sec */
1996 *q++ = 0; /* frame */
1997 *q++ = 0;
1998 *q++ = 1; /* first track */
1999 *q++ = 0x00; /* disk type CD-DA or CD data */
2000 *q++ = 0;
2001
2002 *q++ = 1; /* session number */
2003 *q++ = 0x14; /* data track */
2004 *q++ = 0; /* track number */
2005 *q++ = 0xa1; /* last track in program area */
2006 *q++ = 0; /* min */
2007 *q++ = 0; /* sec */
2008 *q++ = 0; /* frame */
2009 *q++ = 0;
2010 *q++ = 1; /* last track */
2011 *q++ = 0;
2012 *q++ = 0;
2013
2014 *q++ = 1; /* session number */
2015 *q++ = 0x14; /* data track */
2016 *q++ = 0; /* track number */
2017 *q++ = 0xa2; /* lead-out */
2018 *q++ = 0; /* min */
2019 *q++ = 0; /* sec */
2020 *q++ = 0; /* frame */
2021 if (fMSF)
2022 {
2023 *q++ = 0; /* reserved */
2024 ataLBA2MSF(q, s->cTotalSectors);
2025 q += 3;
2026 }
2027 else
2028 {
2029 ataH2BE_U32(q, s->cTotalSectors);
2030 q += 4;
2031 }
2032
2033 *q++ = 1; /* session number */
2034 *q++ = 0x14; /* ADR, control */
2035 *q++ = 0; /* track number */
2036 *q++ = 1; /* point */
2037 *q++ = 0; /* min */
2038 *q++ = 0; /* sec */
2039 *q++ = 0; /* frame */
2040 if (fMSF)
2041 {
2042 *q++ = 0; /* reserved */
2043 ataLBA2MSF(q, 0);
2044 q += 3;
2045 }
2046 else
2047 {
2048 /* sector 0 */
2049 ataH2BE_U32(q, 0);
2050 q += 4;
2051 }
2052
2053 cbSize = q - pbBuf;
2054 ataH2BE_U16(pbBuf, cbSize - 2);
2055 if (cbSize < s->cbTotalTransfer)
2056 s->cbTotalTransfer = cbSize;
2057 s->iSourceSink = ATAFN_SS_NULL;
2058 atapiCmdOK(s);
2059 return false;
2060}
2061
2062
2063static void atapiParseCmdVirtualATAPI(AHCIATADevState *s)
2064{
2065 const uint8_t *pbPacket;
2066 uint8_t *pbBuf;
2067 uint32_t cbMax;
2068
2069 pbPacket = s->aATAPICmd;
2070 pbBuf = s->CTXALLSUFF(pbIOBuffer);
2071 switch (pbPacket[0])
2072 {
2073 case SCSI_TEST_UNIT_READY:
2074 if (s->cNotifiedMediaChange > 0)
2075 {
2076 if (s->cNotifiedMediaChange-- > 2)
2077 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2078 else
2079 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2080 }
2081 else if (s->pDrvMount->pfnIsMounted(s->pDrvMount))
2082 atapiCmdOK(s);
2083 else
2084 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2085 break;
2086 case SCSI_GET_EVENT_STATUS_NOTIFICATION:
2087 cbMax = ataBE2H_U16(pbPacket + 7);
2088 ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
2089 break;
2090 case SCSI_MODE_SENSE_10:
2091 {
2092 uint8_t uPageControl, uPageCode;
2093 cbMax = ataBE2H_U16(pbPacket + 7);
2094 uPageControl = pbPacket[2] >> 6;
2095 uPageCode = pbPacket[2] & 0x3f;
2096 switch (uPageControl)
2097 {
2098 case SCSI_PAGECONTROL_CURRENT:
2099 switch (uPageCode)
2100 {
2101 case SCSI_MODEPAGE_ERROR_RECOVERY:
2102 ataStartTransfer(s, RT_MIN(cbMax, 16), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY, true);
2103 break;
2104 case SCSI_MODEPAGE_CD_STATUS:
2105 ataStartTransfer(s, RT_MIN(cbMax, 40), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS, true);
2106 break;
2107 default:
2108 goto error_cmd;
2109 }
2110 break;
2111 case SCSI_PAGECONTROL_CHANGEABLE:
2112 goto error_cmd;
2113 case SCSI_PAGECONTROL_DEFAULT:
2114 goto error_cmd;
2115 default:
2116 case SCSI_PAGECONTROL_SAVED:
2117 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
2118 break;
2119 }
2120 }
2121 break;
2122 case SCSI_REQUEST_SENSE:
2123 cbMax = pbPacket[4];
2124 ataStartTransfer(s, RT_MIN(cbMax, 18), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
2125 break;
2126 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
2127 if (s->pDrvMount->pfnIsMounted(s->pDrvMount))
2128 {
2129 if (pbPacket[4] & 1)
2130 s->pDrvMount->pfnLock(s->pDrvMount);
2131 else
2132 s->pDrvMount->pfnUnlock(s->pDrvMount);
2133 atapiCmdOK(s);
2134 }
2135 else
2136 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2137 break;
2138 case SCSI_READ_10:
2139 case SCSI_READ_12:
2140 {
2141 uint32_t cSectors, iATAPILBA;
2142
2143 if (s->cNotifiedMediaChange > 0)
2144 {
2145 s->cNotifiedMediaChange-- ;
2146 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2147 break;
2148 }
2149 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
2150 {
2151 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2152 break;
2153 }
2154 if (pbPacket[0] == SCSI_READ_10)
2155 cSectors = ataBE2H_U16(pbPacket + 7);
2156 else
2157 cSectors = ataBE2H_U32(pbPacket + 6);
2158 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2159 if (cSectors == 0)
2160 {
2161 atapiCmdOK(s);
2162 break;
2163 }
2164 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
2165 {
2166 /* Rate limited logging, one log line per second. For
2167 * guests that insist on reading from places outside the
2168 * valid area this often generates too many release log
2169 * entries otherwise. */
2170 static uint64_t uLastLogTS = 0;
2171 if (RTTimeMilliTS() >= uLastLogTS + 1000)
2172 {
2173 LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
2174 uLastLogTS = RTTimeMilliTS();
2175 }
2176 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
2177 break;
2178 }
2179 atapiReadSectors(s, iATAPILBA, cSectors, 2048);
2180 }
2181 break;
2182 case SCSI_READ_CD:
2183 {
2184 uint32_t cSectors, iATAPILBA;
2185
2186 if (s->cNotifiedMediaChange > 0)
2187 {
2188 s->cNotifiedMediaChange-- ;
2189 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2190 break;
2191 }
2192 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
2193 {
2194 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2195 break;
2196 }
2197 cSectors = (pbPacket[6] << 16) | (pbPacket[7] << 8) | pbPacket[8];
2198 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2199 if (cSectors == 0)
2200 {
2201 atapiCmdOK(s);
2202 break;
2203 }
2204 if ((uint64_t)iATAPILBA + cSectors > s->cTotalSectors)
2205 {
2206 /* Rate limited logging, one log line per second. For
2207 * guests that insist on reading from places outside the
2208 * valid area this often generates too many release log
2209 * entries otherwise. */
2210 static uint64_t uLastLogTS = 0;
2211 if (RTTimeMilliTS() >= uLastLogTS + 1000)
2212 {
2213 LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (READ CD)\n", s->iLUN, (uint64_t)iATAPILBA + cSectors));
2214 uLastLogTS = RTTimeMilliTS();
2215 }
2216 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
2217 break;
2218 }
2219 switch (pbPacket[9] & 0xf8)
2220 {
2221 case 0x00:
2222 /* nothing */
2223 atapiCmdOK(s);
2224 break;
2225 case 0x10:
2226 /* normal read */
2227 atapiReadSectors(s, iATAPILBA, cSectors, 2048);
2228 break;
2229 case 0xf8:
2230 /* read all data */
2231 atapiReadSectors(s, iATAPILBA, cSectors, 2352);
2232 break;
2233 default:
2234 LogRel(("AHCI ATA: LUN#%d: CD-ROM sector format not supported\n", s->iLUN));
2235 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
2236 break;
2237 }
2238 }
2239 break;
2240 case SCSI_SEEK_10:
2241 {
2242 uint32_t iATAPILBA;
2243 if (s->cNotifiedMediaChange > 0)
2244 {
2245 s->cNotifiedMediaChange-- ;
2246 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2247 break;
2248 }
2249 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
2250 {
2251 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2252 break;
2253 }
2254 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2255 if (iATAPILBA > s->cTotalSectors)
2256 {
2257 /* Rate limited logging, one log line per second. For
2258 * guests that insist on seeking to places outside the
2259 * valid area this often generates too many release log
2260 * entries otherwise. */
2261 static uint64_t uLastLogTS = 0;
2262 if (RTTimeMilliTS() >= uLastLogTS + 1000)
2263 {
2264 LogRel(("AHCI ATA: LUN#%d: CD-ROM block number %Ld invalid (SEEK)\n", s->iLUN, (uint64_t)iATAPILBA));
2265 uLastLogTS = RTTimeMilliTS();
2266 }
2267 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
2268 break;
2269 }
2270 atapiCmdOK(s);
2271 ataSetStatus(s, ATA_STAT_SEEK); /* Linux expects this. */
2272 }
2273 break;
2274 case SCSI_START_STOP_UNIT:
2275 {
2276 int rc = VINF_SUCCESS;
2277 switch (pbPacket[4] & 3)
2278 {
2279 case 0: /* 00 - Stop motor */
2280 case 1: /* 01 - Start motor */
2281 break;
2282 case 2: /* 10 - Eject media */
2283 /* This must be done from EMT. */
2284 {
2285 PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
2286 PPDMDEVINS pDevIns = ATADEVSTATE_2_DEVINS(s);
2287
2288 PDMCritSectLeave(&pCtl->lock);
2289 rc = VMR3ReqCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
2290 (PFNRT)s->pDrvMount->pfnUnmount, 3, s->pDrvMount,
2291 false /*=fForce*/, true /*=fEeject*/);
2292 AssertReleaseRC(rc);
2293 {
2294 STAM_PROFILE_START(&pCtl->StatLockWait, a);
2295 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
2296 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
2297 }
2298 }
2299 break;
2300 case 3: /* 11 - Load media */
2301 /** @todo rc = s->pDrvMount->pfnLoadMedia(s->pDrvMount) */
2302 break;
2303 }
2304 if (RT_SUCCESS(rc))
2305 atapiCmdOK(s);
2306 else
2307 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
2308 }
2309 break;
2310 case SCSI_MECHANISM_STATUS:
2311 {
2312 cbMax = ataBE2H_U16(pbPacket + 8);
2313 ataStartTransfer(s, RT_MIN(cbMax, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_MECHANISM_STATUS, true);
2314 }
2315 break;
2316 case SCSI_READ_TOC_PMA_ATIP:
2317 {
2318 uint8_t format;
2319
2320 if (s->cNotifiedMediaChange > 0)
2321 {
2322 s->cNotifiedMediaChange-- ;
2323 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2324 break;
2325 }
2326 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
2327 {
2328 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2329 break;
2330 }
2331 cbMax = ataBE2H_U16(pbPacket + 7);
2332 /* SCSI MMC-3 spec says format is at offset 2 (lower 4 bits),
2333 * but Linux kernel uses offset 9 (topmost 2 bits). Hope that
2334 * the other field is clear... */
2335 format = (pbPacket[2] & 0xf) | (pbPacket[9] >> 6);
2336 switch (format)
2337 {
2338 case 0:
2339 ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_NORMAL, true);
2340 break;
2341 case 1:
2342 ataStartTransfer(s, RT_MIN(cbMax, 12), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_MULTI, true);
2343 break;
2344 case 2:
2345 ataStartTransfer(s, cbMax, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TOC_RAW, true);
2346 break;
2347 default:
2348 error_cmd:
2349 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
2350 break;
2351 }
2352 }
2353 break;
2354 case SCSI_READ_CAPACITY:
2355 if (s->cNotifiedMediaChange > 0)
2356 {
2357 s->cNotifiedMediaChange-- ;
2358 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2359 break;
2360 }
2361 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
2362 {
2363 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2364 break;
2365 }
2366 ataStartTransfer(s, 8, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_CAPACITY, true);
2367 break;
2368 case SCSI_READ_DISC_INFORMATION:
2369 if (s->cNotifiedMediaChange > 0)
2370 {
2371 s->cNotifiedMediaChange-- ;
2372 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2373 break;
2374 }
2375 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
2376 {
2377 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2378 break;
2379 }
2380 cbMax = ataBE2H_U16(pbPacket + 7);
2381 ataStartTransfer(s, RT_MIN(cbMax, 34), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_DISC_INFORMATION, true);
2382 break;
2383 case SCSI_READ_TRACK_INFORMATION:
2384 if (s->cNotifiedMediaChange > 0)
2385 {
2386 s->cNotifiedMediaChange-- ;
2387 atapiCmdErrorSimple(s, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
2388 break;
2389 }
2390 else if (!s->pDrvMount->pfnIsMounted(s->pDrvMount))
2391 {
2392 atapiCmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
2393 break;
2394 }
2395 cbMax = ataBE2H_U16(pbPacket + 7);
2396 ataStartTransfer(s, RT_MIN(cbMax, 36), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION, true);
2397 break;
2398 case SCSI_GET_CONFIGURATION:
2399 /* No media change stuff here, it can confuse Linux guests. */
2400 cbMax = ataBE2H_U16(pbPacket + 7);
2401 ataStartTransfer(s, RT_MIN(cbMax, 32), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_CONFIGURATION, true);
2402 break;
2403 case SCSI_INQUIRY:
2404 cbMax = ataBE2H_U16(pbPacket + 3);
2405 ataStartTransfer(s, RT_MIN(cbMax, 36), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_INQUIRY, true);
2406 break;
2407 default:
2408 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
2409 break;
2410 }
2411}
2412
2413
2414/*
2415 * Parse ATAPI commands, passing them directly to the CD/DVD drive.
2416 */
2417static void atapiParseCmdPassthrough(AHCIATADevState *s)
2418{
2419 const uint8_t *pbPacket;
2420 uint8_t *pbBuf;
2421 uint32_t cSectors, iATAPILBA;
2422 uint32_t cbTransfer = 0;
2423 PDMBLOCKTXDIR uTxDir = PDMBLOCKTXDIR_NONE;
2424
2425 pbPacket = s->aATAPICmd;
2426 pbBuf = s->CTXALLSUFF(pbIOBuffer);
2427 switch (pbPacket[0])
2428 {
2429 case SCSI_BLANK:
2430 goto sendcmd;
2431 case SCSI_CLOSE_TRACK_SESSION:
2432 goto sendcmd;
2433 case SCSI_ERASE_10:
2434 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2435 cbTransfer = ataBE2H_U16(pbPacket + 7);
2436 Log2(("ATAPI PT: lba %d\n", iATAPILBA));
2437 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2438 goto sendcmd;
2439 case SCSI_FORMAT_UNIT:
2440 cbTransfer = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */
2441 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2442 goto sendcmd;
2443 case SCSI_GET_CONFIGURATION:
2444 cbTransfer = ataBE2H_U16(pbPacket + 7);
2445 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2446 goto sendcmd;
2447 case SCSI_GET_EVENT_STATUS_NOTIFICATION:
2448 cbTransfer = ataBE2H_U16(pbPacket + 7);
2449 if (ASMAtomicReadU32(&s->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
2450 {
2451 ataStartTransfer(s, RT_MIN(cbTransfer, 8), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION, true);
2452 break;
2453 }
2454 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2455 goto sendcmd;
2456 case SCSI_GET_PERFORMANCE:
2457 cbTransfer = s->uATARegLCyl | (s->uATARegHCyl << 8); /* use ATAPI transfer length */
2458 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2459 goto sendcmd;
2460 case SCSI_INQUIRY:
2461 cbTransfer = ataBE2H_U16(pbPacket + 3);
2462 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2463 goto sendcmd;
2464 case SCSI_LOAD_UNLOAD_MEDIUM:
2465 goto sendcmd;
2466 case SCSI_MECHANISM_STATUS:
2467 cbTransfer = ataBE2H_U16(pbPacket + 8);
2468 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2469 goto sendcmd;
2470 case SCSI_MODE_SELECT_10:
2471 cbTransfer = ataBE2H_U16(pbPacket + 7);
2472 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2473 goto sendcmd;
2474 case SCSI_MODE_SENSE_10:
2475 cbTransfer = ataBE2H_U16(pbPacket + 7);
2476 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2477 goto sendcmd;
2478 case SCSI_PAUSE_RESUME:
2479 goto sendcmd;
2480 case SCSI_PLAY_AUDIO_10:
2481 goto sendcmd;
2482 case SCSI_PLAY_AUDIO_12:
2483 goto sendcmd;
2484 case SCSI_PLAY_AUDIO_MSF:
2485 goto sendcmd;
2486 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
2487 /** @todo do not forget to unlock when a VM is shut down */
2488 goto sendcmd;
2489 case SCSI_READ_10:
2490 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2491 cSectors = ataBE2H_U16(pbPacket + 7);
2492 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
2493 s->cbATAPISector = 2048; /**< @todo this size is not always correct */
2494 cbTransfer = cSectors * s->cbATAPISector;
2495 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2496 goto sendcmd;
2497 case SCSI_READ_12:
2498 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2499 cSectors = ataBE2H_U32(pbPacket + 6);
2500 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
2501 s->cbATAPISector = 2048; /**< @todo this size is not always correct */
2502 cbTransfer = cSectors * s->cbATAPISector;
2503 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2504 goto sendcmd;
2505 case SCSI_READ_BUFFER:
2506 cbTransfer = ataBE2H_U24(pbPacket + 6);
2507 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2508 goto sendcmd;
2509 case SCSI_READ_BUFFER_CAPACITY:
2510 cbTransfer = ataBE2H_U16(pbPacket + 7);
2511 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2512 goto sendcmd;
2513 case SCSI_READ_CAPACITY:
2514 cbTransfer = 8;
2515 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2516 goto sendcmd;
2517 case SCSI_READ_CD:
2518 s->cbATAPISector = 2048; /**< @todo this size is not always correct */
2519 cbTransfer = ataBE2H_U24(pbPacket + 6) / s->cbATAPISector * s->cbATAPISector;
2520 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2521 goto sendcmd;
2522 case SCSI_READ_CD_MSF:
2523 cSectors = ataMSF2LBA(pbPacket + 6) - ataMSF2LBA(pbPacket + 3);
2524 if (cSectors > 32)
2525 cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */
2526 s->cbATAPISector = 2048; /**< @todo this size is not always correct */
2527 cbTransfer = cSectors * s->cbATAPISector;
2528 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2529 goto sendcmd;
2530 case SCSI_READ_DISC_INFORMATION:
2531 cbTransfer = ataBE2H_U16(pbPacket + 7);
2532 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2533 goto sendcmd;
2534 case SCSI_READ_DVD_STRUCTURE:
2535 cbTransfer = ataBE2H_U16(pbPacket + 8);
2536 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2537 goto sendcmd;
2538 case SCSI_READ_FORMAT_CAPACITIES:
2539 cbTransfer = ataBE2H_U16(pbPacket + 7);
2540 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2541 goto sendcmd;
2542 case SCSI_READ_SUBCHANNEL:
2543 cbTransfer = ataBE2H_U16(pbPacket + 7);
2544 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2545 goto sendcmd;
2546 case SCSI_READ_TOC_PMA_ATIP:
2547 cbTransfer = ataBE2H_U16(pbPacket + 7);
2548 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2549 goto sendcmd;
2550 case SCSI_READ_TRACK_INFORMATION:
2551 cbTransfer = ataBE2H_U16(pbPacket + 7);
2552 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2553 goto sendcmd;
2554 case SCSI_REPAIR_TRACK:
2555 goto sendcmd;
2556 case SCSI_REPORT_KEY:
2557 cbTransfer = ataBE2H_U16(pbPacket + 8);
2558 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2559 goto sendcmd;
2560 case SCSI_REQUEST_SENSE:
2561 cbTransfer = pbPacket[4];
2562 if ((s->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
2563 {
2564 ataStartTransfer(s, RT_MIN(cbTransfer, 18), PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_ATAPI_CMD, ATAFN_SS_ATAPI_REQUEST_SENSE, true);
2565 break;
2566 }
2567 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2568 goto sendcmd;
2569 case SCSI_RESERVE_TRACK:
2570 goto sendcmd;
2571 case SCSI_SCAN:
2572 goto sendcmd;
2573 case SCSI_SEEK_10:
2574 goto sendcmd;
2575 case SCSI_SEND_CUE_SHEET:
2576 cbTransfer = ataBE2H_U24(pbPacket + 6);
2577 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2578 goto sendcmd;
2579 case SCSI_SEND_DVD_STRUCTURE:
2580 cbTransfer = ataBE2H_U16(pbPacket + 8);
2581 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2582 goto sendcmd;
2583 case SCSI_SEND_EVENT:
2584 cbTransfer = ataBE2H_U16(pbPacket + 8);
2585 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2586 goto sendcmd;
2587 case SCSI_SEND_KEY:
2588 cbTransfer = ataBE2H_U16(pbPacket + 8);
2589 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2590 goto sendcmd;
2591 case SCSI_SEND_OPC_INFORMATION:
2592 cbTransfer = ataBE2H_U16(pbPacket + 7);
2593 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2594 goto sendcmd;
2595 case SCSI_SET_CD_SPEED:
2596 goto sendcmd;
2597 case SCSI_SET_READ_AHEAD:
2598 goto sendcmd;
2599 case SCSI_SET_STREAMING:
2600 cbTransfer = ataBE2H_U16(pbPacket + 9);
2601 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2602 goto sendcmd;
2603 case SCSI_START_STOP_UNIT:
2604 goto sendcmd;
2605 case SCSI_STOP_PLAY_SCAN:
2606 goto sendcmd;
2607 case SCSI_SYNCHRONIZE_CACHE:
2608 goto sendcmd;
2609 case SCSI_TEST_UNIT_READY:
2610 goto sendcmd;
2611 case SCSI_VERIFY_10:
2612 goto sendcmd;
2613 case SCSI_WRITE_10:
2614 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2615 cSectors = ataBE2H_U16(pbPacket + 7);
2616 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
2617#if 0
2618 /* The sector size is determined by the async I/O thread. */
2619 s->cbATAPISector = 0;
2620 /* Preliminary, will be corrected once the sector size is known. */
2621 cbTransfer = cSectors;
2622#else
2623 s->cbATAPISector = 2048; /**< @todo this size is not always correct */
2624 cbTransfer = cSectors * s->cbATAPISector;
2625#endif
2626 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2627 goto sendcmd;
2628 case SCSI_WRITE_12:
2629 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2630 cSectors = ataBE2H_U32(pbPacket + 6);
2631 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
2632#if 0
2633 /* The sector size is determined by the async I/O thread. */
2634 s->cbATAPISector = 0;
2635 /* Preliminary, will be corrected once the sector size is known. */
2636 cbTransfer = cSectors;
2637#else
2638 s->cbATAPISector = 2048; /**< @todo this size is not always correct */
2639 cbTransfer = cSectors * s->cbATAPISector;
2640#endif
2641 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2642 goto sendcmd;
2643 case SCSI_WRITE_AND_VERIFY_10:
2644 iATAPILBA = ataBE2H_U32(pbPacket + 2);
2645 cSectors = ataBE2H_U16(pbPacket + 7);
2646 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
2647 /* The sector size is determined by the async I/O thread. */
2648 s->cbATAPISector = 0;
2649 /* Preliminary, will be corrected once the sector size is known. */
2650 cbTransfer = cSectors;
2651 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2652 goto sendcmd;
2653 case SCSI_WRITE_BUFFER:
2654 switch (pbPacket[1] & 0x1f)
2655 {
2656 case 0x04: /* download microcode */
2657 case 0x05: /* download microcode and save */
2658 case 0x06: /* download microcode with offsets */
2659 case 0x07: /* download microcode with offsets and save */
2660 case 0x0e: /* download microcode with offsets and defer activation */
2661 case 0x0f: /* activate deferred microcode */
2662 LogRel(("AHCI ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", s->iLUN));
2663 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
2664 break;
2665 default:
2666 cbTransfer = ataBE2H_U16(pbPacket + 6);
2667 uTxDir = PDMBLOCKTXDIR_TO_DEVICE;
2668 goto sendcmd;
2669 }
2670 break;
2671 case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */
2672 cbTransfer = ataBE2H_U32(pbPacket + 6);
2673 uTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
2674 goto sendcmd;
2675 case SCSI_REZERO_UNIT:
2676 /* Obsolete command used by cdrecord. What else would one expect?
2677 * This command is not sent to the drive, it is handled internally,
2678 * as the Linux kernel doesn't like it (message "scsi: unknown
2679 * opcode 0x01" in syslog) and replies with a sense code of 0,
2680 * which sends cdrecord to an endless loop. */
2681 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
2682 break;
2683 default:
2684 LogRel(("AHCI ATA: LUN#%d: passthrough unimplemented for command %#x\n", s->iLUN, pbPacket[0]));
2685 atapiCmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
2686 break;
2687 sendcmd:
2688 /* Send a command to the drive, passing data in/out as required. */
2689 Log2(("ATAPI PT: max size %d\n", cbTransfer));
2690 Assert(cbTransfer <= s->cbIOBuffer);
2691 if (cbTransfer == 0)
2692 uTxDir = PDMBLOCKTXDIR_NONE;
2693 ataStartTransfer(s, cbTransfer, uTxDir, ATAFN_BT_ATAPI_PASSTHROUGH_CMD, ATAFN_SS_ATAPI_PASSTHROUGH, true);
2694 }
2695}
2696
2697
2698static void atapiParseCmd(AHCIATADevState *s)
2699{
2700 const uint8_t *pbPacket;
2701
2702 pbPacket = s->aATAPICmd;
2703#ifdef DEBUG
2704 Log(("%s: LUN#%d DMA=%d CMD=%#04x \"%s\"\n", __FUNCTION__, s->iLUN, s->fDMA, pbPacket[0], SCSICmdText(pbPacket[0])));
2705#else /* !DEBUG */
2706 Log(("%s: LUN#%d DMA=%d CMD=%#04x\n", __FUNCTION__, s->iLUN, s->fDMA, pbPacket[0]));
2707#endif /* !DEBUG */
2708 Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, s->uATARegLCyl | (s->uATARegHCyl << 8), ATAPI_PACKET_SIZE, pbPacket));
2709
2710 if (s->fATAPIPassthrough)
2711 atapiParseCmdPassthrough(s);
2712 else
2713 atapiParseCmdVirtualATAPI(s);
2714}
2715
2716
2717static bool ataPacketSS(AHCIATADevState *s)
2718{
2719 s->fDMA = !!(s->uATARegFeature & 1);
2720 memcpy(s->aATAPICmd, s->CTXALLSUFF(pbIOBuffer), ATAPI_PACKET_SIZE);
2721 s->uTxDir = PDMBLOCKTXDIR_NONE;
2722 s->cbTotalTransfer = 0;
2723 s->cbElementaryTransfer = 0;
2724 atapiParseCmd(s);
2725 return false;
2726}
2727
2728#if 0
2729
2730/**
2731 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium removed" event
2732 * from now on, regardless if there was a medium inserted or not.
2733 */
2734static void ataMediumRemoved(AHCIATADevState *s)
2735{
2736 ASMAtomicWriteU32(&s->MediaEventStatus, ATA_EVENT_STATUS_MEDIA_REMOVED);
2737}
2738
2739
2740/**
2741 * SCSI_GET_EVENT_STATUS_NOTIFICATION should return "medium inserted". If
2742 * there was already a medium inserted, don't forget to send the "medium
2743 * removed" event first.
2744 */
2745static void ataMediumInserted(AHCIATADevState *s)
2746{
2747 uint32_t OldStatus, NewStatus;
2748 do
2749 {
2750 OldStatus = ASMAtomicReadU32(&s->MediaEventStatus);
2751 switch (OldStatus)
2752 {
2753 case ATA_EVENT_STATUS_MEDIA_CHANGED:
2754 case ATA_EVENT_STATUS_MEDIA_REMOVED:
2755 /* no change, we will send "medium removed" + "medium inserted" */
2756 NewStatus = ATA_EVENT_STATUS_MEDIA_CHANGED;
2757 break;
2758 default:
2759 NewStatus = ATA_EVENT_STATUS_MEDIA_NEW;
2760 break;
2761 }
2762 } while (!ASMAtomicCmpXchgU32(&s->MediaEventStatus, NewStatus, OldStatus));
2763}
2764
2765
2766/**
2767 * Called when a media is mounted.
2768 *
2769 * @param pInterface Pointer to the interface structure containing the called function pointer.
2770 */
2771static DECLCALLBACK(void) ataMountNotify(PPDMIMOUNTNOTIFY pInterface)
2772{
2773 AHCIATADevState *pIf = PDMIMOUNTNOTIFY_2_ATASTATE(pInterface);
2774 Log(("%s: changing LUN#%d\n", __FUNCTION__, pIf->iLUN));
2775
2776 /* Ignore the call if we're called while being attached. */
2777 if (!pIf->pDrvBlock)
2778 return;
2779
2780 LogRel(("AHCI ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors));
2781
2782 if (pIf->fATAPI)
2783 pIf->cTotalSectors = pIf->pDrvBlock->pfnGetSize(pIf->pDrvBlock) / 2048;
2784 else
2785 pIf->cTotalSectors = pIf->pDrvBlock->pfnGetSize(pIf->pDrvBlock) / 512;
2786
2787 /* Report media changed in TEST UNIT and other (probably incorrect) places. */
2788 if (pIf->cNotifiedMediaChange < 2)
2789 pIf->cNotifiedMediaChange = 2;
2790 ataMediumInserted(pIf);
2791}
2792
2793/**
2794 * Called when a media is unmounted
2795 * @param pInterface Pointer to the interface structure containing the called function pointer.
2796 */
2797static DECLCALLBACK(void) ataUnmountNotify(PPDMIMOUNTNOTIFY pInterface)
2798{
2799 AHCIATADevState *pIf = PDMIMOUNTNOTIFY_2_ATASTATE(pInterface);
2800 Log(("%s:\n", __FUNCTION__));
2801 pIf->cTotalSectors = 0;
2802
2803 /*
2804 * Whatever I do, XP will not use the GET MEDIA STATUS nor the EVENT stuff.
2805 * However, it will respond to TEST UNIT with a 0x6 0x28 (media changed) sense code.
2806 * So, we'll give it 4 TEST UNIT command to catch up, two which the media is not
2807 * present and 2 in which it is changed.
2808 */
2809 pIf->cNotifiedMediaChange = 4;
2810 ataMediumRemoved(pIf);
2811}
2812#endif
2813
2814static void ataPacketBT(AHCIATADevState *s)
2815{
2816 s->cbElementaryTransfer = s->cbTotalTransfer;
2817 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_CD;
2818 Log2(("%s: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
2819 ataSetStatusValue(s, ATA_STAT_READY);
2820}
2821
2822
2823static void ataResetDevice(AHCIATADevState *s)
2824{
2825 s->cMultSectors = ATA_MAX_MULT_SECTORS;
2826 s->cNotifiedMediaChange = 0;
2827 ASMAtomicWriteU32(&s->MediaEventStatus, ATA_EVENT_STATUS_UNCHANGED);
2828 ataUnsetIRQ(s);
2829
2830 s->uATARegSelect = 0x20;
2831 ataSetStatusValue(s, ATA_STAT_READY);
2832 ataSetSignature(s);
2833 s->cbTotalTransfer = 0;
2834 s->cbElementaryTransfer = 0;
2835 s->iIOBufferPIODataStart = 0;
2836 s->iIOBufferPIODataEnd = 0;
2837 s->iBeginTransfer = ATAFN_BT_NULL;
2838 s->iSourceSink = ATAFN_SS_NULL;
2839 s->fATAPITransfer = false;
2840 s->uATATransferMode = ATA_MODE_UDMA | 2; /* AHCI supports only up to UDMA2 */
2841
2842 s->uATARegFeature = 0;
2843}
2844
2845
2846static bool ataExecuteDeviceDiagnosticSS(AHCIATADevState *s)
2847{
2848 ataSetSignature(s);
2849 if (s->fATAPI)
2850 ataSetStatusValue(s, 0); /* NOTE: READY is _not_ set */
2851 else
2852 ataSetStatusValue(s, ATA_STAT_READY);
2853 s->uATARegError = 0x01;
2854 return false;
2855}
2856
2857
2858static void ataParseCmd(AHCIATADevState *s, uint8_t cmd)
2859{
2860#ifdef DEBUG
2861 Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, s->iLUN, cmd, ATACmdText(cmd)));
2862#else /* !DEBUG */
2863 Log(("%s: LUN#%d CMD=%#04x\n", __FUNCTION__, s->iLUN, cmd));
2864#endif /* !DEBUG */
2865 s->fLBA48 = false;
2866 s->fDMA = false;
2867 if (cmd == ATA_IDLE_IMMEDIATE)
2868 {
2869 /* Detect Linux timeout recovery, first tries IDLE IMMEDIATE (which
2870 * would overwrite the failing command unfortunately), then RESET. */
2871 int32_t uCmdWait = -1;
2872 uint64_t uNow = RTTimeNanoTS();
2873 if (s->u64CmdTS)
2874 uCmdWait = (uNow - s->u64CmdTS) / 1000;
2875 LogRel(("AHCI ATA: LUN#%d: IDLE IMMEDIATE, CmdIf=%#04x (%d usec ago)\n",
2876 s->iLUN, s->uATARegCommand, uCmdWait));
2877 }
2878 s->uATARegCommand = cmd;
2879 switch (cmd)
2880 {
2881 case ATA_IDENTIFY_DEVICE:
2882 if (s->pDrvBlock && !s->fATAPI)
2883 ataStartTransfer(s, 512, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_NULL, ATAFN_SS_IDENTIFY, false);
2884 else
2885 {
2886 if (s->fATAPI)
2887 ataSetSignature(s);
2888 ataCmdError(s, ABRT_ERR);
2889 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2890 }
2891 break;
2892 case ATA_INITIALIZE_DEVICE_PARAMETERS:
2893 case ATA_RECALIBRATE:
2894 ataCmdOK(s, ATA_STAT_SEEK);
2895 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2896 break;
2897 case ATA_SET_MULTIPLE_MODE:
2898 if ( s->uATARegNSector != 0
2899 && ( s->uATARegNSector > ATA_MAX_MULT_SECTORS
2900 || (s->uATARegNSector & (s->uATARegNSector - 1)) != 0))
2901 {
2902 ataCmdError(s, ABRT_ERR);
2903 }
2904 else
2905 {
2906 Log2(("%s: set multi sector count to %d\n", __FUNCTION__, s->uATARegNSector));
2907 s->cMultSectors = s->uATARegNSector;
2908 ataCmdOK(s, 0);
2909 }
2910 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2911 break;
2912 case ATA_READ_VERIFY_SECTORS_EXT:
2913 s->fLBA48 = true;
2914 case ATA_READ_VERIFY_SECTORS:
2915 case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES:
2916 /* do sector number check ? */
2917 ataCmdOK(s, 0);
2918 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2919 break;
2920 case ATA_READ_SECTORS_EXT:
2921 s->fLBA48 = true;
2922 case ATA_READ_SECTORS:
2923 case ATA_READ_SECTORS_WITHOUT_RETRIES:
2924 if (!s->pDrvBlock)
2925 goto abort_cmd;
2926 s->cSectorsPerIRQ = 1;
2927 ataStartTransfer(s, ataGetNSectors(s) * 512, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
2928 break;
2929 case ATA_WRITE_SECTORS_EXT:
2930 s->fLBA48 = true;
2931 case ATA_WRITE_SECTORS:
2932 case ATA_WRITE_SECTORS_WITHOUT_RETRIES:
2933 s->cSectorsPerIRQ = 1;
2934 ataStartTransfer(s, ataGetNSectors(s) * 512, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
2935 break;
2936 case ATA_READ_MULTIPLE_EXT:
2937 s->fLBA48 = true;
2938 case ATA_READ_MULTIPLE:
2939 if (!s->cMultSectors)
2940 goto abort_cmd;
2941 s->cSectorsPerIRQ = s->cMultSectors;
2942 ataStartTransfer(s, ataGetNSectors(s) * 512, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
2943 break;
2944 case ATA_WRITE_MULTIPLE_EXT:
2945 s->fLBA48 = true;
2946 case ATA_WRITE_MULTIPLE:
2947 if (!s->cMultSectors)
2948 goto abort_cmd;
2949 s->cSectorsPerIRQ = s->cMultSectors;
2950 ataStartTransfer(s, ataGetNSectors(s) * 512, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
2951 break;
2952 case ATA_READ_DMA_EXT:
2953 s->fLBA48 = true;
2954 case ATA_READ_DMA:
2955 case ATA_READ_DMA_WITHOUT_RETRIES:
2956 if (!s->pDrvBlock)
2957 goto abort_cmd;
2958 s->cSectorsPerIRQ = ATA_MAX_MULT_SECTORS;
2959 s->fDMA = true;
2960 ataStartTransfer(s, ataGetNSectors(s) * 512, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_READ_SECTORS, false);
2961 break;
2962 case ATA_WRITE_DMA_EXT:
2963 s->fLBA48 = true;
2964 case ATA_WRITE_DMA:
2965 case ATA_WRITE_DMA_WITHOUT_RETRIES:
2966 if (!s->pDrvBlock)
2967 goto abort_cmd;
2968 s->cSectorsPerIRQ = ATA_MAX_MULT_SECTORS;
2969 s->fDMA = true;
2970 ataStartTransfer(s, ataGetNSectors(s) * 512, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_READ_WRITE_SECTORS, ATAFN_SS_WRITE_SECTORS, false);
2971 break;
2972 case ATA_READ_NATIVE_MAX_ADDRESS_EXT:
2973 s->fLBA48 = true;
2974 ataSetSector(s, s->cTotalSectors - 1);
2975 ataCmdOK(s, 0);
2976 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2977 break;
2978 case ATA_READ_NATIVE_MAX_ADDRESS:
2979 ataSetSector(s, RT_MIN(s->cTotalSectors, 1 << 28) - 1);
2980 ataCmdOK(s, 0);
2981 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2982 break;
2983 case ATA_CHECK_POWER_MODE:
2984 s->uATARegNSector = 0xff; /* drive active or idle */
2985 ataCmdOK(s, 0);
2986 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2987 break;
2988 case ATA_SET_FEATURES:
2989 Log2(("%s: feature=%#x\n", __FUNCTION__, s->uATARegFeature));
2990 if (!s->pDrvBlock)
2991 goto abort_cmd;
2992 switch (s->uATARegFeature)
2993 {
2994 case 0x02: /* write cache enable */
2995 Log2(("%s: write cache enable\n", __FUNCTION__));
2996 ataCmdOK(s, ATA_STAT_SEEK);
2997 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
2998 break;
2999 case 0xaa: /* read look-ahead enable */
3000 Log2(("%s: read look-ahead enable\n", __FUNCTION__));
3001 ataCmdOK(s, ATA_STAT_SEEK);
3002 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3003 break;
3004 case 0x55: /* read look-ahead disable */
3005 Log2(("%s: read look-ahead disable\n", __FUNCTION__));
3006 ataCmdOK(s, ATA_STAT_SEEK);
3007 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3008 break;
3009 case 0xcc: /* reverting to power-on defaults enable */
3010 Log2(("%s: revert to power-on defaults enable\n", __FUNCTION__));
3011 ataCmdOK(s, ATA_STAT_SEEK);
3012 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3013 break;
3014 case 0x66: /* reverting to power-on defaults disable */
3015 Log2(("%s: revert to power-on defaults disable\n", __FUNCTION__));
3016 ataCmdOK(s, ATA_STAT_SEEK);
3017 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3018 break;
3019 case 0x82: /* write cache disable */
3020 Log2(("%s: write cache disable\n", __FUNCTION__));
3021 /* As per the ATA/ATAPI-6 specs, a write cache disable
3022 * command MUST flush the write buffers to disc. */
3023 ataStartTransfer(s, 0, PDMBLOCKTXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_FLUSH, false);
3024 break;
3025 case 0x03: { /* set transfer mode */
3026 Log2(("%s: transfer mode %#04x\n", __FUNCTION__, s->uATARegNSector));
3027 switch (s->uATARegNSector & 0xf8)
3028 {
3029 case 0x00: /* PIO default */
3030 case 0x08: /* PIO mode */
3031 break;
3032 case ATA_MODE_MDMA: /* MDMA mode */
3033 s->uATATransferMode = (s->uATARegNSector & 0xf8) | RT_MIN(s->uATARegNSector & 0x07, ATA_MDMA_MODE_MAX);
3034 break;
3035 case ATA_MODE_UDMA: /* UDMA mode */
3036 s->uATATransferMode = (s->uATARegNSector & 0xf8) | RT_MIN(s->uATARegNSector & 0x07, ATA_UDMA_MODE_MAX);
3037 break;
3038 default:
3039 goto abort_cmd;
3040 }
3041 ataCmdOK(s, ATA_STAT_SEEK);
3042 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3043 break;
3044 }
3045 default:
3046 goto abort_cmd;
3047 }
3048 /*
3049 * OS/2 workarond:
3050 * The OS/2 IDE driver from MCP2 appears to rely on the feature register being
3051 * reset here. According to the specification, this is a driver bug as the register
3052 * contents are undefined after the call. This means we can just as well reset it.
3053 */
3054 s->uATARegFeature = 0;
3055 break;
3056 case ATA_FLUSH_CACHE_EXT:
3057 case ATA_FLUSH_CACHE:
3058 if (!s->pDrvBlock || s->fATAPI)
3059 goto abort_cmd;
3060 ataStartTransfer(s, 0, PDMBLOCKTXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_FLUSH, false);
3061 break;
3062 case ATA_STANDBY_IMMEDIATE:
3063 ataCmdOK(s, 0);
3064 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3065 break;
3066 case ATA_IDLE_IMMEDIATE:
3067 LogRel(("AHCI ATA: LUN#%d: aborting current command\n", s->iLUN));
3068 ataAbortCurrentCommand(s, false);
3069 break;
3070 /* ATAPI commands */
3071 case ATA_IDENTIFY_PACKET_DEVICE:
3072 if (s->fATAPI)
3073 ataStartTransfer(s, 512, PDMBLOCKTXDIR_FROM_DEVICE, ATAFN_BT_NULL, ATAFN_SS_ATAPI_IDENTIFY, false);
3074 else
3075 {
3076 ataCmdError(s, ABRT_ERR);
3077 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3078 }
3079 break;
3080 case ATA_EXECUTE_DEVICE_DIAGNOSTIC:
3081 ataStartTransfer(s, 0, PDMBLOCKTXDIR_NONE, ATAFN_BT_NULL, ATAFN_SS_EXECUTE_DEVICE_DIAGNOSTIC, false);
3082 break;
3083 case ATA_DEVICE_RESET:
3084 if (!s->fATAPI)
3085 goto abort_cmd;
3086 LogRel(("AHCI ATA: LUN#%d: performing device RESET\n", s->iLUN));
3087 ataAbortCurrentCommand(s, true);
3088 break;
3089 case ATA_PACKET:
3090 if (!s->fATAPI)
3091 goto abort_cmd;
3092 /* overlapping commands not supported */
3093 if (s->uATARegFeature & 0x02)
3094 goto abort_cmd;
3095 ataStartTransfer(s, ATAPI_PACKET_SIZE, PDMBLOCKTXDIR_TO_DEVICE, ATAFN_BT_PACKET, ATAFN_SS_PACKET, false);
3096 break;
3097 default:
3098 abort_cmd:
3099 ataCmdError(s, ABRT_ERR);
3100 ataSetIRQ(s); /* Shortcut, do not use AIO thread. */
3101 break;
3102 }
3103}
3104
3105
3106/**
3107 * Waits for a particular async I/O thread to complete whatever it
3108 * is doing at the moment.
3109 *
3110 * @returns true on success.
3111 * @returns false when the thread is still processing.
3112 * @param pThis Pointer to the controller data.
3113 * @param cMillies How long to wait (total).
3114 */
3115static bool ataWaitForAsyncIOIsIdle(PAHCIATACONTROLLER pCtl, RTMSINTERVAL cMillies)
3116{
3117 uint64_t u64Start;
3118 bool fRc;
3119
3120 /* Hope for the simple way out... */
3121 if (ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
3122 return true;
3123
3124 /*
3125 * Have to wait. Do the setup while owning the mutex to avoid races.
3126 */
3127 RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
3128
3129 RTThreadUserReset(pCtl->AsyncIOThread);
3130 ASMAtomicWriteBool(&pCtl->fSignalIdle, true);
3131
3132 RTSemMutexRelease(pCtl->AsyncIORequestMutex);
3133
3134 u64Start = RTTimeMilliTS();
3135 for (;;)
3136 {
3137 fRc = ataAsyncIOIsIdle(pCtl, false /*fStrict*/);
3138 if (fRc)
3139 break;
3140
3141 if (RTTimeMilliTS() - u64Start >= cMillies)
3142 break;
3143
3144 int rc = RTThreadUserWait(pCtl->AsyncIOThread, 100 /*ms*/);
3145 AssertMsg( ( RT_SUCCESS(rc)
3146 && ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
3147 || rc == VERR_TIMEOUT,
3148 ("rc=%Rrc irq=%u\n", rc, pCtl->irq));
3149 }
3150
3151 ASMAtomicWriteBool(&pCtl->fSignalIdle, false);
3152 return fRc;
3153}
3154
3155#endif /* IN_RING3 */
3156
3157static int ataIOPortWriteU8(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t val)
3158{
3159 Log2(("%s: write addr=%#x val=%#04x\n", __FUNCTION__, addr, val));
3160 addr &= 7;
3161 switch (addr)
3162 {
3163 case 0:
3164 break;
3165 case 1: /* feature register */
3166 /* NOTE: data is written to the two drives */
3167 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3168 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3169 pCtl->aIfs[0].uATARegFeatureHOB = pCtl->aIfs[0].uATARegFeature;
3170 pCtl->aIfs[1].uATARegFeatureHOB = pCtl->aIfs[1].uATARegFeature;
3171 pCtl->aIfs[0].uATARegFeature = val;
3172 pCtl->aIfs[1].uATARegFeature = val;
3173 break;
3174 case 2: /* sector count */
3175 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3176 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3177 pCtl->aIfs[0].uATARegNSectorHOB = pCtl->aIfs[0].uATARegNSector;
3178 pCtl->aIfs[1].uATARegNSectorHOB = pCtl->aIfs[1].uATARegNSector;
3179 pCtl->aIfs[0].uATARegNSector = val;
3180 pCtl->aIfs[1].uATARegNSector = val;
3181 break;
3182 case 3: /* sector number */
3183 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3184 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3185 pCtl->aIfs[0].uATARegSectorHOB = pCtl->aIfs[0].uATARegSector;
3186 pCtl->aIfs[1].uATARegSectorHOB = pCtl->aIfs[1].uATARegSector;
3187 pCtl->aIfs[0].uATARegSector = val;
3188 pCtl->aIfs[1].uATARegSector = val;
3189 break;
3190 case 4: /* cylinder low */
3191 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3192 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3193 pCtl->aIfs[0].uATARegLCylHOB = pCtl->aIfs[0].uATARegLCyl;
3194 pCtl->aIfs[1].uATARegLCylHOB = pCtl->aIfs[1].uATARegLCyl;
3195 pCtl->aIfs[0].uATARegLCyl = val;
3196 pCtl->aIfs[1].uATARegLCyl = val;
3197 break;
3198 case 5: /* cylinder high */
3199 pCtl->aIfs[0].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3200 pCtl->aIfs[1].uATARegDevCtl &= ~ATA_DEVCTL_HOB;
3201 pCtl->aIfs[0].uATARegHCylHOB = pCtl->aIfs[0].uATARegHCyl;
3202 pCtl->aIfs[1].uATARegHCylHOB = pCtl->aIfs[1].uATARegHCyl;
3203 pCtl->aIfs[0].uATARegHCyl = val;
3204 pCtl->aIfs[1].uATARegHCyl = val;
3205 break;
3206 case 6: /* drive/head */
3207 pCtl->aIfs[0].uATARegSelect = (val & ~0x10) | 0xa0;
3208 pCtl->aIfs[1].uATARegSelect = (val | 0x10) | 0xa0;
3209 if (((val >> 4) & 1) != pCtl->iSelectedIf)
3210 {
3211 PPDMDEVINS pDevIns = CONTROLLER_2_DEVINS(pCtl);
3212
3213 /* select another drive */
3214 pCtl->iSelectedIf = (val >> 4) & 1;
3215 /* The IRQ line is multiplexed between the two drives, so
3216 * update the state when switching to another drive. Only need
3217 * to update interrupt line if it is enabled and there is a
3218 * state change. */
3219 if ( !(pCtl->aIfs[pCtl->iSelectedIf].uATARegDevCtl & ATA_DEVCTL_DISABLE_IRQ)
3220 && ( pCtl->aIfs[pCtl->iSelectedIf].fIrqPending
3221 != pCtl->aIfs[pCtl->iSelectedIf ^ 1].fIrqPending))
3222 {
3223 if (pCtl->aIfs[pCtl->iSelectedIf].fIrqPending)
3224 {
3225 Log2(("%s: LUN#%d asserting IRQ (drive select change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf].iLUN));
3226 /* The BMDMA unit unconditionally sets BM_STATUS_INT if
3227 * the interrupt line is asserted. It monitors the line
3228 * for a rising edge. */
3229 pCtl->BmDma.u8Status |= BM_STATUS_INT;
3230 if (pCtl->irq == 16)
3231 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
3232 else
3233 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 1);
3234 }
3235 else
3236 {
3237 Log2(("%s: LUN#%d deasserting IRQ (drive select change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf].iLUN));
3238 if (pCtl->irq == 16)
3239 PDMDevHlpPCISetIrq(pDevIns, 0, 0);
3240 else
3241 PDMDevHlpISASetIrq(pDevIns, pCtl->irq, 0);
3242 }
3243 }
3244 }
3245 break;
3246 default:
3247 case 7: /* command */
3248 /* ignore commands to non existant slave */
3249 if (pCtl->iSelectedIf && !pCtl->aIfs[pCtl->iSelectedIf].pDrvBlock)
3250 break;
3251#ifndef IN_RING3
3252 /* Don't do anything complicated in GC */
3253 return VINF_IOM_HC_IOPORT_WRITE;
3254#else /* IN_RING3 */
3255 ataParseCmd(&pCtl->aIfs[pCtl->iSelectedIf], val);
3256#endif /* !IN_RING3 */
3257 }
3258 return VINF_SUCCESS;
3259}
3260
3261
3262static int ataIOPortReadU8(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t *pu32)
3263{
3264 AHCIATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];
3265 uint32_t val;
3266 bool fHOB;
3267
3268 fHOB = !!(s->uATARegDevCtl & (1 << 7));
3269 switch (addr & 7)
3270 {
3271 case 0: /* data register */
3272 val = 0xff;
3273 break;
3274 case 1: /* error register */
3275 /* The ATA specification is very terse when it comes to specifying
3276 * the precise effects of reading back the error/feature register.
3277 * The error register (read-only) shares the register number with
3278 * the feature register (write-only), so it seems that it's not
3279 * necessary to support the usual HOB readback here. */
3280 if (!s->pDrvBlock)
3281 val = 0;
3282 else
3283 val = s->uATARegError;
3284 break;
3285 case 2: /* sector count */
3286 if (!s->pDrvBlock)
3287 val = 0;
3288 else if (fHOB)
3289 val = s->uATARegNSectorHOB;
3290 else
3291 val = s->uATARegNSector;
3292 break;
3293 case 3: /* sector number */
3294 if (!s->pDrvBlock)
3295 val = 0;
3296 else if (fHOB)
3297 val = s->uATARegSectorHOB;
3298 else
3299 val = s->uATARegSector;
3300 break;
3301 case 4: /* cylinder low */
3302 if (!s->pDrvBlock)
3303 val = 0;
3304 else if (fHOB)
3305 val = s->uATARegLCylHOB;
3306 else
3307 val = s->uATARegLCyl;
3308 break;
3309 case 5: /* cylinder high */
3310 if (!s->pDrvBlock)
3311 val = 0;
3312 else if (fHOB)
3313 val = s->uATARegHCylHOB;
3314 else
3315 val = s->uATARegHCyl;
3316 break;
3317 case 6: /* drive/head */
3318 /* This register must always work as long as there is at least
3319 * one drive attached to the controller. It is common between
3320 * both drives anyway (completely identical content). */
3321 if (!pCtl->aIfs[0].pDrvBlock && !pCtl->aIfs[1].pDrvBlock)
3322 val = 0;
3323 else
3324 val = s->uATARegSelect;
3325 break;
3326 default:
3327 case 7: /* primary status */
3328 {
3329 /* Counter for number of busy status seen in GC in a row. */
3330 static unsigned cBusy = 0;
3331
3332 if (!s->pDrvBlock)
3333 val = 0;
3334 else
3335 val = s->uATARegStatus;
3336
3337 /* Give the async I/O thread an opportunity to make progress,
3338 * don't let it starve by guests polling frequently. EMT has a
3339 * lower priority than the async I/O thread, but sometimes the
3340 * host OS doesn't care. With some guests we are only allowed to
3341 * be busy for about 5 milliseconds in some situations. Note that
3342 * this is no guarantee for any other VBox thread getting
3343 * scheduled, so this just lowers the CPU load a bit when drives
3344 * are busy. It cannot help with timing problems. */
3345 if (val & ATA_STAT_BUSY)
3346 {
3347#ifdef IN_RING3
3348 cBusy = 0;
3349 PDMCritSectLeave(&pCtl->lock);
3350
3351 RTThreadYield();
3352
3353 {
3354 STAM_PROFILE_START(&pCtl->StatLockWait, a);
3355 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
3356 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
3357 }
3358
3359 val = s->uATARegStatus;
3360#else /* !IN_RING3 */
3361 /* Cannot yield CPU in guest context. And switching to host
3362 * context for each and every busy status is too costly,
3363 * especially on SMP systems where we don't gain much by
3364 * yielding the CPU to someone else. */
3365 if (++cBusy >= 20)
3366 {
3367 cBusy = 0;
3368 return VINF_IOM_HC_IOPORT_READ;
3369 }
3370#endif /* !IN_RING3 */
3371 }
3372 else
3373 cBusy = 0;
3374 ataUnsetIRQ(s);
3375 break;
3376 }
3377 }
3378 Log2(("%s: addr=%#x val=%#04x\n", __FUNCTION__, addr, val));
3379 *pu32 = val;
3380 return VINF_SUCCESS;
3381}
3382
3383
3384static uint32_t ataStatusRead(PAHCIATACONTROLLER pCtl, uint32_t addr)
3385{
3386 AHCIATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];
3387 uint32_t val;
3388
3389 if ((!pCtl->aIfs[0].pDrvBlock && !pCtl->aIfs[1].pDrvBlock) ||
3390 (pCtl->iSelectedIf == 1 && !s->pDrvBlock))
3391 val = 0;
3392 else
3393 val = s->uATARegStatus;
3394 Log2(("%s: addr=%#x val=%#04x\n", __FUNCTION__, addr, val));
3395 return val;
3396}
3397
3398static int ataControlWrite(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t val)
3399{
3400#ifndef IN_RING3
3401 if ((val ^ pCtl->aIfs[0].uATARegDevCtl) & ATA_DEVCTL_RESET)
3402 return VINF_IOM_HC_IOPORT_WRITE; /* The RESET stuff is too complicated for GC. */
3403#endif /* !IN_RING3 */
3404
3405 Log2(("%s: addr=%#x val=%#04x\n", __FUNCTION__, addr, val));
3406 /* RESET is common for both drives attached to a controller. */
3407 if (!(pCtl->aIfs[0].uATARegDevCtl & ATA_DEVCTL_RESET) &&
3408 (val & ATA_DEVCTL_RESET))
3409 {
3410#ifdef IN_RING3
3411 /* Software RESET low to high */
3412 int32_t uCmdWait0 = -1, uCmdWait1 = -1;
3413 uint64_t uNow = RTTimeNanoTS();
3414 if (pCtl->aIfs[0].u64CmdTS)
3415 uCmdWait0 = (uNow - pCtl->aIfs[0].u64CmdTS) / 1000;
3416 if (pCtl->aIfs[1].u64CmdTS)
3417 uCmdWait1 = (uNow - pCtl->aIfs[1].u64CmdTS) / 1000;
3418 LogRel(("AHCI ATA: Ctl: RESET, DevSel=%d AIOIf=%d CmdIf0=%#04x (%d usec ago) CmdIf1=%#04x (%d usec ago)\n",
3419 pCtl->iSelectedIf, pCtl->iAIOIf,
3420 pCtl->aIfs[0].uATARegCommand, uCmdWait0,
3421 pCtl->aIfs[1].uATARegCommand, uCmdWait1));
3422 pCtl->fReset = true;
3423 /* Everything must be done after the reset flag is set, otherwise
3424 * there are unavoidable races with the currently executing request
3425 * (which might just finish in the mean time). */
3426 pCtl->fChainedTransfer = false;
3427 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
3428 {
3429 ataResetDevice(&pCtl->aIfs[i]);
3430 /* The following cannot be done using ataSetStatusValue() since the
3431 * reset flag is already set, which suppresses all status changes. */
3432 pCtl->aIfs[i].uATARegStatus = ATA_STAT_BUSY | ATA_STAT_SEEK;
3433 Log2(("%s: LUN#%d status %#04x\n", __FUNCTION__, pCtl->aIfs[i].iLUN, pCtl->aIfs[i].uATARegStatus));
3434 pCtl->aIfs[i].uATARegError = 0x01;
3435 }
3436 ataAsyncIOClearRequests(pCtl);
3437 Log2(("%s: Ctl: message to async I/O thread, resetA\n", __FUNCTION__));
3438 if (val & ATA_DEVCTL_HOB)
3439 {
3440 val &= ~ATA_DEVCTL_HOB;
3441 Log2(("%s: ignored setting HOB\n", __FUNCTION__));
3442 }
3443 ataAsyncIOPutRequest(pCtl, &ataResetARequest);
3444#else /* !IN_RING3 */
3445 AssertMsgFailed(("RESET handling is too complicated for GC\n"));
3446#endif /* IN_RING3 */
3447 }
3448 else if ((pCtl->aIfs[0].uATARegDevCtl & ATA_DEVCTL_RESET) &&
3449 !(val & ATA_DEVCTL_RESET))
3450 {
3451#ifdef IN_RING3
3452 /* Software RESET high to low */
3453 Log(("%s: deasserting RESET\n", __FUNCTION__));
3454 Log2(("%s: Ctl: message to async I/O thread, resetC\n", __FUNCTION__));
3455 if (val & ATA_DEVCTL_HOB)
3456 {
3457 val &= ~ATA_DEVCTL_HOB;
3458 Log2(("%s: ignored setting HOB\n", __FUNCTION__));
3459 }
3460 ataAsyncIOPutRequest(pCtl, &ataResetCRequest);
3461#else /* !IN_RING3 */
3462 AssertMsgFailed(("RESET handling is too complicated for GC\n"));
3463#endif /* IN_RING3 */
3464 }
3465
3466 /* Change of interrupt disable flag. Update interrupt line if interrupt
3467 * is pending on the current interface. */
3468 if ((val ^ pCtl->aIfs[0].uATARegDevCtl) & ATA_DEVCTL_DISABLE_IRQ
3469 && pCtl->aIfs[pCtl->iSelectedIf].fIrqPending)
3470 {
3471 if (!(val & ATA_DEVCTL_DISABLE_IRQ))
3472 {
3473 Log2(("%s: LUN#%d asserting IRQ (interrupt disable change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf].iLUN));
3474 /* The BMDMA unit unconditionally sets BM_STATUS_INT if the
3475 * interrupt line is asserted. It monitors the line for a rising
3476 * edge. */
3477 pCtl->BmDma.u8Status |= BM_STATUS_INT;
3478 if (pCtl->irq == 16)
3479 PDMDevHlpPCISetIrq(CONTROLLER_2_DEVINS(pCtl), 0, 1);
3480 else
3481 PDMDevHlpISASetIrq(CONTROLLER_2_DEVINS(pCtl), pCtl->irq, 1);
3482 }
3483 else
3484 {
3485 Log2(("%s: LUN#%d deasserting IRQ (interrupt disable change)\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf].iLUN));
3486 if (pCtl->irq == 16)
3487 PDMDevHlpPCISetIrq(CONTROLLER_2_DEVINS(pCtl), 0, 0);
3488 else
3489 PDMDevHlpISASetIrq(CONTROLLER_2_DEVINS(pCtl), pCtl->irq, 0);
3490 }
3491 }
3492
3493 if (val & ATA_DEVCTL_HOB)
3494 Log2(("%s: set HOB\n", __FUNCTION__));
3495
3496 pCtl->aIfs[0].uATARegDevCtl = val;
3497 pCtl->aIfs[1].uATARegDevCtl = val;
3498
3499 return VINF_SUCCESS;
3500}
3501
3502#ifdef IN_RING3
3503
3504static void ataPIOTransfer(PAHCIATACONTROLLER pCtl)
3505{
3506 AHCIATADevState *s;
3507
3508 s = &pCtl->aIfs[pCtl->iAIOIf];
3509 Log3(("%s: if=%p\n", __FUNCTION__, s));
3510
3511 if (s->cbTotalTransfer && s->iIOBufferCur > s->iIOBufferEnd)
3512 {
3513 LogRel(("AHCI ATA: LUN#%d: %s data in the middle of a PIO transfer - VERY SLOW\n", s->iLUN, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "loading" : "storing"));
3514 /* Any guest OS that triggers this case has a pathetic ATA driver.
3515 * In a real system it would block the CPU via IORDY, here we do it
3516 * very similarly by not continuing with the current instruction
3517 * until the transfer to/from the storage medium is completed. */
3518 if (s->iSourceSink != ATAFN_SS_NULL)
3519 {
3520 bool fRedo;
3521 uint8_t status = s->uATARegStatus;
3522 ataSetStatusValue(s, ATA_STAT_BUSY);
3523 Log2(("%s: calling source/sink function\n", __FUNCTION__));
3524 fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
3525 pCtl->fRedo = fRedo;
3526 if (RT_UNLIKELY(fRedo))
3527 return;
3528 ataSetStatusValue(s, status);
3529 s->iIOBufferCur = 0;
3530 s->iIOBufferEnd = s->cbElementaryTransfer;
3531 }
3532 }
3533 if (s->cbTotalTransfer)
3534 {
3535 if (s->fATAPITransfer)
3536 ataPIOTransferLimitATAPI(s);
3537
3538 if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
3539 s->cbElementaryTransfer = s->cbTotalTransfer;
3540
3541 Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
3542 __FUNCTION__, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T",
3543 s->cbTotalTransfer, s->cbElementaryTransfer,
3544 s->iIOBufferCur, s->iIOBufferEnd));
3545 ataPIOTransferStart(s, s->iIOBufferCur, s->cbElementaryTransfer);
3546 s->cbTotalTransfer -= s->cbElementaryTransfer;
3547 s->iIOBufferCur += s->cbElementaryTransfer;
3548
3549 if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
3550 s->cbElementaryTransfer = s->cbTotalTransfer;
3551 }
3552 else
3553 ataPIOTransferStop(s);
3554}
3555
3556
3557DECLINLINE(void) ataPIOTransferFinish(PAHCIATACONTROLLER pCtl, AHCIATADevState *s)
3558{
3559 /* Do not interfere with RESET processing if the PIO transfer finishes
3560 * while the RESET line is asserted. */
3561 if (pCtl->fReset)
3562 {
3563 Log2(("%s: Ctl: suppressed continuing PIO transfer as RESET is active\n", __FUNCTION__));
3564 return;
3565 }
3566
3567 if ( s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE
3568 || ( s->iSourceSink != ATAFN_SS_NULL
3569 && s->iIOBufferCur >= s->iIOBufferEnd))
3570 {
3571 /* Need to continue the transfer in the async I/O thread. This is
3572 * the case for write operations or generally for not yet finished
3573 * transfers (some data might need to be read). */
3574 ataUnsetStatus(s, ATA_STAT_READY | ATA_STAT_DRQ);
3575 ataSetStatus(s, ATA_STAT_BUSY);
3576
3577 Log2(("%s: Ctl: message to async I/O thread, continuing PIO transfer\n", __FUNCTION__));
3578 ataAsyncIOPutRequest(pCtl, &ataPIORequest);
3579 }
3580 else
3581 {
3582 /* Either everything finished (though some data might still be pending)
3583 * or some data is pending before the next read is due. */
3584
3585 /* Continue a previously started transfer. */
3586 ataUnsetStatus(s, ATA_STAT_DRQ);
3587 ataSetStatus(s, ATA_STAT_READY);
3588
3589 if (s->cbTotalTransfer)
3590 {
3591 /* There is more to transfer, happens usually for large ATAPI
3592 * reads - the protocol limits the chunk size to 65534 bytes. */
3593 ataPIOTransfer(pCtl);
3594 ataSetIRQ(s);
3595 }
3596 else
3597 {
3598 Log2(("%s: Ctl: skipping message to async I/O thread, ending PIO transfer\n", __FUNCTION__));
3599 /* Finish PIO transfer. */
3600 ataPIOTransfer(pCtl);
3601 Assert(!pCtl->fRedo);
3602 }
3603 }
3604}
3605
3606#endif /* IN_RING3 */
3607
3608static int ataDataWrite(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t cbSize, const uint8_t *pbBuf)
3609{
3610 AHCIATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];
3611 uint8_t *p;
3612
3613 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd)
3614 {
3615 Assert(s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE);
3616 p = s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart;
3617#ifndef IN_RING3
3618 /* All but the last transfer unit is simple enough for GC, but
3619 * sending a request to the async IO thread is too complicated. */
3620 if (s->iIOBufferPIODataStart + cbSize < s->iIOBufferPIODataEnd)
3621 {
3622 memcpy(p, pbBuf, cbSize);
3623 s->iIOBufferPIODataStart += cbSize;
3624 }
3625 else
3626 return VINF_IOM_HC_IOPORT_WRITE;
3627#else /* IN_RING3 */
3628 memcpy(p, pbBuf, cbSize);
3629 s->iIOBufferPIODataStart += cbSize;
3630 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)
3631 ataPIOTransferFinish(pCtl, s);
3632#endif /* !IN_RING3 */
3633 }
3634 else
3635 Log2(("%s: DUMMY data\n", __FUNCTION__));
3636 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, addr, cbSize, pbBuf));
3637 return VINF_SUCCESS;
3638}
3639
3640static int ataDataRead(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t cbSize, uint8_t *pbBuf)
3641{
3642 AHCIATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];
3643 uint8_t *p;
3644
3645 if (s->iIOBufferPIODataStart < s->iIOBufferPIODataEnd)
3646 {
3647 Assert(s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE);
3648 p = s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart;
3649#ifndef IN_RING3
3650 /* All but the last transfer unit is simple enough for GC, but
3651 * sending a request to the async IO thread is too complicated. */
3652 if (s->iIOBufferPIODataStart + cbSize < s->iIOBufferPIODataEnd)
3653 {
3654 memcpy(pbBuf, p, cbSize);
3655 s->iIOBufferPIODataStart += cbSize;
3656 }
3657 else
3658 return VINF_IOM_HC_IOPORT_READ;
3659#else /* IN_RING3 */
3660 memcpy(pbBuf, p, cbSize);
3661 s->iIOBufferPIODataStart += cbSize;
3662 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)
3663 ataPIOTransferFinish(pCtl, s);
3664#endif /* !IN_RING3 */
3665 }
3666 else
3667 {
3668 Log2(("%s: DUMMY data\n", __FUNCTION__));
3669 memset(pbBuf, '\xff', cbSize);
3670 }
3671 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, addr, cbSize, pbBuf));
3672 return VINF_SUCCESS;
3673}
3674
3675#ifdef IN_RING3
3676
3677static void ataDMATransferStop(AHCIATADevState *s)
3678{
3679 s->cbTotalTransfer = 0;
3680 s->cbElementaryTransfer = 0;
3681 s->iBeginTransfer = ATAFN_BT_NULL;
3682 s->iSourceSink = ATAFN_SS_NULL;
3683}
3684
3685
3686/**
3687 * Perform the entire DMA transfer in one go (unless a source/sink operation
3688 * has to be redone or a RESET comes in between). Unlike the PIO counterpart
3689 * this function cannot handle empty transfers.
3690 *
3691 * @param pCtl Controller for which to perform the transfer.
3692 */
3693static void ataDMATransfer(PAHCIATACONTROLLER pCtl)
3694{
3695 PPDMDEVINS pDevIns = CONTROLLER_2_DEVINS(pCtl);
3696 AHCIATADevState *s = &pCtl->aIfs[pCtl->iAIOIf];
3697 bool fRedo;
3698 RTGCPHYS32 pDesc;
3699 uint32_t cbTotalTransfer, cbElementaryTransfer;
3700 uint32_t iIOBufferCur, iIOBufferEnd;
3701 uint32_t dmalen;
3702 PDMBLOCKTXDIR uTxDir;
3703 bool fLastDesc = false;
3704
3705 Assert(sizeof(BMDMADesc) == 8);
3706
3707 fRedo = pCtl->fRedo;
3708 if (RT_LIKELY(!fRedo))
3709 Assert(s->cbTotalTransfer);
3710 uTxDir = (PDMBLOCKTXDIR)s->uTxDir;
3711 cbTotalTransfer = s->cbTotalTransfer;
3712 cbElementaryTransfer = s->cbElementaryTransfer;
3713 iIOBufferCur = s->iIOBufferCur;
3714 iIOBufferEnd = s->iIOBufferEnd;
3715
3716 /* The DMA loop is designed to hold the lock only when absolutely
3717 * necessary. This avoids long freezes should the guest access the
3718 * ATA registers etc. for some reason. */
3719 PDMCritSectLeave(&pCtl->lock);
3720
3721 Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
3722 __FUNCTION__, uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T",
3723 cbTotalTransfer, cbElementaryTransfer,
3724 iIOBufferCur, iIOBufferEnd));
3725 for (pDesc = pCtl->pFirstDMADesc; pDesc <= pCtl->pLastDMADesc; pDesc += sizeof(BMDMADesc))
3726 {
3727 BMDMADesc DMADesc;
3728 RTGCPHYS32 pBuffer;
3729 uint32_t cbBuffer;
3730
3731 if (RT_UNLIKELY(fRedo))
3732 {
3733 pBuffer = pCtl->pRedoDMABuffer;
3734 cbBuffer = pCtl->cbRedoDMABuffer;
3735 fLastDesc = pCtl->fRedoDMALastDesc;
3736 }
3737 else
3738 {
3739 PDMDevHlpPhysRead(pDevIns, pDesc, &DMADesc, sizeof(BMDMADesc));
3740 pBuffer = RT_LE2H_U32(DMADesc.pBuffer);
3741 cbBuffer = RT_LE2H_U32(DMADesc.cbBuffer);
3742 fLastDesc = !!(cbBuffer & 0x80000000);
3743 cbBuffer &= 0xfffe;
3744 if (cbBuffer == 0)
3745 cbBuffer = 0x10000;
3746 if (cbBuffer > cbTotalTransfer)
3747 cbBuffer = cbTotalTransfer;
3748 }
3749
3750 while (RT_UNLIKELY(fRedo) || (cbBuffer && cbTotalTransfer))
3751 {
3752 if (RT_LIKELY(!fRedo))
3753 {
3754 dmalen = RT_MIN(cbBuffer, iIOBufferEnd - iIOBufferCur);
3755 Log2(("%s: DMA desc %#010x: addr=%#010x size=%#010x\n", __FUNCTION__,
3756 pDesc, pBuffer, cbBuffer));
3757 if (uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
3758 PDMDevHlpPhysWrite(pDevIns, pBuffer, s->CTX_SUFF(pbIOBuffer) + iIOBufferCur, dmalen);
3759 else
3760 PDMDevHlpPhysRead(pDevIns, pBuffer, s->CTX_SUFF(pbIOBuffer) + iIOBufferCur, dmalen);
3761 iIOBufferCur += dmalen;
3762 cbTotalTransfer -= dmalen;
3763 cbBuffer -= dmalen;
3764 pBuffer += dmalen;
3765 }
3766 if ( iIOBufferCur == iIOBufferEnd
3767 && (uTxDir == PDMBLOCKTXDIR_TO_DEVICE || cbTotalTransfer))
3768 {
3769 if (uTxDir == PDMBLOCKTXDIR_FROM_DEVICE && cbElementaryTransfer > cbTotalTransfer)
3770 cbElementaryTransfer = cbTotalTransfer;
3771
3772 {
3773 STAM_PROFILE_START(&pCtl->StatLockWait, a);
3774 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
3775 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
3776 }
3777
3778 /* The RESET handler could have cleared the DMA transfer
3779 * state (since we didn't hold the lock until just now
3780 * the guest can continue in parallel). If so, the state
3781 * is already set up so the loop is exited immediately. */
3782 if (s->iSourceSink != ATAFN_SS_NULL)
3783 {
3784 s->iIOBufferCur = iIOBufferCur;
3785 s->iIOBufferEnd = iIOBufferEnd;
3786 s->cbElementaryTransfer = cbElementaryTransfer;
3787 s->cbTotalTransfer = cbTotalTransfer;
3788 Log2(("%s: calling source/sink function\n", __FUNCTION__));
3789 fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
3790 if (RT_UNLIKELY(fRedo))
3791 {
3792 pCtl->pFirstDMADesc = pDesc;
3793 pCtl->pRedoDMABuffer = pBuffer;
3794 pCtl->cbRedoDMABuffer = cbBuffer;
3795 pCtl->fRedoDMALastDesc = fLastDesc;
3796 }
3797 else
3798 {
3799 cbTotalTransfer = s->cbTotalTransfer;
3800 cbElementaryTransfer = s->cbElementaryTransfer;
3801
3802 if (uTxDir == PDMBLOCKTXDIR_TO_DEVICE && cbElementaryTransfer > cbTotalTransfer)
3803 cbElementaryTransfer = cbTotalTransfer;
3804 iIOBufferCur = 0;
3805 iIOBufferEnd = cbElementaryTransfer;
3806 }
3807 pCtl->fRedo = fRedo;
3808 }
3809 else
3810 {
3811 /* This forces the loop to exit immediately. */
3812 pDesc = pCtl->pLastDMADesc + 1;
3813 }
3814
3815 PDMCritSectLeave(&pCtl->lock);
3816 if (RT_UNLIKELY(fRedo))
3817 break;
3818 }
3819 }
3820
3821 if (RT_UNLIKELY(fRedo))
3822 break;
3823
3824 /* end of transfer */
3825 if (!cbTotalTransfer || fLastDesc)
3826 break;
3827
3828 {
3829 STAM_PROFILE_START(&pCtl->StatLockWait, a);
3830 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
3831 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
3832 }
3833
3834 if (!(pCtl->BmDma.u8Cmd & BM_CMD_START) || pCtl->fReset)
3835 {
3836 LogRel(("AHCI ATA: Ctl: ABORT DMA%s\n", pCtl->fReset ? " due to RESET" : ""));
3837 if (!pCtl->fReset)
3838 ataDMATransferStop(s);
3839 /* This forces the loop to exit immediately. */
3840 pDesc = pCtl->pLastDMADesc + 1;
3841 }
3842
3843 PDMCritSectLeave(&pCtl->lock);
3844 }
3845
3846 {
3847 STAM_PROFILE_START(&pCtl->StatLockWait, a);
3848 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
3849 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
3850 }
3851
3852 if (RT_UNLIKELY(fRedo))
3853 return;
3854
3855 if (fLastDesc)
3856 pCtl->BmDma.u8Status &= ~BM_STATUS_DMAING;
3857 s->cbTotalTransfer = cbTotalTransfer;
3858 s->cbElementaryTransfer = cbElementaryTransfer;
3859 s->iIOBufferCur = iIOBufferCur;
3860 s->iIOBufferEnd = iIOBufferEnd;
3861}
3862
3863
3864/**
3865 * Signal ataWaitForAsyncIOIsIdle that we're idle (if we actually are).
3866 *
3867 * @param pCtl The controller.
3868 */
3869static void ataAsyncSignalIdle(PAHCIATACONTROLLER pCtl)
3870{
3871 /*
3872 * Take the mutex here and recheck the idle indicator as there might be
3873 * interesting races, like in the ataReset code.
3874 */
3875 int rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT); AssertRC(rc);
3876
3877 if ( pCtl->fSignalIdle
3878 && ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
3879 {
3880 PDMDevHlpAsyncNotificationCompleted(pCtl->pDevInsR3);
3881 RTThreadUserSignal(pCtl->AsyncIOThread);
3882 }
3883
3884 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex); AssertRC(rc);
3885}
3886
3887
3888/** Async I/O thread for an interface. Once upon a time this was readable
3889 * code with several loops and a different semaphore for each purpose. But
3890 * then came the "how can one save the state in the middle of a PIO transfer"
3891 * question. The solution was to use an ASM, which is what's there now. */
3892static DECLCALLBACK(int) ataAsyncIOLoop(RTTHREAD ThreadSelf, void *pvUser)
3893{
3894 const AHCIATARequest *pReq;
3895 uint64_t u64TS = 0; /* shut up gcc */
3896 uint64_t uWait;
3897 int rc = VINF_SUCCESS;
3898 PAHCIATACONTROLLER pCtl = (PAHCIATACONTROLLER)pvUser;
3899 AHCIATADevState *s;
3900
3901 pReq = NULL;
3902 pCtl->fChainedTransfer = false;
3903 while (!pCtl->fShutdown)
3904 {
3905 /* Keep this thread from doing anything as long as EMT is suspended. */
3906 while (pCtl->fRedoIdle)
3907 {
3908 if (pCtl->fSignalIdle)
3909 ataAsyncSignalIdle(pCtl);
3910 rc = RTSemEventWait(pCtl->SuspendIOSem, RT_INDEFINITE_WAIT);
3911 if (RT_FAILURE(rc) || pCtl->fShutdown)
3912 break;
3913
3914 pCtl->fRedoIdle = false;
3915 }
3916
3917 /* Wait for work. */
3918 if (pReq == NULL)
3919 {
3920 if (pCtl->fSignalIdle)
3921 ataAsyncSignalIdle(pCtl);
3922 rc = RTSemEventWait(pCtl->AsyncIOSem, RT_INDEFINITE_WAIT);
3923 if (RT_FAILURE(rc) || pCtl->fShutdown)
3924 break;
3925
3926 pReq = ataAsyncIOGetCurrentRequest(pCtl);
3927 }
3928
3929 if (pReq == NULL)
3930 continue;
3931
3932 AHCIATAAIO ReqType = pReq->ReqType;
3933
3934 Log2(("%s: Ctl: state=%d, req=%d\n", __FUNCTION__, pCtl->uAsyncIOState, ReqType));
3935 if (pCtl->uAsyncIOState != ReqType)
3936 {
3937 /* The new state is not the state that was expected by the normal
3938 * state changes. This is either a RESET/ABORT or there's something
3939 * really strange going on. */
3940 if ( (pCtl->uAsyncIOState == AHCIATA_AIO_PIO || pCtl->uAsyncIOState == AHCIATA_AIO_DMA)
3941 && (ReqType == AHCIATA_AIO_PIO || ReqType == AHCIATA_AIO_DMA))
3942 {
3943 /* Incorrect sequence of PIO/DMA states. Dump request queue. */
3944 ataAsyncIODumpRequests(pCtl);
3945 }
3946 AssertReleaseMsg(ReqType == AHCIATA_AIO_RESET_ASSERTED || ReqType == AHCIATA_AIO_RESET_CLEARED || ReqType == AHCIATA_AIO_ABORT || pCtl->uAsyncIOState == ReqType, ("I/O state inconsistent: state=%d request=%d\n", pCtl->uAsyncIOState, ReqType));
3947 }
3948
3949 /* Do our work. */
3950 {
3951 STAM_PROFILE_START(&pCtl->StatLockWait, a);
3952 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
3953 STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
3954 }
3955
3956 if (pCtl->uAsyncIOState == AHCIATA_AIO_NEW && !pCtl->fChainedTransfer)
3957 {
3958 u64TS = RTTimeNanoTS();
3959#if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
3960 STAM_PROFILE_ADV_START(&pCtl->StatAsyncTime, a);
3961#endif /* DEBUG || VBOX_WITH_STATISTICS */
3962 }
3963
3964 switch (ReqType)
3965 {
3966 case AHCIATA_AIO_NEW:
3967
3968 pCtl->iAIOIf = pReq->u.t.iIf;
3969 s = &pCtl->aIfs[pCtl->iAIOIf];
3970 s->cbTotalTransfer = pReq->u.t.cbTotalTransfer;
3971 s->uTxDir = pReq->u.t.uTxDir;
3972 s->iBeginTransfer = pReq->u.t.iBeginTransfer;
3973 s->iSourceSink = pReq->u.t.iSourceSink;
3974 s->iIOBufferEnd = 0;
3975 s->u64CmdTS = u64TS;
3976
3977 if (s->fATAPI)
3978 {
3979 if (pCtl->fChainedTransfer)
3980 {
3981 /* Only count the actual transfers, not the PIO
3982 * transfer of the ATAPI command bytes. */
3983 if (s->fDMA)
3984 STAM_REL_COUNTER_INC(&s->StatATAPIDMA);
3985 else
3986 STAM_REL_COUNTER_INC(&s->StatATAPIPIO);
3987 }
3988 }
3989 else
3990 {
3991 if (s->fDMA)
3992 STAM_REL_COUNTER_INC(&s->StatATADMA);
3993 else
3994 STAM_REL_COUNTER_INC(&s->StatATAPIO);
3995 }
3996
3997 pCtl->fChainedTransfer = false;
3998
3999 if (s->iBeginTransfer != ATAFN_BT_NULL)
4000 {
4001 Log2(("%s: Ctl: calling begin transfer function\n", __FUNCTION__));
4002 g_apfnBeginTransFuncs[s->iBeginTransfer](s);
4003 s->iBeginTransfer = ATAFN_BT_NULL;
4004 if (s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)
4005 s->iIOBufferEnd = s->cbElementaryTransfer;
4006 }
4007 else
4008 {
4009 s->cbElementaryTransfer = s->cbTotalTransfer;
4010 s->iIOBufferEnd = s->cbTotalTransfer;
4011 }
4012 s->iIOBufferCur = 0;
4013
4014 if (s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE)
4015 {
4016 if (s->iSourceSink != ATAFN_SS_NULL)
4017 {
4018 bool fRedo;
4019 Log2(("%s: Ctl: calling source/sink function\n", __FUNCTION__));
4020 fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
4021 pCtl->fRedo = fRedo;
4022 if (RT_UNLIKELY(fRedo))
4023 {
4024 /* Operation failed at the initial transfer, restart
4025 * everything from scratch by resending the current
4026 * request. Occurs very rarely, not worth optimizing. */
4027 LogRel(("%s: Ctl: redo entire operation\n", __FUNCTION__));
4028 ataAsyncIOPutRequest(pCtl, pReq);
4029 break;
4030 }
4031 }
4032 else
4033 ataCmdOK(s, 0);
4034 s->iIOBufferEnd = s->cbElementaryTransfer;
4035
4036 }
4037
4038 /* Do not go into the transfer phase if RESET is asserted.
4039 * The CritSect is released while waiting for the host OS
4040 * to finish the I/O, thus RESET is possible here. Most
4041 * important: do not change uAsyncIOState. */
4042 if (pCtl->fReset)
4043 break;
4044
4045 if (s->fDMA)
4046 {
4047 if (s->cbTotalTransfer)
4048 {
4049 ataSetStatus(s, ATA_STAT_DRQ);
4050
4051 pCtl->uAsyncIOState = AHCIATA_AIO_DMA;
4052 /* If BMDMA is already started, do the transfer now. */
4053 if (pCtl->BmDma.u8Cmd & BM_CMD_START)
4054 {
4055 Log2(("%s: Ctl: message to async I/O thread, continuing DMA transfer immediately\n", __FUNCTION__));
4056 ataAsyncIOPutRequest(pCtl, &ataDMARequest);
4057 }
4058 }
4059 else
4060 {
4061 Assert(s->uTxDir == PDMBLOCKTXDIR_NONE); /* Any transfer which has an initial transfer size of 0 must be marked as such. */
4062 /* Finish DMA transfer. */
4063 ataDMATransferStop(s);
4064 ataSetIRQ(s);
4065 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4066 }
4067 }
4068 else
4069 {
4070 if (s->cbTotalTransfer)
4071 {
4072 ataPIOTransfer(pCtl);
4073 Assert(!pCtl->fRedo);
4074 if (s->fATAPITransfer || s->uTxDir != PDMBLOCKTXDIR_TO_DEVICE)
4075 ataSetIRQ(s);
4076
4077 if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
4078 {
4079 /* Write operations and not yet finished transfers
4080 * must be completed in the async I/O thread. */
4081 pCtl->uAsyncIOState = AHCIATA_AIO_PIO;
4082 }
4083 else
4084 {
4085 /* Finished read operation can be handled inline
4086 * in the end of PIO transfer handling code. Linux
4087 * depends on this, as it waits only briefly for
4088 * devices to become ready after incoming data
4089 * transfer. Cannot find anything in the ATA spec
4090 * that backs this assumption, but as all kernels
4091 * are affected (though most of the time it does
4092 * not cause any harm) this must work. */
4093 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4094 }
4095 }
4096 else
4097 {
4098 Assert(s->uTxDir == PDMBLOCKTXDIR_NONE); /* Any transfer which has an initial transfer size of 0 must be marked as such. */
4099 /* Finish PIO transfer. */
4100 ataPIOTransfer(pCtl);
4101 Assert(!pCtl->fRedo);
4102 if (!s->fATAPITransfer)
4103 ataSetIRQ(s);
4104 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4105 }
4106 }
4107 break;
4108
4109 case AHCIATA_AIO_DMA:
4110 {
4111 BMDMAState *bm = &pCtl->BmDma;
4112 s = &pCtl->aIfs[pCtl->iAIOIf]; /* Do not remove or there's an instant crash after loading the saved state */
4113 ATAFNSS iOriginalSourceSink = (ATAFNSS)s->iSourceSink; /* Used by the hack below, but gets reset by then. */
4114
4115 if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE)
4116 AssertRelease(bm->u8Cmd & BM_CMD_WRITE);
4117 else
4118 AssertRelease(!(bm->u8Cmd & BM_CMD_WRITE));
4119
4120 if (RT_LIKELY(!pCtl->fRedo))
4121 {
4122 /* The specs say that the descriptor table must not cross a
4123 * 4K boundary. */
4124 pCtl->pFirstDMADesc = bm->pvAddr;
4125 pCtl->pLastDMADesc = RT_ALIGN_32(bm->pvAddr + 1, _4K) - sizeof(BMDMADesc);
4126 }
4127 ataDMATransfer(pCtl);
4128
4129 if (RT_UNLIKELY(pCtl->fRedo))
4130 {
4131 LogRel(("AHCI ATA: Ctl: redo DMA operation\n"));
4132 ataAsyncIOPutRequest(pCtl, &ataDMARequest);
4133 break;
4134 }
4135
4136 /* The infamous delay IRQ hack. */
4137 if ( iOriginalSourceSink == ATAFN_SS_WRITE_SECTORS
4138 && s->cbTotalTransfer == 0
4139 && pCtl->DelayIRQMillies)
4140 {
4141 /* Delay IRQ for writing. Required to get the Win2K
4142 * installation work reliably (otherwise it crashes,
4143 * usually during component install). So far no better
4144 * solution has been found. */
4145 Log(("%s: delay IRQ hack\n", __FUNCTION__));
4146 PDMCritSectLeave(&pCtl->lock);
4147 RTThreadSleep(pCtl->DelayIRQMillies);
4148 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
4149 }
4150
4151 ataUnsetStatus(s, ATA_STAT_DRQ);
4152 Assert(!pCtl->fChainedTransfer);
4153 Assert(s->iSourceSink == ATAFN_SS_NULL);
4154 if (s->fATAPITransfer)
4155 {
4156 s->uATARegNSector = (s->uATARegNSector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
4157 Log2(("%s: Ctl: interrupt reason %#04x\n", __FUNCTION__, s->uATARegNSector));
4158 s->fATAPITransfer = false;
4159 }
4160 ataSetIRQ(s);
4161 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4162 break;
4163 }
4164
4165 case AHCIATA_AIO_PIO:
4166 s = &pCtl->aIfs[pCtl->iAIOIf]; /* Do not remove or there's an instant crash after loading the saved state */
4167
4168 if (s->iSourceSink != ATAFN_SS_NULL)
4169 {
4170 bool fRedo;
4171 Log2(("%s: Ctl: calling source/sink function\n", __FUNCTION__));
4172 fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
4173 pCtl->fRedo = fRedo;
4174 if (RT_UNLIKELY(fRedo))
4175 {
4176 LogRel(("AHCI ATA: Ctl: redo PIO operation\n"));
4177 ataAsyncIOPutRequest(pCtl, &ataPIORequest);
4178 break;
4179 }
4180 s->iIOBufferCur = 0;
4181 s->iIOBufferEnd = s->cbElementaryTransfer;
4182 }
4183 else
4184 {
4185 /* Continue a previously started transfer. */
4186 ataUnsetStatus(s, ATA_STAT_BUSY);
4187 ataSetStatus(s, ATA_STAT_READY);
4188 }
4189
4190 /* It is possible that the drives on this controller get RESET
4191 * during the above call to the source/sink function. If that's
4192 * the case, don't restart the transfer and don't finish it the
4193 * usual way. RESET handling took care of all that already.
4194 * Most important: do not change uAsyncIOState. */
4195 if (pCtl->fReset)
4196 break;
4197
4198 if (s->cbTotalTransfer)
4199 {
4200 ataPIOTransfer(pCtl);
4201 ataSetIRQ(s);
4202
4203 if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
4204 {
4205 /* Write operations and not yet finished transfers
4206 * must be completed in the async I/O thread. */
4207 pCtl->uAsyncIOState = AHCIATA_AIO_PIO;
4208 }
4209 else
4210 {
4211 /* Finished read operation can be handled inline
4212 * in the end of PIO transfer handling code. Linux
4213 * depends on this, as it waits only briefly for
4214 * devices to become ready after incoming data
4215 * transfer. Cannot find anything in the ATA spec
4216 * that backs this assumption, but as all kernels
4217 * are affected (though most of the time it does
4218 * not cause any harm) this must work. */
4219 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4220 }
4221 }
4222 else
4223 {
4224 /* Finish PIO transfer. */
4225 ataPIOTransfer(pCtl);
4226 if ( !pCtl->fChainedTransfer
4227 && !s->fATAPITransfer
4228 && s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)
4229 {
4230 ataSetIRQ(s);
4231 }
4232 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4233 }
4234 break;
4235
4236 case AHCIATA_AIO_RESET_ASSERTED:
4237 pCtl->uAsyncIOState = AHCIATA_AIO_RESET_CLEARED;
4238 ataPIOTransferStop(&pCtl->aIfs[0]);
4239 ataPIOTransferStop(&pCtl->aIfs[1]);
4240 /* Do not change the DMA registers, they are not affected by the
4241 * ATA controller reset logic. It should be sufficient to issue a
4242 * new command, which is now possible as the state is cleared. */
4243 break;
4244
4245 case AHCIATA_AIO_RESET_CLEARED:
4246 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4247 pCtl->fReset = false;
4248 LogRel(("AHCI ATA: Ctl: finished processing RESET\n"));
4249 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
4250 {
4251 if (pCtl->aIfs[i].fATAPI)
4252 ataSetStatusValue(&pCtl->aIfs[i], 0); /* NOTE: READY is _not_ set */
4253 else
4254 ataSetStatusValue(&pCtl->aIfs[i], ATA_STAT_READY | ATA_STAT_SEEK);
4255 ataSetSignature(&pCtl->aIfs[i]);
4256 }
4257 break;
4258
4259 case AHCIATA_AIO_ABORT:
4260 /* Abort the current command only if it operates on the same interface. */
4261 if (pCtl->iAIOIf == pReq->u.a.iIf)
4262 {
4263 s = &pCtl->aIfs[pCtl->iAIOIf];
4264
4265 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4266 /* Do not change the DMA registers, they are not affected by the
4267 * ATA controller reset logic. It should be sufficient to issue a
4268 * new command, which is now possible as the state is cleared. */
4269 if (pReq->u.a.fResetDrive)
4270 {
4271 ataResetDevice(s);
4272 ataExecuteDeviceDiagnosticSS(s);
4273 }
4274 else
4275 {
4276 ataPIOTransferStop(s);
4277 ataUnsetStatus(s, ATA_STAT_BUSY | ATA_STAT_DRQ | ATA_STAT_SEEK | ATA_STAT_ERR);
4278 ataSetStatus(s, ATA_STAT_READY);
4279 ataSetIRQ(s);
4280 }
4281 }
4282 break;
4283
4284 default:
4285 AssertMsgFailed(("Undefined async I/O state %d\n", pCtl->uAsyncIOState));
4286 }
4287
4288 ataAsyncIORemoveCurrentRequest(pCtl, ReqType);
4289 pReq = ataAsyncIOGetCurrentRequest(pCtl);
4290
4291 if (pCtl->uAsyncIOState == AHCIATA_AIO_NEW && !pCtl->fChainedTransfer)
4292 {
4293#if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
4294 STAM_PROFILE_ADV_STOP(&pCtl->StatAsyncTime, a);
4295#endif /* DEBUG || VBOX_WITH_STATISTICS */
4296
4297 u64TS = RTTimeNanoTS() - u64TS;
4298 uWait = u64TS / 1000;
4299 Log(("%s: Ctl: LUN#%d finished I/O transaction in %d microseconds\n", __FUNCTION__, pCtl->aIfs[pCtl->iAIOIf].iLUN, (uint32_t)(uWait)));
4300 /* Mark command as finished. */
4301 pCtl->aIfs[pCtl->iAIOIf].u64CmdTS = 0;
4302
4303 /*
4304 * Release logging of command execution times depends on the
4305 * command type. ATAPI commands often take longer (due to CD/DVD
4306 * spin up time etc.) so the threshold is different.
4307 */
4308 if (pCtl->aIfs[pCtl->iAIOIf].uATARegCommand != ATA_PACKET)
4309 {
4310 if (uWait > 8 * 1000 * 1000)
4311 {
4312 /*
4313 * Command took longer than 8 seconds. This is close
4314 * enough or over the guest's command timeout, so place
4315 * an entry in the release log to allow tracking such
4316 * timing errors (which are often caused by the host).
4317 */
4318 LogRel(("AHCI ATA: execution time for ATA command %#04x was %d seconds\n", pCtl->aIfs[pCtl->iAIOIf].uATARegCommand, uWait / (1000 * 1000)));
4319 }
4320 }
4321 else
4322 {
4323 if (uWait > 20 * 1000 * 1000)
4324 {
4325 /*
4326 * Command took longer than 20 seconds. This is close
4327 * enough or over the guest's command timeout, so place
4328 * an entry in the release log to allow tracking such
4329 * timing errors (which are often caused by the host).
4330 */
4331 LogRel(("AHCI ATA: execution time for ATAPI command %#04x was %d seconds\n", pCtl->aIfs[pCtl->iAIOIf].aATAPICmd[0], uWait / (1000 * 1000)));
4332 }
4333 }
4334
4335#if defined(DEBUG) || defined(VBOX_WITH_STATISTICS)
4336 if (uWait < pCtl->StatAsyncMinWait || !pCtl->StatAsyncMinWait)
4337 pCtl->StatAsyncMinWait = uWait;
4338 if (uWait > pCtl->StatAsyncMaxWait)
4339 pCtl->StatAsyncMaxWait = uWait;
4340
4341 STAM_COUNTER_ADD(&pCtl->StatAsyncTimeUS, uWait);
4342 STAM_COUNTER_INC(&pCtl->StatAsyncOps);
4343#endif /* DEBUG || VBOX_WITH_STATISTICS */
4344 }
4345
4346 PDMCritSectLeave(&pCtl->lock);
4347 }
4348
4349 /* Signal the ultimate idleness. */
4350 if (pCtl->fSignalIdle)
4351 PDMDevHlpAsyncNotificationCompleted(pCtl->pDevInsR3);
4352 RTThreadUserSignal(ThreadSelf);
4353
4354 /* Do not destroy request mutex yet, still needed for proper shutdown. */
4355 pCtl->fShutdown = false;
4356
4357 Log2(("%s: Ctl: return %Rrc\n", __FUNCTION__, rc));
4358 return rc;
4359}
4360
4361#endif /* IN_RING3 */
4362
4363static uint32_t ataBMDMACmdReadB(PAHCIATACONTROLLER pCtl, uint32_t addr)
4364{
4365 uint32_t val = pCtl->BmDma.u8Cmd;
4366 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
4367 return val;
4368}
4369
4370
4371static void ataBMDMACmdWriteB(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t val)
4372{
4373 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
4374 if (!(val & BM_CMD_START))
4375 {
4376 pCtl->BmDma.u8Status &= ~BM_STATUS_DMAING;
4377 pCtl->BmDma.u8Cmd = val & (BM_CMD_START | BM_CMD_WRITE);
4378 }
4379 else
4380 {
4381#ifdef IN_RING3
4382 /* Check whether the guest OS wants to change DMA direction in
4383 * mid-flight. Not allowed, according to the AHCI specs. */
4384 Assert(!(pCtl->BmDma.u8Status & BM_STATUS_DMAING) || !((val ^ pCtl->BmDma.u8Cmd) & 0x04));
4385 pCtl->BmDma.u8Status |= BM_STATUS_DMAING;
4386 pCtl->BmDma.u8Cmd = val & (BM_CMD_START | BM_CMD_WRITE);
4387
4388 /* Do not continue DMA transfers while the RESET line is asserted. */
4389 if (pCtl->fReset)
4390 {
4391 Log2(("%s: Ctl: suppressed continuing DMA transfer as RESET is active\n", __FUNCTION__));
4392 return;
4393 }
4394
4395 /* Do not start DMA transfers if there's a PIO transfer going on. */
4396 if (!pCtl->aIfs[pCtl->iSelectedIf].fDMA)
4397 return;
4398
4399 if (pCtl->aIfs[pCtl->iAIOIf].uATARegStatus & ATA_STAT_DRQ)
4400 {
4401 Log2(("%s: Ctl: message to async I/O thread, continuing DMA transfer\n", __FUNCTION__));
4402 ataAsyncIOPutRequest(pCtl, &ataDMARequest);
4403 }
4404#else /* !IN_RING3 */
4405 AssertMsgFailed(("DMA START handling is too complicated for GC\n"));
4406#endif /* IN_RING3 */
4407 }
4408}
4409
4410static uint32_t ataBMDMAStatusReadB(PAHCIATACONTROLLER pCtl, uint32_t addr)
4411{
4412 uint32_t val = pCtl->BmDma.u8Status;
4413 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
4414 return val;
4415}
4416
4417static void ataBMDMAStatusWriteB(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t val)
4418{
4419 Log2(("%s: addr=%#06x val=%#04x\n", __FUNCTION__, addr, val));
4420 pCtl->BmDma.u8Status = (val & (BM_STATUS_D0DMA | BM_STATUS_D1DMA))
4421 | (pCtl->BmDma.u8Status & BM_STATUS_DMAING)
4422 | (pCtl->BmDma.u8Status & ~val & (BM_STATUS_ERROR | BM_STATUS_INT));
4423}
4424
4425static uint32_t ataBMDMAAddrReadL(PAHCIATACONTROLLER pCtl, uint32_t addr)
4426{
4427 uint32_t val = (uint32_t)pCtl->BmDma.pvAddr;
4428 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
4429 return val;
4430}
4431
4432static void ataBMDMAAddrWriteL(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t val)
4433{
4434 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
4435 pCtl->BmDma.pvAddr = val & ~3;
4436}
4437
4438static void ataBMDMAAddrWriteLowWord(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t val)
4439{
4440 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
4441 pCtl->BmDma.pvAddr = (pCtl->BmDma.pvAddr & 0xFFFF0000) | RT_LOWORD(val & ~3);
4442
4443}
4444
4445static void ataBMDMAAddrWriteHighWord(PAHCIATACONTROLLER pCtl, uint32_t addr, uint32_t val)
4446{
4447 Log2(("%s: addr=%#06x val=%#010x\n", __FUNCTION__, addr, val));
4448 pCtl->BmDma.pvAddr = (RT_LOWORD(val) << 16) | RT_LOWORD(pCtl->BmDma.pvAddr);
4449}
4450
4451#define VAL(port, size) ( ((port) & 7) | ((size) << 3) )
4452
4453/**
4454 * Port I/O Handler for bus master DMA IN operations.
4455 * @see FNIOMIOPORTIN for details.
4456 */
4457int ataControllerBMDMAIOPortRead(PAHCIATACONTROLLER pCtl, RTIOPORT Port, uint32_t *pu32, unsigned cb)
4458{
4459 int rc;
4460
4461 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_READ);
4462 if (rc != VINF_SUCCESS)
4463 return rc;
4464 switch (VAL(Port, cb))
4465 {
4466 case VAL(0, 1): *pu32 = ataBMDMACmdReadB(pCtl, Port); break;
4467 case VAL(0, 2): *pu32 = ataBMDMACmdReadB(pCtl, Port); break;
4468 case VAL(2, 1): *pu32 = ataBMDMAStatusReadB(pCtl, Port); break;
4469 case VAL(2, 2): *pu32 = ataBMDMAStatusReadB(pCtl, Port); break;
4470 case VAL(4, 4): *pu32 = ataBMDMAAddrReadL(pCtl, Port); break;
4471 default:
4472 AssertMsgFailed(("%s: Unsupported read from port %x size=%d\n", __FUNCTION__, Port, cb));
4473 PDMCritSectLeave(&pCtl->lock);
4474 return VERR_IOM_IOPORT_UNUSED;
4475 }
4476 PDMCritSectLeave(&pCtl->lock);
4477 return rc;
4478}
4479
4480/**
4481 * Port I/O Handler for bus master DMA OUT operations.
4482 * @see FNIOMIOPORTOUT for details.
4483 */
4484int ataControllerBMDMAIOPortWrite(PAHCIATACONTROLLER pCtl, RTIOPORT Port, uint32_t u32, unsigned cb)
4485{
4486 int rc;
4487
4488 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_WRITE);
4489 if (rc != VINF_SUCCESS)
4490 return rc;
4491 switch (VAL(Port, cb))
4492 {
4493 case VAL(0, 1):
4494#ifndef IN_RING3
4495 if (u32 & BM_CMD_START)
4496 {
4497 rc = VINF_IOM_HC_IOPORT_WRITE;
4498 break;
4499 }
4500#endif /* !IN_RING3 */
4501 ataBMDMACmdWriteB(pCtl, Port, u32);
4502 break;
4503 case VAL(2, 1): ataBMDMAStatusWriteB(pCtl, Port, u32); break;
4504 case VAL(4, 4): ataBMDMAAddrWriteL(pCtl, Port, u32); break;
4505 case VAL(4, 2): ataBMDMAAddrWriteLowWord(pCtl, Port, u32); break;
4506 case VAL(6, 2): ataBMDMAAddrWriteHighWord(pCtl, Port, u32); break;
4507 default: AssertMsgFailed(("%s: Unsupported write to port %x size=%d val=%x\n", __FUNCTION__, Port, cb, u32)); break;
4508 }
4509 PDMCritSectLeave(&pCtl->lock);
4510 return rc;
4511}
4512
4513#undef VAL
4514
4515
4516#ifdef IN_RING3
4517#if 0
4518
4519/**
4520 * Callback function for mapping an PCI I/O region.
4521 *
4522 * @return VBox status code.
4523 * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
4524 * @param iRegion The region number.
4525 * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
4526 * I/O port, else it's a physical address.
4527 * This address is *NOT* relative to pci_mem_base like earlier!
4528 * @param enmType One of the PCI_ADDRESS_SPACE_* values.
4529 */
4530static DECLCALLBACK(int) ataBMDMAIORangeMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
4531{
4532 PCIATAState *pThis = PCIDEV_2_PCIATASTATE(pPciDev);
4533 int rc = VINF_SUCCESS;
4534 Assert(enmType == PCI_ADDRESS_SPACE_IO);
4535 Assert(iRegion == 4);
4536 AssertMsg(RT_ALIGN(GCPhysAddress, 8) == GCPhysAddress, ("Expected 8 byte alignment. GCPhysAddress=%#x\n", GCPhysAddress));
4537
4538 /* Register the port range. */
4539 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)
4540 {
4541 int rc2 = PDMDevHlpIOPortRegister(pPciDev->pDevIns, (RTIOPORT)GCPhysAddress + i * 8, 8,
4542 (RTHCPTR)i, ataBMDMAIOPortWrite, ataBMDMAIOPortRead, NULL, NULL, "ATA Bus Master DMA");
4543 AssertRC(rc2);
4544 if (rc2 < rc)
4545 rc = rc2;
4546
4547 if (pThis->fGCEnabled)
4548 {
4549 rc2 = PDMDevHlpIOPortRegisterGC(pPciDev->pDevIns, (RTIOPORT)GCPhysAddress + i * 8, 8,
4550 (RTGCPTR)i, "ataBMDMAIOPortWrite", "ataBMDMAIOPortRead", NULL, NULL, "ATA Bus Master DMA");
4551 AssertRC(rc2);
4552 if (rc2 < rc)
4553 rc = rc2;
4554 }
4555 if (pThis->fR0Enabled)
4556 {
4557 rc2 = PDMDevHlpIOPortRegisterR0(pPciDev->pDevIns, (RTIOPORT)GCPhysAddress + i * 8, 8,
4558 (RTR0PTR)i, "ataBMDMAIOPortWrite", "ataBMDMAIOPortRead", NULL, NULL, "ATA Bus Master DMA");
4559 AssertRC(rc2);
4560 if (rc2 < rc)
4561 rc = rc2;
4562 }
4563 }
4564 return rc;
4565}
4566#endif
4567
4568/**
4569 * Reset the controller to an initial state.
4570 *
4571 * @returns VBox status.
4572 * @param pDevIns The device instance data.
4573 */
4574void ataControllerReset(PAHCIATACONTROLLER pCtl)
4575{
4576 pCtl->iSelectedIf = 0;
4577 pCtl->iAIOIf = 0;
4578 pCtl->BmDma.u8Cmd = 0;
4579 /* Report that both drives present on the bus are in DMA mode. This
4580 * pretends that there is a BIOS that has set it up. Normal reset
4581 * default is 0x00. */
4582 pCtl->BmDma.u8Status = (pCtl->aIfs[0].pDrvBase != NULL ? BM_STATUS_D0DMA : 0)
4583 | (pCtl->aIfs[1].pDrvBase != NULL ? BM_STATUS_D1DMA : 0);
4584 pCtl->BmDma.pvAddr = 0;
4585
4586 pCtl->fReset = true;
4587 pCtl->fRedo = false;
4588 pCtl->fRedoIdle = false;
4589 ataAsyncIOClearRequests(pCtl);
4590 Log2(("%s: Ctl: message to async I/O thread, reset controller\n", __FUNCTION__));
4591 ataAsyncIOPutRequest(pCtl, &ataResetARequest);
4592 ataAsyncIOPutRequest(pCtl, &ataResetCRequest);
4593 if (!ataWaitForAsyncIOIsIdle(pCtl, 30000))
4594 AssertReleaseMsgFailed(("Async I/O thread busy after reset\n"));
4595
4596 for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
4597 ataResetDevice(&pCtl->aIfs[i]);
4598}
4599
4600#if 0
4601/* -=-=-=-=-=- AHCIATADevState::IBase -=-=-=-=-=- */
4602
4603/**
4604 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
4605 */
4606static DECLCALLBACK(void *) ataQueryInterface(PPDMIBASE pInterface, const char *pszIID)
4607{
4608 ATADevState *pIf = PDMIBASE_2_ATASTATE(pInterface);
4609 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pIf->IBase);
4610 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBLOCKPORT, &pIf->IPort);
4611 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pIf->IMountNotify);
4612 return NULL;
4613}
4614#endif
4615#endif /* IN_RING3 */
4616
4617
4618/* -=-=-=-=-=- Wrappers -=-=-=-=-=- */
4619
4620/**
4621 * Port I/O Handler for primary port range OUT operations.
4622 * @see FNIOMIOPORTOUT for details.
4623 */
4624int ataControllerIOPortWrite1(PAHCIATACONTROLLER pCtl, RTIOPORT Port, uint32_t u32, unsigned cb)
4625{
4626 int rc = VINF_SUCCESS;
4627
4628 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_WRITE);
4629 if (rc != VINF_SUCCESS)
4630 return rc;
4631 if (cb == 1)
4632 rc = ataIOPortWriteU8(pCtl, Port, u32);
4633 else if (Port == pCtl->IOPortBase1)
4634 {
4635 Assert(cb == 2 || cb == 4);
4636 rc = ataDataWrite(pCtl, Port, cb, (const uint8_t *)&u32);
4637 }
4638 else
4639 AssertMsgFailed(("ataIOPortWrite1: unsupported write to port %x val=%x size=%d\n", Port, u32, cb));
4640 PDMCritSectLeave(&pCtl->lock);
4641 return rc;
4642}
4643
4644
4645/**
4646 * Port I/O Handler for primary port range IN operations.
4647 * @see FNIOMIOPORTIN for details.
4648 */
4649int ataControllerIOPortRead1(PAHCIATACONTROLLER pCtl, RTIOPORT Port, uint32_t *pu32, unsigned cb)
4650{
4651 int rc = VINF_SUCCESS;
4652
4653 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_READ);
4654 if (rc != VINF_SUCCESS)
4655 return rc;
4656 if (cb == 1)
4657 {
4658 rc = ataIOPortReadU8(pCtl, Port, pu32);
4659 }
4660 else if (Port == pCtl->IOPortBase1)
4661 {
4662 Assert(cb == 2 || cb == 4);
4663 rc = ataDataRead(pCtl, Port, cb, (uint8_t *)pu32);
4664 if (cb == 2)
4665 *pu32 &= 0xffff;
4666 }
4667 else
4668 {
4669 AssertMsgFailed(("ataIOPortRead1: unsupported read from port %x size=%d\n", Port, cb));
4670 rc = VERR_IOM_IOPORT_UNUSED;
4671 }
4672 PDMCritSectLeave(&pCtl->lock);
4673 return rc;
4674}
4675
4676#ifndef IN_RING0 /** @todo do this in ring-0 as well. */
4677/**
4678 * Port I/O Handler for primary port range IN string operations.
4679 * @see FNIOMIOPORTINSTRING for details.
4680 */
4681int ataControllerIOPortReadStr1(PAHCIATACONTROLLER pCtl, RTIOPORT Port, RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfer, unsigned cb)
4682{
4683 int rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_READ);
4684 if (rc != VINF_SUCCESS)
4685 return rc;
4686 if (Port == pCtl->IOPortBase1)
4687 {
4688 uint32_t cTransAvailable, cTransfer = *pcTransfer, cbTransfer;
4689 RTGCPTR GCDst = *pGCPtrDst;
4690 AHCIATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];
4691 Assert(cb == 2 || cb == 4);
4692
4693 cTransAvailable = (s->iIOBufferPIODataEnd - s->iIOBufferPIODataStart) / cb;
4694#ifndef IN_RING3
4695 /* Deal with the unlikely case where no data (or not enough for the read length operation) is available; go back to ring 3. */
4696 if (!cTransAvailable)
4697 {
4698 PDMCritSectLeave(&pCtl->lock);
4699 return VINF_IOM_HC_IOPORT_READ;
4700 }
4701 /* The last transfer unit cannot be handled in GC, as it involves thread communication. */
4702 cTransAvailable--;
4703#endif /* !IN_RING3 */
4704 /* Do not handle the dummy transfer stuff here, leave it to the single-word transfers.
4705 * They are not performance-critical and generally shouldn't occur at all. */
4706 if (cTransAvailable > cTransfer)
4707 cTransAvailable = cTransfer;
4708 cbTransfer = cTransAvailable * cb;
4709
4710 PPDMDEVINS pDevIns = pCtl->CTX_SUFF(pDevIns);
4711 rc = PGMPhysSimpleDirtyWriteGCPtr(PDMDevHlpGetVMCPU(pDevIns), GCDst, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart, cbTransfer);
4712#ifndef IN_RING3
4713 /* Paranoia. */
4714 if (RT_FAILURE(rc))
4715 {
4716 PDMCritSectLeave(&pCtl->lock);
4717 AssertFailed();
4718 return VINF_IOM_HC_IOPORT_READ;
4719 }
4720#else
4721 Assert(rc == VINF_SUCCESS);
4722#endif
4723
4724 if (cbTransfer)
4725 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cbTransfer, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart));
4726 s->iIOBufferPIODataStart += cbTransfer;
4727 *pGCPtrDst = (RTGCPTR)((RTGCUINTPTR)GCDst + cbTransfer);
4728 *pcTransfer = cTransfer - cTransAvailable;
4729#ifdef IN_RING3
4730 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)
4731 ataPIOTransferFinish(pCtl, s);
4732#endif /* IN_RING3 */
4733 }
4734 PDMCritSectLeave(&pCtl->lock);
4735 return rc;
4736}
4737
4738
4739/**
4740 * Port I/O Handler for primary port range OUT string operations.
4741 * @see FNIOMIOPORTOUTSTRING for details.
4742 */
4743int ataControllerIOPortWriteStr1(PAHCIATACONTROLLER pCtl, RTIOPORT Port, RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfer, unsigned cb)
4744{
4745 int rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_WRITE);
4746 if (rc != VINF_SUCCESS)
4747 return rc;
4748 if (Port == pCtl->IOPortBase1)
4749 {
4750 uint32_t cTransAvailable, cTransfer = *pcTransfer, cbTransfer;
4751 RTGCPTR GCSrc = *pGCPtrSrc;
4752 AHCIATADevState *s = &pCtl->aIfs[pCtl->iSelectedIf];
4753 Assert(cb == 2 || cb == 4);
4754
4755 cTransAvailable = (s->iIOBufferPIODataEnd - s->iIOBufferPIODataStart) / cb;
4756#ifndef IN_RING3
4757 /* Deal with the unlikely case where no data (or not enough for the read length operation) is available; go back to ring 3. */
4758 if (!cTransAvailable)
4759 {
4760 PDMCritSectLeave(&pCtl->lock);
4761 return VINF_IOM_HC_IOPORT_WRITE;
4762 }
4763 /* The last transfer unit cannot be handled in GC, as it involves thread communication. */
4764 cTransAvailable--;
4765#endif /* !IN_RING3 */
4766 /* Do not handle the dummy transfer stuff here, leave it to the single-word transfers.
4767 * They are not performance-critical and generally shouldn't occur at all. */
4768 if (cTransAvailable > cTransfer)
4769 cTransAvailable = cTransfer;
4770 cbTransfer = cTransAvailable * cb;
4771
4772 PPDMDEVINS pDevIns = pCtl->CTX_SUFF(pDevIns);
4773 rc = PGMPhysSimpleReadGCPtr(PDMDevHlpGetVMCPU(pDevIns), s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart, GCSrc, cbTransfer);
4774#ifndef IN_RING3
4775 /* Paranoia. */
4776 if (RT_FAILURE(rc))
4777 {
4778 PDMCritSectLeave(&pCtl->lock);
4779 AssertFailed();
4780 return VINF_IOM_HC_IOPORT_WRITE;
4781 }
4782#else
4783 Assert(rc == VINF_SUCCESS);
4784#endif
4785
4786 if (cbTransfer)
4787 Log3(("%s: addr=%#x val=%.*Rhxs\n", __FUNCTION__, Port, cbTransfer, s->CTX_SUFF(pbIOBuffer) + s->iIOBufferPIODataStart));
4788 s->iIOBufferPIODataStart += cbTransfer;
4789 *pGCPtrSrc = (RTGCPTR)((RTGCUINTPTR)GCSrc + cbTransfer);
4790 *pcTransfer = cTransfer - cTransAvailable;
4791#ifdef IN_RING3
4792 if (s->iIOBufferPIODataStart >= s->iIOBufferPIODataEnd)
4793 ataPIOTransferFinish(pCtl, s);
4794#endif /* IN_RING3 */
4795 }
4796 PDMCritSectLeave(&pCtl->lock);
4797 return rc;
4798}
4799#endif /* !IN_RING0 */
4800
4801/**
4802 * Port I/O Handler for secondary port range OUT operations.
4803 * @see FNIOMIOPORTOUT for details.
4804 */
4805int ataControllerIOPortWrite2(PAHCIATACONTROLLER pCtl, RTIOPORT Port, uint32_t u32, unsigned cb)
4806{
4807 int rc;
4808
4809 if (cb != 1)
4810 return VINF_SUCCESS;
4811 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_WRITE);
4812 if (rc != VINF_SUCCESS)
4813 return rc;
4814 rc = ataControlWrite(pCtl, Port, u32);
4815 PDMCritSectLeave(&pCtl->lock);
4816 return rc;
4817}
4818
4819
4820/**
4821 * Port I/O Handler for secondary port range IN operations.
4822 * @see FNIOMIOPORTIN for details.
4823 */
4824int ataControllerIOPortRead2(PAHCIATACONTROLLER pCtl, RTIOPORT Port, uint32_t *pu32, unsigned cb)
4825{
4826 int rc;
4827
4828 if (cb != 1)
4829 return VERR_IOM_IOPORT_UNUSED;
4830
4831 rc = PDMCritSectEnter(&pCtl->lock, VINF_IOM_HC_IOPORT_READ);
4832 if (rc != VINF_SUCCESS)
4833 return rc;
4834 *pu32 = ataStatusRead(pCtl, Port);
4835 PDMCritSectLeave(&pCtl->lock);
4836 return VINF_SUCCESS;
4837}
4838
4839#ifdef IN_RING3
4840
4841/**
4842 * Waits for all async I/O threads to complete whatever they
4843 * are doing at the moment.
4844 *
4845 * @returns true on success.
4846 * @returns false when one or more threads is still processing.
4847 * @param pThis Pointer to the instance data.
4848 * @param cMillies How long to wait (total).
4849 */
4850static bool ataWaitForAllAsyncIOIsIdle(PAHCIATACONTROLLER pCtl, RTMSINTERVAL cMillies)
4851{
4852 uint64_t u64Start;
4853 PPDMDEVINS pDevIns = pCtl->CTXALLSUFF(pDevIns);
4854 bool fAllIdle = false;
4855
4856 /*
4857 * Wait for any pending async operation to finish
4858 */
4859 u64Start = RTTimeMilliTS();
4860 for (;;)
4861 {
4862 /* Check all async I/O threads. */
4863 fAllIdle = true;
4864
4865 fAllIdle &= ataAsyncIOIsIdle(pCtl, false);
4866 if (!fAllIdle)
4867 break;
4868
4869 if ( fAllIdle
4870 || RTTimeMilliTS() - u64Start >= cMillies)
4871 break;
4872
4873 /* Sleep for a bit. */
4874 RTThreadSleep(100);
4875 }
4876
4877 if (!fAllIdle)
4878 LogRel(("AHCI ATA: Ctl is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",
4879 pCtl->iSelectedIf, pCtl->iAIOIf,
4880 pCtl->aIfs[0].uATARegCommand, pCtl->aIfs[1].uATARegCommand));
4881
4882 return fAllIdle;
4883}
4884
4885
4886DECLINLINE(void) ataRelocBuffer(PPDMDEVINS pDevIns, AHCIATADevState *s)
4887{
4888 if (s->pbIOBufferR3)
4889 s->pbIOBufferRC = MMHyperR3ToRC(PDMDevHlpGetVM(pDevIns), s->pbIOBufferR3);
4890}
4891
4892
4893/**
4894 * @copydoc FNPDMDEVRELOCATE
4895 */
4896void ataControllerRelocate(PAHCIATACONTROLLER pCtl, RTGCINTPTR offDelta)
4897{
4898 PPDMDEVINS pDevIns = pCtl->CTXALLSUFF(pDevIns);
4899
4900 pCtl->pDevInsRC += offDelta;
4901 pCtl->aIfs[0].pDevInsRC += offDelta;
4902 pCtl->aIfs[0].pControllerRC += offDelta;
4903 ataRelocBuffer(pDevIns, &pCtl->aIfs[0]);
4904 pCtl->aIfs[1].pDevInsRC += offDelta;
4905 pCtl->aIfs[1].pControllerRC += offDelta;
4906 ataRelocBuffer(pDevIns, &pCtl->aIfs[1]);
4907}
4908
4909
4910/**
4911 * Destroy a controller instance.
4912 *
4913 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
4914 * resources can be freed correctly.
4915 *
4916 * @param pCtl The controller instance.
4917 */
4918int ataControllerDestroy(PAHCIATACONTROLLER pCtl)
4919{
4920 int rc;
4921
4922 Log(("%s:\n", __FUNCTION__));
4923
4924 /*
4925 * Terminate the async helper thread and wait for it to finish up.
4926 */
4927 if (pCtl->AsyncIOThread != NIL_RTTHREAD)
4928 {
4929 ASMAtomicWriteU32(&pCtl->fShutdown, true);
4930 rc = RTSemEventSignal(pCtl->AsyncIOSem);
4931 AssertRC(rc);
4932 rc = RTSemEventSignal(pCtl->SuspendIOSem);
4933 AssertRC(rc);
4934
4935 rc = RTThreadWait(pCtl->AsyncIOThread, 30000 /* 30 s*/, NULL);
4936 if (RT_SUCCESS(rc))
4937 pCtl->AsyncIOThread = NIL_RTTHREAD;
4938 else
4939 LogRel(("PIIX3 ATA Dtor: Ctl/irq=%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x rc=%Rrc\n",
4940 pCtl->irq, pCtl->iSelectedIf, pCtl->iAIOIf,
4941 pCtl->aIfs[0].uATARegCommand, pCtl->aIfs[1].uATARegCommand, rc));
4942 }
4943
4944 /*
4945 * Now the request mutexes are no longer needed. Free resources.
4946 */
4947 if (pCtl->AsyncIORequestMutex != NIL_RTSEMMUTEX)
4948 {
4949 RTSemMutexDestroy(pCtl->AsyncIORequestMutex);
4950 pCtl->AsyncIORequestMutex = NIL_RTSEMMUTEX;
4951 }
4952 if (pCtl->AsyncIOSem != NIL_RTSEMEVENT)
4953 {
4954 RTSemEventDestroy(pCtl->AsyncIOSem);
4955 pCtl->AsyncIOSem = NIL_RTSEMEVENT;
4956 }
4957 if (pCtl->SuspendIOSem != NIL_RTSEMEVENT)
4958 {
4959 RTSemEventDestroy(pCtl->SuspendIOSem);
4960 pCtl->SuspendIOSem = NIL_RTSEMEVENT;
4961 }
4962
4963 /* try one final time */
4964 if (pCtl->AsyncIOThread != NIL_RTTHREAD)
4965 {
4966 rc = RTThreadWait(pCtl->AsyncIOThread, 1 /*ms*/, NULL);
4967 if (RT_SUCCESS(rc))
4968 {
4969 pCtl->AsyncIOThread = NIL_RTTHREAD;
4970 LogRel(("AHCI ATA Dtor: Ctl/irq=%u actually completed.\n", pCtl->irq));
4971 }
4972 }
4973
4974 return VINF_SUCCESS;
4975}
4976
4977/**
4978 * Detach notification.
4979 *
4980 * The DVD drive has been unplugged.
4981 *
4982 * @param pDevIns The device instance.
4983 * @param fMaster True if the master is detached
4984 * false for the slave
4985 */
4986void ataControllerDetach(PAHCIATACONTROLLER pCtl, bool fMaster)
4987{
4988 AHCIATADevState *pIf;
4989
4990 /*
4991 * Locate the controller and stuff.
4992 */
4993 pIf = &pCtl->aIfs[fMaster ? 0 : 1];
4994
4995 /*
4996 * Zero some important members.
4997 */
4998 pIf->pDrvBase = NULL;
4999 pIf->pDrvBlock = NULL;
5000 pIf->pDrvBlockBios = NULL;
5001 pIf->pDrvMount = NULL;
5002}
5003
5004/**
5005 * Configure a LUN.
5006 *
5007 * @returns VBox status code.
5008 * @param pDevIns The device instance.
5009 * @param pIf The ATA unit state.
5010 */
5011static int ataConfigLun(PPDMDEVINS pDevIns, AHCIATADevState *pIf)
5012{
5013 int rc;
5014 PDMBLOCKTYPE enmType;
5015
5016 /*
5017 * Query Block, Bios and Mount interfaces.
5018 */
5019 pIf->pDrvBlock = PDMIBASE_QUERY_INTERFACE(pIf->pDrvBase, PDMIBLOCK);
5020 if (!pIf->pDrvBlock)
5021 {
5022 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pIf->iLUN));
5023 return VERR_PDM_MISSING_INTERFACE;
5024 }
5025
5026 /** @todo implement the BIOS invisible code path. */
5027 pIf->pDrvBlockBios = PDMIBASE_QUERY_INTERFACE(pIf->pDrvBase, PDMIBLOCKBIOS);
5028 if (!pIf->pDrvBlockBios)
5029 {
5030 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block BIOS interface!\n", pIf->iLUN));
5031 return VERR_PDM_MISSING_INTERFACE;
5032 }
5033 pIf->pDrvMount = PDMIBASE_QUERY_INTERFACE(pIf->pDrvBase, PDMIMOUNT);
5034
5035 /*
5036 * Validate type.
5037 */
5038 enmType = pIf->pDrvBlock->pfnGetType(pIf->pDrvBlock);
5039 if ( enmType != PDMBLOCKTYPE_CDROM
5040 && enmType != PDMBLOCKTYPE_DVD
5041 && enmType != PDMBLOCKTYPE_HARD_DISK)
5042 {
5043 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd-rom. enmType=%d\n", pIf->iLUN, enmType));
5044 return VERR_PDM_UNSUPPORTED_BLOCK_TYPE;
5045 }
5046 if ( ( enmType == PDMBLOCKTYPE_DVD
5047 || enmType == PDMBLOCKTYPE_CDROM)
5048 && !pIf->pDrvMount)
5049 {
5050 AssertMsgFailed(("Internal error: cdrom without a mountable interface, WTF???!\n"));
5051 return VERR_INTERNAL_ERROR;
5052 }
5053 pIf->fATAPI = enmType == PDMBLOCKTYPE_DVD || enmType == PDMBLOCKTYPE_CDROM;
5054 pIf->fATAPIPassthrough = pIf->fATAPI ? (pIf->pDrvBlock->pfnSendCmd != NULL) : false;
5055
5056 /*
5057 * Allocate I/O buffer.
5058 */
5059 PVM pVM = PDMDevHlpGetVM(pDevIns);
5060 if (pIf->cbIOBuffer)
5061 {
5062 /* Buffer is (probably) already allocated. Validate the fields,
5063 * because memory corruption can also overwrite pIf->cbIOBuffer. */
5064 if (pIf->fATAPI)
5065 AssertRelease(pIf->cbIOBuffer == _128K);
5066 else
5067 AssertRelease(pIf->cbIOBuffer == ATA_MAX_MULT_SECTORS * 512);
5068 Assert(pIf->pbIOBufferR3);
5069 Assert(pIf->pbIOBufferR0 == MMHyperR3ToR0(pVM, pIf->pbIOBufferR3));
5070 Assert(pIf->pbIOBufferRC == MMHyperR3ToRC(pVM, pIf->pbIOBufferR3));
5071 }
5072 else
5073 {
5074 if (pIf->fATAPI)
5075 pIf->cbIOBuffer = _128K;
5076 else
5077 pIf->cbIOBuffer = ATA_MAX_MULT_SECTORS * 512;
5078 Assert(!pIf->pbIOBufferR3);
5079 rc = MMR3HyperAllocOnceNoRel(pVM, pIf->cbIOBuffer, 0, MM_TAG_PDM_DEVICE_USER, (void **)&pIf->pbIOBufferR3);
5080 if (RT_FAILURE(rc))
5081 return VERR_NO_MEMORY;
5082 pIf->pbIOBufferR0 = MMHyperR3ToR0(pVM, pIf->pbIOBufferR3);
5083 pIf->pbIOBufferRC = MMHyperR3ToRC(pVM, pIf->pbIOBufferR3);
5084 }
5085
5086 /*
5087 * Init geometry (only for non-CD/DVD media).
5088 */
5089 if (pIf->fATAPI)
5090 {
5091 pIf->cTotalSectors = pIf->pDrvBlock->pfnGetSize(pIf->pDrvBlock) / 2048;
5092 pIf->PCHSGeometry.cCylinders = 0; /* dummy */
5093 pIf->PCHSGeometry.cHeads = 0; /* dummy */
5094 pIf->PCHSGeometry.cSectors = 0; /* dummy */
5095 LogRel(("AHCI ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled")));
5096 }
5097 else
5098 {
5099 pIf->cTotalSectors = pIf->pDrvBlock->pfnGetSize(pIf->pDrvBlock) / 512;
5100 rc = pIf->pDrvBlockBios->pfnGetPCHSGeometry(pIf->pDrvBlockBios,
5101 &pIf->PCHSGeometry);
5102 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED)
5103 {
5104 pIf->PCHSGeometry.cCylinders = 0;
5105 pIf->PCHSGeometry.cHeads = 16; /*??*/
5106 pIf->PCHSGeometry.cSectors = 63; /*??*/
5107 }
5108 else if (rc == VERR_PDM_GEOMETRY_NOT_SET)
5109 {
5110 pIf->PCHSGeometry.cCylinders = 0; /* autodetect marker */
5111 rc = VINF_SUCCESS;
5112 }
5113 AssertRC(rc);
5114
5115 if ( pIf->PCHSGeometry.cCylinders == 0
5116 || pIf->PCHSGeometry.cHeads == 0
5117 || pIf->PCHSGeometry.cSectors == 0
5118 )
5119 {
5120 uint64_t cCylinders = pIf->cTotalSectors / (16 * 63);
5121 pIf->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1);
5122 pIf->PCHSGeometry.cHeads = 16;
5123 pIf->PCHSGeometry.cSectors = 63;
5124 /* Set the disk geometry information. */
5125 rc = pIf->pDrvBlockBios->pfnSetPCHSGeometry(pIf->pDrvBlockBios,
5126 &pIf->PCHSGeometry);
5127 }
5128 LogRel(("AHCI ATA: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n", pIf->iLUN, pIf->PCHSGeometry.cCylinders, pIf->PCHSGeometry.cHeads, pIf->PCHSGeometry.cSectors, pIf->cTotalSectors));
5129 }
5130 return VINF_SUCCESS;
5131}
5132
5133/**
5134 * Attach command.
5135 *
5136 * This is called when we change block driver for the DVD drive.
5137 *
5138 * @returns VBox status code.
5139 * @param pDevIns The device instance.
5140 * @param iLUN The logical unit which is being detached.
5141 */
5142int ataControllerAttach(PAHCIATACONTROLLER pCtl, PPDMIBASE pDrvBase, bool fMaster)
5143{
5144 AHCIATADevState *pIf;
5145 int rc = VINF_SUCCESS;
5146
5147 /*
5148 * Locate the controller and stuff.
5149 */
5150 pIf = &pCtl->aIfs[fMaster ? 0 : 1];
5151
5152 /* the usual paranoia */
5153 AssertRelease(!pIf->pDrvBase);
5154 AssertRelease(!pIf->pDrvBlock);
5155 Assert(ATADEVSTATE_2_CONTROLLER(pIf) == pCtl);
5156
5157 /*
5158 * Try attach the block device and get the interfaces,
5159 * required as well as optional.
5160 */
5161
5162 pIf->pDrvBase = pDrvBase;
5163 if (pDrvBase)
5164 {
5165 rc = ataConfigLun(pCtl->pDevInsR3, pIf);
5166 AssertRC(rc);
5167
5168 if (RT_FAILURE(rc))
5169 {
5170 pIf->pDrvBase = NULL;
5171 pIf->pDrvBlock = NULL;
5172 }
5173 }
5174
5175 return rc;
5176}
5177
5178
5179/**
5180 * Resume notification.
5181 *
5182 * @returns VBox status.
5183 * @param pDevIns The device instance data.
5184 */
5185void ataControllerResume(PAHCIATACONTROLLER pCtl)
5186{
5187 int rc;
5188
5189 Log(("%s:\n", __FUNCTION__));
5190 if (pCtl->fRedo && pCtl->fRedoIdle)
5191 {
5192 rc = RTSemEventSignal(pCtl->SuspendIOSem);
5193 AssertRC(rc);
5194 }
5195
5196 return;
5197}
5198
5199
5200/**
5201 * Tests if the controller is idle, leaving the PDM notifications on if busy.
5202 *
5203 * @returns true if idle, false if idle.
5204 * @param pCtl the controller instance.
5205 */
5206bool ataControllerIsIdle(PAHCIATACONTROLLER pCtl)
5207{
5208 ASMAtomicWriteBool(&pCtl->fSignalIdle, true);
5209 if (ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
5210 {
5211 ASMAtomicWriteBool(&pCtl->fSignalIdle, false);
5212 return true;
5213 }
5214 return false;
5215}
5216
5217/**
5218 * Saves a state of the ATA device.
5219 *
5220 * @returns VBox status code.
5221 * @param pCtl Controller instance.
5222 * @param pSSM The handle to save the state to.
5223 */
5224int ataControllerSaveExec(PAHCIATACONTROLLER pCtl, PSSMHANDLE pSSM)
5225{
5226 SSMR3PutU32(pSSM, ATA_CTL_SAVED_STATE_VERSION);
5227 SSMR3PutU8(pSSM, pCtl->iSelectedIf);
5228 SSMR3PutU8(pSSM, pCtl->iAIOIf);
5229 SSMR3PutU8(pSSM, pCtl->uAsyncIOState);
5230 SSMR3PutBool(pSSM, pCtl->fChainedTransfer);
5231 SSMR3PutBool(pSSM, pCtl->fReset);
5232 SSMR3PutBool(pSSM, pCtl->fRedo);
5233 SSMR3PutBool(pSSM, pCtl->fRedoIdle);
5234 SSMR3PutBool(pSSM, pCtl->fRedoDMALastDesc);
5235 SSMR3PutMem(pSSM, &pCtl->BmDma, sizeof(pCtl->BmDma));
5236 SSMR3PutGCPhys32(pSSM, pCtl->pFirstDMADesc);
5237 SSMR3PutGCPhys32(pSSM, pCtl->pLastDMADesc);
5238 SSMR3PutGCPhys32(pSSM, pCtl->pRedoDMABuffer);
5239 SSMR3PutU32(pSSM, pCtl->cbRedoDMABuffer);
5240
5241 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
5242 {
5243 SSMR3PutBool(pSSM, pCtl->aIfs[j].fLBA48);
5244 SSMR3PutBool(pSSM, pCtl->aIfs[j].fATAPI);
5245 SSMR3PutBool(pSSM, pCtl->aIfs[j].fIrqPending);
5246 SSMR3PutU8(pSSM, pCtl->aIfs[j].cMultSectors);
5247 SSMR3PutU32(pSSM, pCtl->aIfs[j].PCHSGeometry.cCylinders);
5248 SSMR3PutU32(pSSM, pCtl->aIfs[j].PCHSGeometry.cHeads);
5249 SSMR3PutU32(pSSM, pCtl->aIfs[j].PCHSGeometry.cSectors);
5250 SSMR3PutU32(pSSM, pCtl->aIfs[j].cSectorsPerIRQ);
5251 SSMR3PutU64(pSSM, pCtl->aIfs[j].cTotalSectors);
5252 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegFeature);
5253 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegFeatureHOB);
5254 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegError);
5255 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegNSector);
5256 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegNSectorHOB);
5257 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegSector);
5258 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegSectorHOB);
5259 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegLCyl);
5260 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegLCylHOB);
5261 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegHCyl);
5262 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegHCylHOB);
5263 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegSelect);
5264 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegStatus);
5265 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegCommand);
5266 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATARegDevCtl);
5267 SSMR3PutU8(pSSM, pCtl->aIfs[j].uATATransferMode);
5268 SSMR3PutU8(pSSM, pCtl->aIfs[j].uTxDir);
5269 SSMR3PutU8(pSSM, pCtl->aIfs[j].iBeginTransfer);
5270 SSMR3PutU8(pSSM, pCtl->aIfs[j].iSourceSink);
5271 SSMR3PutBool(pSSM, pCtl->aIfs[j].fDMA);
5272 SSMR3PutBool(pSSM, pCtl->aIfs[j].fATAPITransfer);
5273 SSMR3PutU32(pSSM, pCtl->aIfs[j].cbTotalTransfer);
5274 SSMR3PutU32(pSSM, pCtl->aIfs[j].cbElementaryTransfer);
5275 SSMR3PutU32(pSSM, pCtl->aIfs[j].iIOBufferCur);
5276 SSMR3PutU32(pSSM, pCtl->aIfs[j].iIOBufferEnd);
5277 SSMR3PutU32(pSSM, pCtl->aIfs[j].iIOBufferPIODataStart);
5278 SSMR3PutU32(pSSM, pCtl->aIfs[j].iIOBufferPIODataEnd);
5279 SSMR3PutU32(pSSM, pCtl->aIfs[j].iATAPILBA);
5280 SSMR3PutU32(pSSM, pCtl->aIfs[j].cbATAPISector);
5281 SSMR3PutMem(pSSM, &pCtl->aIfs[j].aATAPICmd, sizeof(pCtl->aIfs[j].aATAPICmd));
5282 SSMR3PutMem(pSSM, &pCtl->aIfs[j].abATAPISense, sizeof(pCtl->aIfs[j].abATAPISense));
5283 SSMR3PutU8(pSSM, pCtl->aIfs[j].cNotifiedMediaChange);
5284 SSMR3PutU32(pSSM, pCtl->aIfs[j].MediaEventStatus);
5285
5286 PDMLED Led;
5287 memset(&Led, 0, sizeof(PDMLED));
5288 SSMR3PutMem(pSSM, &Led, sizeof(PDMLED));
5289 SSMR3PutU32(pSSM, pCtl->aIfs[j].cbIOBuffer);
5290 if (pCtl->aIfs[j].cbIOBuffer)
5291 SSMR3PutMem(pSSM, pCtl->aIfs[j].CTX_SUFF(pbIOBuffer), pCtl->aIfs[j].cbIOBuffer);
5292 else
5293 Assert(pCtl->aIfs[j].CTX_SUFF(pbIOBuffer) == NULL);
5294 }
5295
5296 return SSMR3PutU32(pSSM, ~0); /* sanity/terminator */
5297}
5298
5299
5300/**
5301 * Loads a saved ATA device state.
5302 *
5303 * @returns VBox status code.
5304 * @param pDevIns The device instance.
5305 * @param pSSM The handle to the saved state.
5306 */
5307int ataControllerLoadExec(PAHCIATACONTROLLER pCtl, PSSMHANDLE pSSM)
5308{
5309 int rc;
5310 uint32_t u32Version;
5311 uint32_t u32;
5312
5313 /* Test for correct version. */
5314 rc = SSMR3GetU32(pSSM, &u32Version);
5315 AssertRCReturn(rc, rc);
5316
5317 if ( u32Version != ATA_CTL_SAVED_STATE_VERSION
5318 && u32Version != ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE
5319 && u32Version != ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
5320 {
5321 AssertMsgFailed(("u32Version=%d\n", u32Version));
5322 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
5323 }
5324
5325 /* integrity check */
5326 if (!ataAsyncIOIsIdle(pCtl, false))
5327 {
5328 AssertMsgFailed(("Async I/O for controller is active\n"));
5329 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
5330 }
5331
5332 SSMR3GetU8(pSSM, &pCtl->iSelectedIf);
5333 SSMR3GetU8(pSSM, &pCtl->iAIOIf);
5334 SSMR3GetU8(pSSM, &pCtl->uAsyncIOState);
5335 SSMR3GetBool(pSSM, &pCtl->fChainedTransfer);
5336 SSMR3GetBool(pSSM, (bool *)&pCtl->fReset);
5337 SSMR3GetBool(pSSM, (bool *)&pCtl->fRedo);
5338 SSMR3GetBool(pSSM, (bool *)&pCtl->fRedoIdle);
5339 SSMR3GetBool(pSSM, (bool *)&pCtl->fRedoDMALastDesc);
5340 SSMR3GetMem(pSSM, &pCtl->BmDma, sizeof(pCtl->BmDma));
5341 SSMR3GetGCPhys32(pSSM, &pCtl->pFirstDMADesc);
5342 SSMR3GetGCPhys32(pSSM, &pCtl->pLastDMADesc);
5343 SSMR3GetGCPhys32(pSSM, &pCtl->pRedoDMABuffer);
5344 SSMR3GetU32(pSSM, &pCtl->cbRedoDMABuffer);
5345
5346 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
5347 {
5348 SSMR3GetBool(pSSM, &pCtl->aIfs[j].fLBA48);
5349 SSMR3GetBool(pSSM, &pCtl->aIfs[j].fATAPI);
5350 SSMR3GetBool(pSSM, &pCtl->aIfs[j].fIrqPending);
5351 SSMR3GetU8(pSSM, &pCtl->aIfs[j].cMultSectors);
5352 SSMR3GetU32(pSSM, &pCtl->aIfs[j].PCHSGeometry.cCylinders);
5353 SSMR3GetU32(pSSM, &pCtl->aIfs[j].PCHSGeometry.cHeads);
5354 SSMR3GetU32(pSSM, &pCtl->aIfs[j].PCHSGeometry.cSectors);
5355 SSMR3GetU32(pSSM, &pCtl->aIfs[j].cSectorsPerIRQ);
5356 SSMR3GetU64(pSSM, &pCtl->aIfs[j].cTotalSectors);
5357 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegFeature);
5358 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegFeatureHOB);
5359 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegError);
5360 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegNSector);
5361 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegNSectorHOB);
5362 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegSector);
5363 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegSectorHOB);
5364 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegLCyl);
5365 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegLCylHOB);
5366 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegHCyl);
5367 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegHCylHOB);
5368 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegSelect);
5369 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegStatus);
5370 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegCommand);
5371 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATARegDevCtl);
5372 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uATATransferMode);
5373 SSMR3GetU8(pSSM, &pCtl->aIfs[j].uTxDir);
5374 SSMR3GetU8(pSSM, &pCtl->aIfs[j].iBeginTransfer);
5375 SSMR3GetU8(pSSM, &pCtl->aIfs[j].iSourceSink);
5376 SSMR3GetBool(pSSM, &pCtl->aIfs[j].fDMA);
5377 SSMR3GetBool(pSSM, &pCtl->aIfs[j].fATAPITransfer);
5378 SSMR3GetU32(pSSM, &pCtl->aIfs[j].cbTotalTransfer);
5379 SSMR3GetU32(pSSM, &pCtl->aIfs[j].cbElementaryTransfer);
5380 SSMR3GetU32(pSSM, &pCtl->aIfs[j].iIOBufferCur);
5381 SSMR3GetU32(pSSM, &pCtl->aIfs[j].iIOBufferEnd);
5382 SSMR3GetU32(pSSM, &pCtl->aIfs[j].iIOBufferPIODataStart);
5383 SSMR3GetU32(pSSM, &pCtl->aIfs[j].iIOBufferPIODataEnd);
5384 SSMR3GetU32(pSSM, &pCtl->aIfs[j].iATAPILBA);
5385 SSMR3GetU32(pSSM, &pCtl->aIfs[j].cbATAPISector);
5386 SSMR3GetMem(pSSM, &pCtl->aIfs[j].aATAPICmd, sizeof(pCtl->aIfs[j].aATAPICmd));
5387 if (u32Version > ATA_CTL_SAVED_STATE_VERSION_WITHOUT_FULL_SENSE)
5388 {
5389 SSMR3GetMem(pSSM, &pCtl->aIfs[j].abATAPISense, sizeof(pCtl->aIfs[j].abATAPISense));
5390 }
5391 else
5392 {
5393 uint8_t uATAPISenseKey, uATAPIASC;
5394 memset(pCtl->aIfs[j].abATAPISense, '\0', sizeof(pCtl->aIfs[j].abATAPISense));
5395 pCtl->aIfs[j].abATAPISense[0] = 0x70 | (1 << 7);
5396 pCtl->aIfs[j].abATAPISense[7] = 10;
5397 SSMR3GetU8(pSSM, &uATAPISenseKey);
5398 SSMR3GetU8(pSSM, &uATAPIASC);
5399 pCtl->aIfs[j].abATAPISense[2] = uATAPISenseKey & 0x0f;
5400 pCtl->aIfs[j].abATAPISense[12] = uATAPIASC;
5401 }
5402 /** @todo triple-check this hack after passthrough is working */
5403 SSMR3GetU8(pSSM, &pCtl->aIfs[j].cNotifiedMediaChange);
5404 if (u32Version > ATA_CTL_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS)
5405 SSMR3GetU32(pSSM, (uint32_t*)&pCtl->aIfs[j].MediaEventStatus);
5406 else
5407 pCtl->aIfs[j].MediaEventStatus = ATA_EVENT_STATUS_UNCHANGED;
5408
5409 PDMLED Led;
5410 SSMR3GetMem(pSSM, &Led, sizeof(PDMLED));
5411 SSMR3GetU32(pSSM, &pCtl->aIfs[j].cbIOBuffer);
5412 if (pCtl->aIfs[j].cbIOBuffer)
5413 {
5414 if (pCtl->aIfs[j].CTX_SUFF(pbIOBuffer))
5415 SSMR3GetMem(pSSM, pCtl->aIfs[j].CTX_SUFF(pbIOBuffer), pCtl->aIfs[j].cbIOBuffer);
5416 else
5417 {
5418 LogRel(("AHCI ATA: No buffer for %d\n", j));
5419 if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
5420 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("No buffer for %d"), j);
5421
5422 /* skip the buffer if we're loading for the debugger / animator. */
5423 uint8_t u8Ignored;
5424 size_t cbLeft = pCtl->aIfs[j].cbIOBuffer;
5425 while (cbLeft-- > 0)
5426 SSMR3GetU8(pSSM, &u8Ignored);
5427 }
5428 }
5429 else
5430 Assert(pCtl->aIfs[j].CTX_SUFF(pbIOBuffer) == NULL);
5431 }
5432
5433 rc = SSMR3GetU32(pSSM, &u32);
5434 if (RT_FAILURE(rc))
5435 return rc;
5436 if (u32 != ~0U)
5437 {
5438 AssertMsgFailed(("u32=%#x expected ~0\n", u32));
5439 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
5440 return rc;
5441 }
5442
5443 return VINF_SUCCESS;
5444}
5445
5446int ataControllerInit(PPDMDEVINS pDevIns, PAHCIATACONTROLLER pCtl,
5447 unsigned iLUNMaster, PPDMIBASE pDrvBaseMaster, PPDMLED pLedMaster,
5448 PSTAMCOUNTER pStatBytesReadMaster, PSTAMCOUNTER pStatBytesWrittenMaster,
5449 unsigned iLUNSlave, PPDMIBASE pDrvBaseSlave, PPDMLED pLedSlave,
5450 PSTAMCOUNTER pStatBytesReadSlave, PSTAMCOUNTER pStatBytesWrittenSlave,
5451 uint32_t *pcbSSMState, const char *szName)
5452{
5453 int rc;
5454
5455 AssertMsg(pcbSSMState, ("pcbSSMState is invalid\n"));
5456
5457 pCtl->pDevInsR3 = pDevIns;
5458 pCtl->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
5459 pCtl->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
5460 pCtl->AsyncIOSem = NIL_RTSEMEVENT;
5461 pCtl->SuspendIOSem = NIL_RTSEMEVENT;
5462 pCtl->AsyncIORequestMutex = NIL_RTSEMMUTEX;
5463 pCtl->AsyncIOThread = NIL_RTTHREAD;
5464
5465 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
5466 {
5467 pCtl->aIfs[j].iLUN = j == 0 ? iLUNMaster : iLUNSlave;
5468 pCtl->aIfs[j].pDevInsR3 = pDevIns;
5469 pCtl->aIfs[j].pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
5470 pCtl->aIfs[j].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
5471 pCtl->aIfs[j].pControllerR3 = pCtl;
5472 pCtl->aIfs[j].pControllerR0 = MMHyperR3ToR0(PDMDevHlpGetVM(pDevIns), pCtl);
5473 pCtl->aIfs[j].pControllerRC = MMHyperR3ToRC(PDMDevHlpGetVM(pDevIns), pCtl);
5474 pCtl->aIfs[j].pLed = j == 0 ? pLedMaster : pLedSlave;
5475 pCtl->aIfs[j].pStatBytesRead = j == 0 ? pStatBytesReadMaster : pStatBytesReadSlave;
5476 pCtl->aIfs[j].pStatBytesWritten = j == 0 ? pStatBytesWrittenMaster : pStatBytesWrittenSlave;
5477 }
5478
5479 /* Initialize per-controller critical section */
5480 rc = PDMDevHlpCritSectInit(pDevIns, &pCtl->lock, RT_SRC_POS, "%s", szName);
5481 if (RT_FAILURE(rc))
5482 return PDMDEV_SET_ERROR(pDevIns, rc, N_("AHCI ATA: cannot initialize critical section"));
5483
5484 /*
5485 * Attach the units.
5486 */
5487 uint32_t cbTotalBuffer = 0;
5488
5489 /*
5490 * Start the worker thread.
5491 */
5492 pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
5493 rc = RTSemEventCreate(&pCtl->AsyncIOSem);
5494 AssertRCReturn(rc, rc);
5495 rc = RTSemEventCreate(&pCtl->SuspendIOSem);
5496 AssertRCReturn(rc, rc);
5497 rc = RTSemMutexCreate(&pCtl->AsyncIORequestMutex);
5498 AssertRCReturn(rc, rc);
5499 ataAsyncIOClearRequests(pCtl);
5500 rc = RTThreadCreateF(&pCtl->AsyncIOThread, ataAsyncIOLoop, (void *)pCtl, 128*1024,
5501 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "AHCI-ATA-%u", pCtl->irq);
5502 AssertRCReturn(rc, rc);
5503 Assert(pCtl->AsyncIOThread != NIL_RTTHREAD && pCtl->AsyncIOSem != NIL_RTSEMEVENT && pCtl->SuspendIOSem != NIL_RTSEMEVENT && pCtl->AsyncIORequestMutex != NIL_RTSEMMUTEX);
5504 Log(("%s: controller AIO thread id %#x; sem %p susp_sem %p mutex %p\n", __FUNCTION__, pCtl->AsyncIOThread, pCtl->AsyncIOSem, pCtl->SuspendIOSem, pCtl->AsyncIORequestMutex));
5505
5506 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
5507 {
5508 /*
5509 * Try attach the block device and get the interfaces,
5510 * required as well as optional.
5511 */
5512 AHCIATADevState *pIf = &pCtl->aIfs[j];
5513
5514 pIf->pDrvBase = (j == 0) ? pDrvBaseMaster : pDrvBaseSlave;
5515
5516#if 0
5517 rc = PDMDevHlpDriverAttach(pDevIns, pIf->iLUN, &pIf->IBase, &pIf->pDrvBase, s_apszDescs[j]);
5518 if (RT_SUCCESS(rc))
5519#endif
5520 if (pIf->pDrvBase)
5521 rc = ataConfigLun(pDevIns, pIf);
5522 else
5523 {
5524 pIf->pDrvBase = NULL;
5525 pIf->pDrvBlock = NULL;
5526 pIf->cbIOBuffer = 0;
5527 pIf->pbIOBufferR3 = NULL;
5528 pIf->pbIOBufferR0 = NIL_RTR0PTR;
5529 pIf->pbIOBufferRC = NIL_RTRCPTR;
5530 LogRel(("AHCI ATA: LUN#%d: no unit\n", pIf->iLUN));
5531 }
5532 cbTotalBuffer += pIf->cbIOBuffer;
5533 }
5534
5535 *pcbSSMState = cbTotalBuffer;
5536
5537 /*
5538 * Initialize the device state.
5539 */
5540 ataControllerReset(pCtl);
5541
5542 return VINF_SUCCESS;
5543}
5544#endif /* IN_RING3 */
5545#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