VirtualBox

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

Last change on this file since 10753 was 10082, checked in by vboxsync, 16 years ago

typo

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Revision Author Id
File size: 13.2 KB
Line 
1/* $Id: SATAControllerImpl.cpp 10082 2008-07-01 18:50:28Z 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_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 /* 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
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