VirtualBox

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

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

AHCI: Fix crash on reset after a snapshot was taken. The Driver needs to be updated in the ATA emulation

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