VirtualBox

source: vbox/trunk/src/VBox/Main/SATAControllerImpl.cpp@ 7554

Last change on this file since 7554 was 7457, checked in by vboxsync, 17 years ago

AHCI: add configuration options for VBoxManage and fix two mistakes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 10.9 KB
Line 
1/* $Id: SATAControllerImpl.cpp 7457 2008-03-14 12:17:16Z vboxsync $ */
2
3/** @file
4 *
5 * Implementation of ISATAController.
6 */
7
8/*
9 * Copyright (C) 2008 innotek GmbH
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20
21
22#include "SATAControllerImpl.h"
23#include "MachineImpl.h"
24#include "VirtualBoxImpl.h"
25#include "Logging.h"
26
27#include <iprt/string.h>
28#include <iprt/cpputils.h>
29#include <VBox/err.h>
30
31#include <algorithm>
32
33// defines
34/////////////////////////////////////////////////////////////////////////////
35
36// constructor / destructor
37/////////////////////////////////////////////////////////////////////////////
38
39DEFINE_EMPTY_CTOR_DTOR (SATAController)
40
41HRESULT SATAController::FinalConstruct()
42{
43 return S_OK;
44}
45
46void SATAController::FinalRelease()
47{
48 uninit();
49}
50
51// public initializer/uninitializer for internal purposes only
52/////////////////////////////////////////////////////////////////////////////
53
54/**
55 * Initializes the USB controller object.
56 *
57 * @returns COM result indicator.
58 * @param aParent Pointer to our parent object.
59 */
60HRESULT SATAController::init (Machine *aParent)
61{
62 LogFlowThisFunc (("aParent=%p\n", aParent));
63
64 ComAssertRet (aParent, E_INVALIDARG);
65
66 /* Enclose the state transition NotReady->InInit->Ready */
67 AutoInitSpan autoInitSpan (this);
68 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
69
70 unconst (mParent) = aParent;
71 /* mPeer is left null */
72
73 mData.allocate();
74
75 /* Confirm a successful initialization */
76 autoInitSpan.setSucceeded();
77
78 return S_OK;
79}
80
81
82/**
83 * Initializes the SATA controller object given another SATA controller object
84 * (a kind of copy constructor). This object shares data with
85 * the object passed as an argument.
86 *
87 * @returns COM result indicator.
88 * @param aParent Pointer to our parent object.
89 * @param aPeer The object to share.
90 *
91 * @note This object must be destroyed before the original object
92 * it shares data with is destroyed.
93 */
94HRESULT SATAController::init (Machine *aParent, SATAController *aPeer)
95{
96 LogFlowThisFunc (("aParent=%p, aPeer=%p\n", aParent, aPeer));
97
98 ComAssertRet (aParent && aPeer, E_INVALIDARG);
99
100 /* Enclose the state transition NotReady->InInit->Ready */
101 AutoInitSpan autoInitSpan (this);
102 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
103
104 unconst (mParent) = aParent;
105 unconst (mPeer) = aPeer;
106
107 AutoLock thatlock (aPeer);
108 mData.share (aPeer->mData);
109
110 /* Confirm a successful initialization */
111 autoInitSpan.setSucceeded();
112
113 return S_OK;
114}
115
116
117/**
118 * Initializes the SATA controller object given another guest object
119 * (a kind of copy constructor). This object makes a private copy of data
120 * of the original object passed as an argument.
121 */
122HRESULT SATAController::initCopy (Machine *aParent, SATAController *aPeer)
123{
124 LogFlowThisFunc (("aParent=%p, aPeer=%p\n", aParent, aPeer));
125
126 ComAssertRet (aParent && aPeer, E_INVALIDARG);
127
128 /* Enclose the state transition NotReady->InInit->Ready */
129 AutoInitSpan autoInitSpan (this);
130 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
131
132 unconst (mParent) = aParent;
133 /* mPeer is left null */
134
135 AutoLock thatlock (aPeer);
136 mData.attachCopy (aPeer->mData);
137
138 /* Confirm a successful initialization */
139 autoInitSpan.setSucceeded();
140
141 return S_OK;
142}
143
144
145/**
146 * Uninitializes the instance and sets the ready flag to FALSE.
147 * Called either from FinalRelease() or by the parent when it gets destroyed.
148 */
149void SATAController::uninit()
150{
151 LogFlowThisFunc (("\n"));
152
153 /* Enclose the state transition Ready->InUninit->NotReady */
154 AutoUninitSpan autoUninitSpan (this);
155 if (autoUninitSpan.uninitDone())
156 return;
157
158 /* uninit all filters (including those still referenced by clients) */
159 uninitDependentChildren();
160
161 mData.free();
162
163 unconst (mPeer).setNull();
164 unconst (mParent).setNull();
165}
166
167
168// ISATAController properties
169/////////////////////////////////////////////////////////////////////////////
170
171STDMETHODIMP SATAController::COMGETTER(Enabled) (BOOL *aEnabled)
172{
173 if (!aEnabled)
174 return E_POINTER;
175
176 AutoCaller autoCaller (this);
177 CheckComRCReturnRC (autoCaller.rc());
178
179 AutoReaderLock alock (this);
180
181 *aEnabled = mData->mEnabled;
182
183 return S_OK;
184}
185
186
187STDMETHODIMP SATAController::COMSETTER(Enabled) (BOOL aEnabled)
188{
189 LogFlowThisFunc (("aEnabled=%RTbool\n", aEnabled));
190
191 AutoCaller autoCaller (this);
192 CheckComRCReturnRC (autoCaller.rc());
193
194 /* the machine needs to be mutable */
195 Machine::AutoMutableStateDependency adep (mParent);
196 CheckComRCReturnRC (adep.rc());
197
198 AutoLock alock (this);
199
200 if (mData->mEnabled != aEnabled)
201 {
202 mData.backup();
203 mData->mEnabled = aEnabled;
204
205 /* leave the lock for safety */
206 alock.leave();
207
208 mParent->onSATAControllerChange();
209 }
210
211 return S_OK;
212}
213
214// ISATAController methods
215/////////////////////////////////////////////////////////////////////////////
216
217STDMETHODIMP SATAController::GetIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
218{
219 if (!aPortNumber)
220 return E_POINTER;
221
222 AutoCaller autoCaller (this);
223 CheckComRCReturnRC (autoCaller.rc());
224
225 switch (DevicePosition)
226 {
227 case 0:
228 *aPortNumber = mData->mPortIde0Master;
229 break;
230 case 1:
231 *aPortNumber = mData->mPortIde0Slave;
232 break;
233 case 2:
234 *aPortNumber = mData->mPortIde1Master;
235 break;
236 case 3:
237 *aPortNumber = mData->mPortIde1Slave;
238 break;
239 default:
240 return E_INVALIDARG;
241 }
242
243 return S_OK;
244}
245
246STDMETHODIMP SATAController::SetIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
247{
248 AutoCaller autoCaller (this);
249 CheckComRCReturnRC (autoCaller.rc());
250
251 /* the machine needs to be mutable */
252 Machine::AutoMutableStateDependency adep (mParent);
253 CheckComRCReturnRC (adep.rc());
254 AutoLock alock (this);
255
256 switch (DevicePosition)
257 {
258 case 0:
259 mData->mPortIde0Master = aPortNumber;
260 break;
261 case 1:
262 mData->mPortIde0Slave = aPortNumber;
263 break;
264 case 2:
265 mData->mPortIde1Master = aPortNumber;
266 break;
267 case 3:
268 mData->mPortIde1Slave = aPortNumber;
269 break;
270 default:
271 return E_INVALIDARG;
272 }
273
274 return S_OK;
275}
276
277
278// public methods only for internal purposes
279/////////////////////////////////////////////////////////////////////////////
280
281/**
282 * Loads settings from the given machine node.
283 * May be called once right after this object creation.
284 *
285 * @param aMachineNode <Machine> node.
286 *
287 * @note Locks this object for writing.
288 */
289HRESULT SATAController::loadSettings (const settings::Key &aMachineNode)
290{
291 using namespace settings;
292
293 AssertReturn (!aMachineNode.isNull(), E_FAIL);
294
295 AutoCaller autoCaller (this);
296 AssertComRCReturnRC (autoCaller.rc());
297
298 AutoLock alock (this);
299
300 /* SATA Controller node (required) */
301 Key controller = aMachineNode.key ("SATAController");
302
303 /* enabled (required) */
304 mData->mEnabled = controller.value <bool> ("enabled");
305
306 /* ide emulation settings (optional, default to 0,1,2,3 respectively) */
307 mData->mPortIde0Master = controller.value <ULONG> ("IDE0MasterEmulationPort");
308 mData->mPortIde0Slave = controller.value <ULONG> ("IDE0SlaveEmulationPort");
309 mData->mPortIde1Master = controller.value <ULONG> ("IDE1MasterEmulationPort");
310 mData->mPortIde1Slave = controller.value <ULONG> ("IDE1SlaveEmulationPort");
311
312 return S_OK;
313}
314
315/**
316 * Saves settings to the given machine node.
317 *
318 * @param aMachineNode <Machine> node.
319 *
320 * @note Locks this object for reading.
321 */
322HRESULT SATAController::saveSettings (settings::Key &aMachineNode)
323{
324 using namespace settings;
325
326 AssertReturn (!aMachineNode.isNull(), E_FAIL);
327
328 AutoCaller autoCaller (this);
329 CheckComRCReturnRC (autoCaller.rc());
330
331 AutoReaderLock alock (this);
332
333 /* first, delete the entry */
334 Key controller = aMachineNode.findKey ("SATAController");
335 if (!controller.isNull())
336 controller.zap();
337 /* then, recreate it */
338 controller = aMachineNode.createKey ("SATAController");
339
340 /* enabled */
341 controller.setValue <bool> ("enabled", !!mData->mEnabled);
342
343 /* ide emulation settings */
344 controller.setValue <ULONG> ("IDE0MasterEmulationPort", mData->mPortIde0Master);
345 controller.setValue <ULONG> ("IDE0SlaveEmulationPort", mData->mPortIde0Slave);
346 controller.setValue <ULONG> ("IDE1MasterEmulationPort", mData->mPortIde1Master);
347 controller.setValue <ULONG> ("IDE1SlaveEmulationPort", mData->mPortIde1Slave);
348
349 return S_OK;
350}
351
352/** @note Locks objects for reading! */
353bool SATAController::isModified()
354{
355 AutoCaller autoCaller (this);
356 AssertComRCReturn (autoCaller.rc(), false);
357
358 AutoReaderLock alock (this);
359
360 if (mData.isBackedUp())
361 return true;
362
363 return false;
364}
365
366/** @note Locks objects for reading! */
367bool SATAController::isReallyModified()
368{
369 AutoCaller autoCaller (this);
370 AssertComRCReturn (autoCaller.rc(), false);
371
372 AutoReaderLock alock (this);
373
374 if (mData.hasActualChanges())
375 return true;
376
377 return false;
378}
379
380/** @note Locks objects for writing! */
381bool SATAController::rollback()
382{
383 AutoCaller autoCaller (this);
384 AssertComRCReturn (autoCaller.rc(), false);
385
386 /* we need the machine state */
387 Machine::AutoAnyStateDependency adep (mParent);
388 AssertComRCReturn (adep.rc(), false);
389
390 AutoLock alock (this);
391
392 bool dataChanged = false;
393
394 if (mData.isBackedUp())
395 {
396 /* we need to check all data to see whether anything will be changed
397 * after rollback */
398 dataChanged = mData.hasActualChanges();
399 mData.rollback();
400 }
401
402 return dataChanged;
403}
404
405/** @note Locks objects for writing! */
406void SATAController::commit()
407{
408 AutoCaller autoCaller (this);
409 AssertComRCReturnVoid (autoCaller.rc());
410
411 AutoLock alock (this);
412
413 if (mData.isBackedUp())
414 {
415 mData.commit();
416 if (mPeer)
417 {
418 // attach new data to the peer and reshare it
419 AutoLock peerlock (mPeer);
420 mPeer->mData.attach (mData);
421 }
422 }
423}
424
425/** @note Locks object for writing and that object for reading! */
426void SATAController::copyFrom (SATAController *aThat)
427{
428 AutoCaller autoCaller (this);
429 AssertComRCReturnVoid (autoCaller.rc());
430
431 AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
432
433 /* this will back up current data */
434 mData.assignCopy (aThat->mData);
435}
436
437// private methods
438/////////////////////////////////////////////////////////////////////////////
439
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