VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DrvHostFloppy.cpp@ 45061

Last change on this file since 45061 was 45061, checked in by vboxsync, 12 years ago

Review of PDM driver destructors making sure that variables they use are correctly initialized in the constructor. Found several RTFileClose(0) cases.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1/** @file
2 *
3 * VBox storage devices:
4 * Host floppy block driver
5 */
6
7/*
8 * Copyright (C) 2006-2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.215389.xyz. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#define LOG_GROUP LOG_GROUP_DRV_HOST_FLOPPY
24#ifdef RT_OS_LINUX
25# include <sys/ioctl.h>
26# include <linux/fd.h>
27# include <sys/fcntl.h>
28# include <errno.h>
29
30# elif defined(RT_OS_WINDOWS)
31# include <windows.h>
32# include <dbt.h>
33
34#elif defined(RT_OS_L4)
35
36#else /* !RT_OS_WINDOWS nor RT_OS_LINUX nor RT_OS_L4 */
37# error "Unsupported Platform."
38#endif /* !RT_OS_WINDOWS nor RT_OS_LINUX nor RT_OS_L4 */
39
40#include <VBox/vmm/pdmdrv.h>
41#include <iprt/assert.h>
42#include <iprt/file.h>
43#include <iprt/string.h>
44#include <iprt/thread.h>
45#include <iprt/semaphore.h>
46#include <iprt/uuid.h>
47#include <iprt/asm.h>
48#include <iprt/critsect.h>
49
50#include "VBoxDD.h"
51#include "DrvHostBase.h"
52
53
54/**
55 * Floppy driver instance data.
56 */
57typedef struct DRVHOSTFLOPPY
58{
59 DRVHOSTBASE Base;
60 /** Previous poll status. */
61 bool fPrevDiskIn;
62
63} DRVHOSTFLOPPY, *PDRVHOSTFLOPPY;
64
65
66
67#ifdef RT_OS_WINDOWS
68/**
69 * Get media size - needs a special IOCTL.
70 *
71 * @param pThis The instance data.
72 */
73static DECLCALLBACK(int) drvHostFloppyGetMediaSize(PDRVHOSTBASE pThis, uint64_t *pcb)
74{
75 DISK_GEOMETRY geom;
76 DWORD cbBytesReturned;
77 int rc;
78 int cbSectors;
79
80 memset(&geom, 0, sizeof(geom));
81 rc = DeviceIoControl((HANDLE)RTFileToNative(pThis->hFileDevice), IOCTL_DISK_GET_DRIVE_GEOMETRY,
82 NULL, 0, &geom, sizeof(geom), &cbBytesReturned, NULL);
83 if (rc) {
84 cbSectors = geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack;
85 *pcb = cbSectors * geom.BytesPerSector;
86 rc = VINF_SUCCESS;
87 }
88 else
89 {
90 DWORD dwLastError;
91
92 dwLastError = GetLastError();
93 rc = RTErrConvertFromWin32(dwLastError);
94 Log(("DrvHostFloppy: IOCTL_DISK_GET_DRIVE_GEOMETRY(%s) failed, LastError=%d rc=%Rrc\n",
95 pThis->pszDevice, dwLastError, rc));
96 return rc;
97 }
98
99 return rc;
100}
101#endif /* RT_OS_WINDOWS */
102
103#ifdef RT_OS_LINUX
104/**
105 * Get media size and do change processing.
106 *
107 * @param pThis The instance data.
108 */
109static DECLCALLBACK(int) drvHostFloppyGetMediaSize(PDRVHOSTBASE pThis, uint64_t *pcb)
110{
111 int rc = ioctl(RTFileToNative(pThis->hFileDevice), FDFLUSH);
112 if (rc)
113 {
114 rc = RTErrConvertFromErrno (errno);
115 Log(("DrvHostFloppy: FDFLUSH ioctl(%s) failed, errno=%d rc=%Rrc\n", pThis->pszDevice, errno, rc));
116 return rc;
117 }
118
119 floppy_drive_struct DrvStat;
120 rc = ioctl(RTFileToNative(pThis->hFileDevice), FDGETDRVSTAT, &DrvStat);
121 if (rc)
122 {
123 rc = RTErrConvertFromErrno(errno);
124 Log(("DrvHostFloppy: FDGETDRVSTAT ioctl(%s) failed, errno=%d rc=%Rrc\n", pThis->pszDevice, errno, rc));
125 return rc;
126 }
127 pThis->fReadOnly = !(DrvStat.flags & FD_DISK_WRITABLE);
128
129 return RTFileSeek(pThis->hFileDevice, 0, RTFILE_SEEK_END, pcb);
130}
131#endif /* RT_OS_LINUX */
132
133
134#ifdef RT_OS_LINUX
135/**
136 * This thread will periodically poll the Floppy for media presence.
137 *
138 * @returns Ignored.
139 * @param ThreadSelf Handle of this thread. Ignored.
140 * @param pvUser Pointer to the driver instance structure.
141 */
142static DECLCALLBACK(int) drvHostFloppyPoll(PDRVHOSTBASE pThis)
143{
144 PDRVHOSTFLOPPY pThisFloppy = (PDRVHOSTFLOPPY)pThis;
145 floppy_drive_struct DrvStat;
146 int rc = ioctl(RTFileToNative(pThis->hFileDevice), FDPOLLDRVSTAT, &DrvStat);
147 if (rc)
148 return RTErrConvertFromErrno(errno);
149
150 RTCritSectEnter(&pThis->CritSect);
151 bool fDiskIn = !(DrvStat.flags & (FD_VERIFY | FD_DISK_NEWCHANGE));
152 if ( fDiskIn
153 && !pThisFloppy->fPrevDiskIn)
154 {
155 if (pThis->fMediaPresent)
156 DRVHostBaseMediaNotPresent(pThis);
157 rc = DRVHostBaseMediaPresent(pThis);
158 if (RT_FAILURE(rc))
159 {
160 pThisFloppy->fPrevDiskIn = fDiskIn;
161 RTCritSectLeave(&pThis->CritSect);
162 return rc;
163 }
164 }
165
166 if ( !fDiskIn
167 && pThisFloppy->fPrevDiskIn
168 && pThis->fMediaPresent)
169 DRVHostBaseMediaNotPresent(pThis);
170 pThisFloppy->fPrevDiskIn = fDiskIn;
171
172 RTCritSectLeave(&pThis->CritSect);
173 return VINF_SUCCESS;
174}
175#endif /* RT_OS_LINUX */
176
177
178/**
179 * @copydoc FNPDMDRVCONSTRUCT
180 */
181static DECLCALLBACK(int) drvHostFloppyConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
182{
183 PDRVHOSTFLOPPY pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTFLOPPY);
184 LogFlow(("drvHostFloppyConstruct: iInstance=%d\n", pDrvIns->iInstance));
185
186 /*
187 * Init instance data.
188 */
189 int rc = DRVHostBaseInitData(pDrvIns, pCfg, PDMBLOCKTYPE_FLOPPY_1_44);
190 if (RT_SUCCESS(rc))
191 {
192 /*
193 * Validate configuration.
194 */
195 if (CFGMR3AreValuesValid(pCfg, "Path\0ReadOnly\0Interval\0Locked\0BIOSVisible\0"))
196 {
197 /*
198 * Override stuff.
199 */
200#ifdef RT_OS_WINDOWS
201 pThis->Base.pfnGetMediaSize = drvHostFloppyGetMediaSize;
202#endif
203#ifdef RT_OS_LINUX
204 pThis->Base.pfnPoll = drvHostFloppyPoll;
205 pThis->Base.pfnGetMediaSize = drvHostFloppyGetMediaSize;
206#endif
207
208 /*
209 * 2nd init part.
210 */
211 rc = DRVHostBaseInitFinish(&pThis->Base);
212 }
213 else
214 {
215 pThis->fAttachFailError = true;
216 rc = VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
217 }
218 }
219 if (RT_FAILURE(rc))
220 {
221 if (!pThis->Base.fAttachFailError)
222 {
223 /* Suppressing the attach failure error must not affect the normal
224 * DRVHostBaseDestruct, so reset this flag below before leaving. */
225 pThis->Base.fKeepInstance = true;
226 rc = VINF_SUCCESS;
227 }
228 DRVHostBaseDestruct(pDrvIns);
229 pThis->Base.fKeepInstance = false;
230 }
231
232 LogFlow(("drvHostFloppyConstruct: returns %Rrc\n", rc));
233 return rc;
234}
235
236
237/**
238 * Block driver registration record.
239 */
240const PDMDRVREG g_DrvHostFloppy =
241{
242 /* u32Version */
243 PDM_DRVREG_VERSION,
244 /* szName */
245 "HostFloppy",
246 /* szRCMod */
247 "",
248 /* szR0Mod */
249 "",
250 /* pszDescription */
251 "Host Floppy Block Driver.",
252 /* fFlags */
253 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
254 /* fClass. */
255 PDM_DRVREG_CLASS_BLOCK,
256 /* cMaxInstances */
257 ~0U,
258 /* cbInstance */
259 sizeof(DRVHOSTFLOPPY),
260 /* pfnConstruct */
261 drvHostFloppyConstruct,
262 /* pfnDestruct */
263 DRVHostBaseDestruct,
264 /* pfnRelocate */
265 NULL,
266 /* pfnIOCtl */
267 NULL,
268 /* pfnPowerOn */
269 NULL,
270 /* pfnReset */
271 NULL,
272 /* pfnSuspend */
273 NULL,
274 /* pfnResume */
275 NULL,
276 /* pfnAttach */
277 NULL,
278 /* pfnDetach */
279 NULL,
280 /* pfnPowerOff */
281 NULL,
282 /* pfnSoftReset */
283 NULL,
284 /* u32EndVersion */
285 PDM_DRVREG_VERSION
286};
287
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette