VirtualBox

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

Last change on this file since 14789 was 14772, checked in by vboxsync, 16 years ago

Added vim modelines to aid following coding guidelines, like no tabs,
similar to what is already in the xidl file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 13.3 KB
Line 
1/* $Id: SATAControllerImpl.cpp 14772 2008-11-28 12:41:22Z 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 SATA 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_FAIL);
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_FAIL);
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_FAIL);
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 /* We support a maximum of 30 channels. */
239 if ((aPortCount < 1) || (aPortCount > 30))
240 return setError (E_INVALIDARG,
241 tr ("Invalid port count: %lu (must be in range [%lu, %lu])"),
242 aPortCount, 1, 30);
243
244 AutoCaller autoCaller (this);
245 CheckComRCReturnRC (autoCaller.rc());
246
247 /* the machine needs to be mutable */
248 Machine::AutoMutableStateDependency adep (mParent);
249 CheckComRCReturnRC (adep.rc());
250
251 AutoWriteLock alock (this);
252
253 if (mData->mPortCount != aPortCount)
254 {
255 mData.backup();
256 mData->mPortCount = aPortCount;
257
258 /* leave the lock for safety */
259 alock.leave();
260
261 mParent->onSATAControllerChange();
262 }
263
264 return S_OK;
265}
266
267// ISATAController methods
268/////////////////////////////////////////////////////////////////////////////
269
270STDMETHODIMP SATAController::GetIDEEmulationPort(LONG DevicePosition, LONG *aPortNumber)
271{
272 if (!aPortNumber)
273 return E_POINTER;
274
275 AutoCaller autoCaller (this);
276 CheckComRCReturnRC (autoCaller.rc());
277
278 switch (DevicePosition)
279 {
280 case 0:
281 *aPortNumber = mData->mPortIde0Master;
282 break;
283 case 1:
284 *aPortNumber = mData->mPortIde0Slave;
285 break;
286 case 2:
287 *aPortNumber = mData->mPortIde1Master;
288 break;
289 case 3:
290 *aPortNumber = mData->mPortIde1Slave;
291 break;
292 default:
293 return E_INVALIDARG;
294 }
295
296 return S_OK;
297}
298
299STDMETHODIMP SATAController::SetIDEEmulationPort(LONG DevicePosition, LONG aPortNumber)
300{
301 if ((aPortNumber < 0) || (aPortNumber >= 30))
302 return setError (E_INVALIDARG,
303 tr ("Invalid port number: %l (must be in range [%lu, %lu])"),
304 aPortNumber, 0, 29);
305
306 AutoCaller autoCaller (this);
307 CheckComRCReturnRC (autoCaller.rc());
308
309 /* the machine needs to be mutable */
310 Machine::AutoMutableStateDependency adep (mParent);
311 CheckComRCReturnRC (adep.rc());
312 AutoWriteLock alock (this);
313
314 switch (DevicePosition)
315 {
316 case 0:
317 mData->mPortIde0Master = aPortNumber;
318 break;
319 case 1:
320 mData->mPortIde0Slave = aPortNumber;
321 break;
322 case 2:
323 mData->mPortIde1Master = aPortNumber;
324 break;
325 case 3:
326 mData->mPortIde1Slave = aPortNumber;
327 break;
328 default:
329 return E_INVALIDARG;
330 }
331
332 return S_OK;
333}
334
335// public methods only for internal purposes
336/////////////////////////////////////////////////////////////////////////////
337
338/**
339 * Loads settings from the given machine node.
340 * May be called once right after this object creation.
341 *
342 * @param aMachineNode <Machine> node.
343 *
344 * @note Locks this object for writing.
345 */
346HRESULT SATAController::loadSettings (const settings::Key &aMachineNode)
347{
348 using namespace settings;
349
350 AssertReturn (!aMachineNode.isNull(), E_FAIL);
351
352 AutoCaller autoCaller (this);
353 AssertComRCReturnRC (autoCaller.rc());
354
355 AutoWriteLock alock (this);
356
357 /* SATA Controller node (required) */
358 Key controller = aMachineNode.key ("SATAController");
359
360 /* enabled (required) */
361 mData->mEnabled = controller.value <bool> ("enabled");
362
363 /* number of useable ports */
364 mData->mPortCount = controller.valueOr <ULONG> ("PortCount", 30);
365
366 /* ide emulation settings (optional, default to 0,1,2,3 respectively) */
367 mData->mPortIde0Master = controller.value <ULONG> ("IDE0MasterEmulationPort");
368 mData->mPortIde0Slave = controller.value <ULONG> ("IDE0SlaveEmulationPort");
369 mData->mPortIde1Master = controller.value <ULONG> ("IDE1MasterEmulationPort");
370 mData->mPortIde1Slave = controller.value <ULONG> ("IDE1SlaveEmulationPort");
371
372 return S_OK;
373}
374
375/**
376 * Saves settings to the given machine node.
377 *
378 * @param aMachineNode <Machine> node.
379 *
380 * @note Locks this object for reading.
381 */
382HRESULT SATAController::saveSettings (settings::Key &aMachineNode)
383{
384 using namespace settings;
385
386 AssertReturn (!aMachineNode.isNull(), E_FAIL);
387
388 AutoCaller autoCaller (this);
389 CheckComRCReturnRC (autoCaller.rc());
390
391 AutoReadLock alock (this);
392
393 /* first, delete the entry */
394 Key controller = aMachineNode.findKey ("SATAController");
395 if (!controller.isNull())
396 controller.zap();
397 /* then, recreate it */
398 controller = aMachineNode.createKey ("SATAController");
399
400 /* enabled */
401 controller.setValue <bool> ("enabled", !!mData->mEnabled);
402
403 /* number of useable ports */
404 controller.setValue <ULONG> ("PortCount", mData->mPortCount);
405
406 /* ide emulation settings */
407 controller.setValue <ULONG> ("IDE0MasterEmulationPort", mData->mPortIde0Master);
408 controller.setValue <ULONG> ("IDE0SlaveEmulationPort", mData->mPortIde0Slave);
409 controller.setValue <ULONG> ("IDE1MasterEmulationPort", mData->mPortIde1Master);
410 controller.setValue <ULONG> ("IDE1SlaveEmulationPort", mData->mPortIde1Slave);
411
412 return S_OK;
413}
414
415/** @note Locks objects for reading! */
416bool SATAController::isModified()
417{
418 AutoCaller autoCaller (this);
419 AssertComRCReturn (autoCaller.rc(), false);
420
421 AutoReadLock alock (this);
422
423 if (mData.isBackedUp())
424 return true;
425
426 return false;
427}
428
429/** @note Locks objects for reading! */
430bool SATAController::isReallyModified()
431{
432 AutoCaller autoCaller (this);
433 AssertComRCReturn (autoCaller.rc(), false);
434
435 AutoReadLock alock (this);
436
437 if (mData.hasActualChanges())
438 return true;
439
440 return false;
441}
442
443/** @note Locks objects for writing! */
444bool SATAController::rollback()
445{
446 AutoCaller autoCaller (this);
447 AssertComRCReturn (autoCaller.rc(), false);
448
449 /* we need the machine state */
450 Machine::AutoAnyStateDependency adep (mParent);
451 AssertComRCReturn (adep.rc(), false);
452
453 AutoWriteLock alock (this);
454
455 bool dataChanged = false;
456
457 if (mData.isBackedUp())
458 {
459 /* we need to check all data to see whether anything will be changed
460 * after rollback */
461 dataChanged = mData.hasActualChanges();
462 mData.rollback();
463 }
464
465 return dataChanged;
466}
467
468/**
469 * @note Locks this object for writing, together with the peer object (also
470 * for writing) if there is one.
471 */
472void SATAController::commit()
473{
474 /* sanity */
475 AutoCaller autoCaller (this);
476 AssertComRCReturnVoid (autoCaller.rc());
477
478 /* sanity too */
479 AutoCaller peerCaller (mPeer);
480 AssertComRCReturnVoid (peerCaller.rc());
481
482 /* lock both for writing since we modify both (mPeer is "master" so locked
483 * first) */
484 AutoMultiWriteLock2 alock (mPeer, this);
485
486 if (mData.isBackedUp())
487 {
488 mData.commit();
489 if (mPeer)
490 {
491 // attach new data to the peer and reshare it
492 AutoWriteLock peerlock (mPeer);
493 mPeer->mData.attach (mData);
494 }
495 }
496}
497
498/**
499 * @note Locks this object for writing, together with the peer object
500 * represented by @a aThat (locked for reading).
501 */
502void SATAController::copyFrom (SATAController *aThat)
503{
504 AssertReturnVoid (aThat != NULL);
505
506 /* sanity */
507 AutoCaller autoCaller (this);
508 AssertComRCReturnVoid (autoCaller.rc());
509
510 /* sanity too */
511 AutoCaller thatCaller (aThat);
512 AssertComRCReturnVoid (thatCaller.rc());
513
514 /* peer is not modified, lock it for reading (aThat is "master" so locked
515 * first) */
516 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
517
518 /* this will back up current data */
519 mData.assignCopy (aThat->mData);
520}
521
522// private methods
523/////////////////////////////////////////////////////////////////////////////
524/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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