VirtualBox

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

Last change on this file since 8572 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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