VirtualBox

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

Last change on this file since 23118 was 23020, checked in by vboxsync, 16 years ago

unused variables

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

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