VirtualBox

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

Last change on this file since 7692 was 7556, checked in by vboxsync, 17 years ago

AHCI/Main/VBoxManage: Add configuration parameter to set the number of ports on the sata controller. FreeBSD cannot handle more than 8 and would crash otherwise. Also adds the previously forgotten BIOS configuration parameters for booting from SATA

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