VirtualBox

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

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

Storage/ATAController: release log msg cosmetics

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

© 2023 Oracle
ContactPrivacy policyTerms of Use