VirtualBox

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

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

Storage/DevATA+ATAController: only allow read/write commands for ATA devices

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