VirtualBox

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

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

AHCI: Fix wrong Led assignments

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

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