VirtualBox

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

Last change on this file since 26837 was 26195, checked in by vboxsync, 15 years ago

style

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

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