VirtualBox

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

Last change on this file since 27653 was 27361, checked in by vboxsync, 15 years ago

Storate/ATA: implemented ATA_EVENT_STATUS_MEDIA_EJECT_REQUESTED (currently unused)

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