VirtualBox

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

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

build fix

  • 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.virtualbox.org. 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->Base.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.

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