VirtualBox

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

Last change on this file since 56992 was 56292, checked in by vboxsync, 10 years ago

Devices: Updated (C) year.

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