VirtualBox

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

Last change on this file since 7449 was 7442, checked in by vboxsync, 17 years ago

Main: Applied SATA changes from #2406. Increased XML settings version format from 1.2 to 1.3.pre.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 11.1 KB
Line 
1/* $Id: SATAControllerImpl.cpp 7442 2008-03-13 14:33:18Z 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 /* the machine needs to be mutable */
226 Machine::AutoMutableStateDependency adep (mParent);
227 CheckComRCReturnRC (adep.rc());
228 AutoLock alock (this);
229
230 switch (DevicePosition)
231 {
232 case 0:
233 *aPortNumber = mData->mPortIde0Master;
234 break;
235 case 1:
236 *aPortNumber = mData->mPortIde0Slave;
237 break;
238 case 2:
239 *aPortNumber = mData->mPortIde1Master;
240 break;
241 case 3:
242 *aPortNumber = mData->mPortIde1Slave;
243 break;
244 default:
245 return E_INVALIDARG;
246 }
247
248 return S_OK;
249}
250
251STDMETHODIMP SATAController::SetIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
252{
253 AutoCaller autoCaller (this);
254 CheckComRCReturnRC (autoCaller.rc());
255
256 /* the machine needs to be mutable */
257 Machine::AutoMutableStateDependency adep (mParent);
258 CheckComRCReturnRC (adep.rc());
259 AutoLock alock (this);
260
261 switch (DevicePosition)
262 {
263 case 0:
264 mData->mPortIde0Master = aPortNumber;
265 break;
266 case 1:
267 mData->mPortIde0Slave = aPortNumber;
268 break;
269 case 2:
270 mData->mPortIde1Master = aPortNumber;
271 break;
272 case 3:
273 mData->mPortIde1Slave = aPortNumber;
274 break;
275 default:
276 return E_INVALIDARG;
277 }
278
279 return S_OK;
280}
281
282
283// public methods only for internal purposes
284/////////////////////////////////////////////////////////////////////////////
285
286/**
287 * Loads settings from the given machine node.
288 * May be called once right after this object creation.
289 *
290 * @param aMachineNode <Machine> node.
291 *
292 * @note Locks this object for writing.
293 */
294HRESULT SATAController::loadSettings (const settings::Key &aMachineNode)
295{
296 using namespace settings;
297
298 AssertReturn (!aMachineNode.isNull(), E_FAIL);
299
300 AutoCaller autoCaller (this);
301 AssertComRCReturnRC (autoCaller.rc());
302
303 AutoLock alock (this);
304
305 /* SATA Controller node (required) */
306 Key controller = aMachineNode.key ("SATAController");
307
308 /* enabled (required) */
309 mData->mEnabled = controller.value <bool> ("enabled");
310
311 /* ide emulation settings (optional, default to 0,1,2,3 respectively) */
312 mData->mPortIde0Master = controller.value <ULONG> ("IDE0MasterEmulationPort");
313 mData->mPortIde0Slave = controller.value <ULONG> ("IDE0SlaveEmulationPort");
314 mData->mPortIde1Master = controller.value <ULONG> ("IDE1MasterEmulationPort");
315 mData->mPortIde1Slave = controller.value <ULONG> ("IDE1SlaveEmulationPort");
316
317 return S_OK;
318}
319
320/**
321 * Saves settings to the given machine node.
322 *
323 * @param aMachineNode <Machine> node.
324 *
325 * @note Locks this object for reading.
326 */
327HRESULT SATAController::saveSettings (settings::Key &aMachineNode)
328{
329 using namespace settings;
330
331 AssertReturn (!aMachineNode.isNull(), E_FAIL);
332
333 AutoCaller autoCaller (this);
334 CheckComRCReturnRC (autoCaller.rc());
335
336 AutoReaderLock alock (this);
337
338 /* first, delete the entry */
339 Key controller = aMachineNode.findKey ("SATAController");
340 if (!controller.isNull())
341 controller.zap();
342 /* then, recreate it */
343 controller = aMachineNode.createKey ("SATAController");
344
345 /* enabled */
346 controller.setValue <bool> ("enabled", !!mData->mEnabled);
347
348 /* ide emulation settings */
349 controller.setValue <ULONG> ("IDE0MasterEmulationPort", mData->mPortIde0Master);
350 controller.setValue <ULONG> ("IDE0SlaveEmulationPort", mData->mPortIde0Slave);
351 controller.setValue <ULONG> ("IDE1MasterEmulationPort", mData->mPortIde1Master);
352 controller.setValue <ULONG> ("IDE1SlaveEmulationPort", mData->mPortIde1Slave);
353
354 return S_OK;
355}
356
357/** @note Locks objects for reading! */
358bool SATAController::isModified()
359{
360 AutoCaller autoCaller (this);
361 AssertComRCReturn (autoCaller.rc(), false);
362
363 AutoReaderLock alock (this);
364
365 if (mData.isBackedUp())
366 return true;
367
368 return false;
369}
370
371/** @note Locks objects for reading! */
372bool SATAController::isReallyModified()
373{
374 AutoCaller autoCaller (this);
375 AssertComRCReturn (autoCaller.rc(), false);
376
377 AutoReaderLock alock (this);
378
379 if (mData.hasActualChanges())
380 return true;
381
382 return false;
383}
384
385/** @note Locks objects for writing! */
386bool SATAController::rollback()
387{
388 AutoCaller autoCaller (this);
389 AssertComRCReturn (autoCaller.rc(), false);
390
391 /* we need the machine state */
392 Machine::AutoAnyStateDependency adep (mParent);
393 AssertComRCReturn (adep.rc(), false);
394
395 AutoLock alock (this);
396
397 bool dataChanged = false;
398
399 if (mData.isBackedUp())
400 {
401 /* we need to check all data to see whether anything will be changed
402 * after rollback */
403 dataChanged = mData.hasActualChanges();
404 mData.rollback();
405 }
406
407 return dataChanged;
408}
409
410/** @note Locks objects for writing! */
411void SATAController::commit()
412{
413 AutoCaller autoCaller (this);
414 AssertComRCReturnVoid (autoCaller.rc());
415
416 AutoLock alock (this);
417
418 if (mData.isBackedUp())
419 {
420 mData.commit();
421 if (mPeer)
422 {
423 // attach new data to the peer and reshare it
424 AutoLock peerlock (mPeer);
425 mPeer->mData.attach (mData);
426 }
427 }
428}
429
430/** @note Locks object for writing and that object for reading! */
431void SATAController::copyFrom (SATAController *aThat)
432{
433 AutoCaller autoCaller (this);
434 AssertComRCReturnVoid (autoCaller.rc());
435
436 AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
437
438 /* this will back up current data */
439 mData.assignCopy (aThat->mData);
440}
441
442// private methods
443/////////////////////////////////////////////////////////////////////////////
444
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