Statistics
| Branch: | Revision:

root / block / raw-posix.c @ 9a2d77ad

History | View | Annotate | Download (35.8 kB)

1 83f64091 bellard
/*
2 223d4670 ths
 * Block driver for RAW files (posix)
3 5fafdf24 ths
 *
4 83f64091 bellard
 * Copyright (c) 2006 Fabrice Bellard
5 5fafdf24 ths
 *
6 83f64091 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 83f64091 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 83f64091 bellard
 * in the Software without restriction, including without limitation the rights
9 83f64091 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 83f64091 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 83f64091 bellard
 * furnished to do so, subject to the following conditions:
12 83f64091 bellard
 *
13 83f64091 bellard
 * The above copyright notice and this permission notice shall be included in
14 83f64091 bellard
 * all copies or substantial portions of the Software.
15 83f64091 bellard
 *
16 83f64091 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 83f64091 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 83f64091 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 83f64091 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 83f64091 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 83f64091 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 83f64091 bellard
 * THE SOFTWARE.
23 83f64091 bellard
 */
24 faf07963 pbrook
#include "qemu-common.h"
25 87ecb68b pbrook
#include "qemu-timer.h"
26 baf35cb9 aliguori
#include "qemu-char.h"
27 0bf9e31a Blue Swirl
#include "qemu-log.h"
28 83f64091 bellard
#include "block_int.h"
29 5efa9d5a Anthony Liguori
#include "module.h"
30 9ef91a67 Christoph Hellwig
#include "block/raw-posix-aio.h"
31 83f64091 bellard
32 83f64091 bellard
#ifdef CONFIG_COCOA
33 83f64091 bellard
#include <paths.h>
34 83f64091 bellard
#include <sys/param.h>
35 83f64091 bellard
#include <IOKit/IOKitLib.h>
36 83f64091 bellard
#include <IOKit/IOBSD.h>
37 83f64091 bellard
#include <IOKit/storage/IOMediaBSDClient.h>
38 83f64091 bellard
#include <IOKit/storage/IOMedia.h>
39 83f64091 bellard
#include <IOKit/storage/IOCDMedia.h>
40 83f64091 bellard
//#include <IOKit/storage/IOCDTypes.h>
41 83f64091 bellard
#include <CoreFoundation/CoreFoundation.h>
42 83f64091 bellard
#endif
43 83f64091 bellard
44 83f64091 bellard
#ifdef __sun__
45 2e9671da ths
#define _POSIX_PTHREAD_SEMANTICS 1
46 2e9671da ths
#include <signal.h>
47 83f64091 bellard
#include <sys/dkio.h>
48 83f64091 bellard
#endif
49 19cb3738 bellard
#ifdef __linux__
50 19cb3738 bellard
#include <sys/ioctl.h>
51 19cb3738 bellard
#include <linux/cdrom.h>
52 19cb3738 bellard
#include <linux/fd.h>
53 19cb3738 bellard
#endif
54 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
55 543952ca blueswir1
#include <signal.h>
56 1cb6c3fd ths
#include <sys/disk.h>
57 9f23011a blueswir1
#include <sys/cdio.h>
58 1cb6c3fd ths
#endif
59 83f64091 bellard
60 128ab2ff blueswir1
#ifdef __OpenBSD__
61 128ab2ff blueswir1
#include <sys/ioctl.h>
62 128ab2ff blueswir1
#include <sys/disklabel.h>
63 128ab2ff blueswir1
#include <sys/dkio.h>
64 128ab2ff blueswir1
#endif
65 128ab2ff blueswir1
66 c5e97233 blueswir1
#ifdef __DragonFly__
67 c5e97233 blueswir1
#include <sys/ioctl.h>
68 c5e97233 blueswir1
#include <sys/diskslice.h>
69 c5e97233 blueswir1
#endif
70 c5e97233 blueswir1
71 19cb3738 bellard
//#define DEBUG_FLOPPY
72 83f64091 bellard
73 faf07963 pbrook
//#define DEBUG_BLOCK
74 03ff3ca3 aliguori
#if defined(DEBUG_BLOCK)
75 001faf32 Blue Swirl
#define DEBUG_BLOCK_PRINT(formatCstr, ...) do { if (qemu_log_enabled()) \
76 001faf32 Blue Swirl
    { qemu_log(formatCstr, ## __VA_ARGS__); qemu_log_flush(); } } while (0)
77 8c05dbf9 ths
#else
78 001faf32 Blue Swirl
#define DEBUG_BLOCK_PRINT(formatCstr, ...)
79 8c05dbf9 ths
#endif
80 8c05dbf9 ths
81 f6465578 aliguori
/* OS X does not have O_DSYNC */
82 f6465578 aliguori
#ifndef O_DSYNC
83 1c27a8b3 G 3
#ifdef O_SYNC
84 7ab064d2 aliguori
#define O_DSYNC O_SYNC
85 1c27a8b3 G 3
#elif defined(O_FSYNC)
86 1c27a8b3 G 3
#define O_DSYNC O_FSYNC
87 1c27a8b3 G 3
#endif
88 f6465578 aliguori
#endif
89 f6465578 aliguori
90 9f7965c7 aliguori
/* Approximate O_DIRECT with O_DSYNC if O_DIRECT isn't available */
91 9f7965c7 aliguori
#ifndef O_DIRECT
92 9f7965c7 aliguori
#define O_DIRECT O_DSYNC
93 9f7965c7 aliguori
#endif
94 9f7965c7 aliguori
95 19cb3738 bellard
#define FTYPE_FILE   0
96 19cb3738 bellard
#define FTYPE_CD     1
97 19cb3738 bellard
#define FTYPE_FD     2
98 83f64091 bellard
99 bed5cc52 bellard
#define ALIGNED_BUFFER_SIZE (32 * 512)
100 bed5cc52 bellard
101 19cb3738 bellard
/* if the FD is not accessed during that time (in ms), we try to
102 19cb3738 bellard
   reopen it to see if the disk has been changed */
103 19cb3738 bellard
#define FD_OPEN_TIMEOUT 1000
104 83f64091 bellard
105 19cb3738 bellard
typedef struct BDRVRawState {
106 19cb3738 bellard
    int fd;
107 19cb3738 bellard
    int type;
108 8c05dbf9 ths
    unsigned int lseek_err_cnt;
109 0e1d8f4c Christoph Hellwig
    int open_flags;
110 19cb3738 bellard
#if defined(__linux__)
111 19cb3738 bellard
    /* linux floppy specific */
112 19cb3738 bellard
    int64_t fd_open_time;
113 19cb3738 bellard
    int64_t fd_error_time;
114 19cb3738 bellard
    int fd_got_error;
115 19cb3738 bellard
    int fd_media_changed;
116 83f64091 bellard
#endif
117 e44bd6fc Stefan Weil
#ifdef CONFIG_LINUX_AIO
118 5c6c3a6c Christoph Hellwig
    int use_aio;
119 1e5b9d2f Kevin Wolf
    void *aio_ctx;
120 e44bd6fc Stefan Weil
#endif
121 bed5cc52 bellard
    uint8_t* aligned_buf;
122 19cb3738 bellard
} BDRVRawState;
123 19cb3738 bellard
124 19cb3738 bellard
static int fd_open(BlockDriverState *bs);
125 22afa7b5 Kevin Wolf
static int64_t raw_getlength(BlockDriverState *bs);
126 83f64091 bellard
127 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
128 f3a5d3f8 Christoph Hellwig
static int cdrom_reopen(BlockDriverState *bs);
129 9f23011a blueswir1
#endif
130 9f23011a blueswir1
131 90babde0 Christoph Hellwig
static int raw_open_common(BlockDriverState *bs, const char *filename,
132 19a3da7f Blue Swirl
                           int bdrv_flags, int open_flags)
133 83f64091 bellard
{
134 83f64091 bellard
    BDRVRawState *s = bs->opaque;
135 0e1d8f4c Christoph Hellwig
    int fd, ret;
136 83f64091 bellard
137 8c05dbf9 ths
    s->lseek_err_cnt = 0;
138 8c05dbf9 ths
139 19a3da7f Blue Swirl
    s->open_flags = open_flags | O_BINARY;
140 11a1feb6 Avi Kivity
    s->open_flags &= ~O_ACCMODE;
141 f5edb014 Naphtali Sprei
    if (bdrv_flags & BDRV_O_RDWR) {
142 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_RDWR;
143 83f64091 bellard
    } else {
144 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_RDONLY;
145 83f64091 bellard
        bs->read_only = 1;
146 83f64091 bellard
    }
147 9f7965c7 aliguori
148 9f7965c7 aliguori
    /* Use O_DSYNC for write-through caching, no flags for write-back caching,
149 9f7965c7 aliguori
     * and O_DIRECT for no caching. */
150 19a3da7f Blue Swirl
    if ((bdrv_flags & BDRV_O_NOCACHE))
151 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_DIRECT;
152 19a3da7f Blue Swirl
    else if (!(bdrv_flags & BDRV_O_CACHE_WB))
153 0e1d8f4c Christoph Hellwig
        s->open_flags |= O_DSYNC;
154 83f64091 bellard
155 90babde0 Christoph Hellwig
    s->fd = -1;
156 40ff6d7e Kevin Wolf
    fd = qemu_open(filename, s->open_flags, 0644);
157 19cb3738 bellard
    if (fd < 0) {
158 19cb3738 bellard
        ret = -errno;
159 19cb3738 bellard
        if (ret == -EROFS)
160 19cb3738 bellard
            ret = -EACCES;
161 19cb3738 bellard
        return ret;
162 19cb3738 bellard
    }
163 83f64091 bellard
    s->fd = fd;
164 bed5cc52 bellard
    s->aligned_buf = NULL;
165 5c6c3a6c Christoph Hellwig
166 19a3da7f Blue Swirl
    if ((bdrv_flags & BDRV_O_NOCACHE)) {
167 e268ca52 aliguori
        s->aligned_buf = qemu_blockalign(bs, ALIGNED_BUFFER_SIZE);
168 bed5cc52 bellard
        if (s->aligned_buf == NULL) {
169 9ef91a67 Christoph Hellwig
            goto out_close;
170 bed5cc52 bellard
        }
171 bed5cc52 bellard
    }
172 9ef91a67 Christoph Hellwig
173 5c6c3a6c Christoph Hellwig
#ifdef CONFIG_LINUX_AIO
174 5c6c3a6c Christoph Hellwig
    if ((bdrv_flags & (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) ==
175 5c6c3a6c Christoph Hellwig
                      (BDRV_O_NOCACHE|BDRV_O_NATIVE_AIO)) {
176 d2e46345 Kevin Wolf
177 d2e46345 Kevin Wolf
        /* We're falling back to POSIX AIO in some cases */
178 d2e46345 Kevin Wolf
        paio_init();
179 d2e46345 Kevin Wolf
180 5c6c3a6c Christoph Hellwig
        s->aio_ctx = laio_init();
181 5c6c3a6c Christoph Hellwig
        if (!s->aio_ctx) {
182 5c6c3a6c Christoph Hellwig
            goto out_free_buf;
183 5c6c3a6c Christoph Hellwig
        }
184 5c6c3a6c Christoph Hellwig
        s->use_aio = 1;
185 5c6c3a6c Christoph Hellwig
    } else
186 5c6c3a6c Christoph Hellwig
#endif
187 5c6c3a6c Christoph Hellwig
    {
188 1e5b9d2f Kevin Wolf
        if (paio_init() < 0) {
189 5c6c3a6c Christoph Hellwig
            goto out_free_buf;
190 5c6c3a6c Christoph Hellwig
        }
191 e44bd6fc Stefan Weil
#ifdef CONFIG_LINUX_AIO
192 5c6c3a6c Christoph Hellwig
        s->use_aio = 0;
193 e44bd6fc Stefan Weil
#endif
194 9ef91a67 Christoph Hellwig
    }
195 9ef91a67 Christoph Hellwig
196 83f64091 bellard
    return 0;
197 9ef91a67 Christoph Hellwig
198 9ef91a67 Christoph Hellwig
out_free_buf:
199 9ef91a67 Christoph Hellwig
    qemu_vfree(s->aligned_buf);
200 9ef91a67 Christoph Hellwig
out_close:
201 9ef91a67 Christoph Hellwig
    close(fd);
202 9ef91a67 Christoph Hellwig
    return -errno;
203 83f64091 bellard
}
204 83f64091 bellard
205 90babde0 Christoph Hellwig
static int raw_open(BlockDriverState *bs, const char *filename, int flags)
206 90babde0 Christoph Hellwig
{
207 90babde0 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
208 90babde0 Christoph Hellwig
209 90babde0 Christoph Hellwig
    s->type = FTYPE_FILE;
210 9a2d77ad Christoph Hellwig
    return raw_open_common(bs, filename, flags, 0);
211 90babde0 Christoph Hellwig
}
212 90babde0 Christoph Hellwig
213 83f64091 bellard
/* XXX: use host sector size if necessary with:
214 83f64091 bellard
#ifdef DIOCGSECTORSIZE
215 83f64091 bellard
        {
216 83f64091 bellard
            unsigned int sectorsize = 512;
217 83f64091 bellard
            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
218 83f64091 bellard
                sectorsize > bufsize)
219 83f64091 bellard
                bufsize = sectorsize;
220 83f64091 bellard
        }
221 83f64091 bellard
#endif
222 83f64091 bellard
#ifdef CONFIG_COCOA
223 83f64091 bellard
        u_int32_t   blockSize = 512;
224 83f64091 bellard
        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
225 83f64091 bellard
            bufsize = blockSize;
226 83f64091 bellard
        }
227 83f64091 bellard
#endif
228 83f64091 bellard
*/
229 83f64091 bellard
230 bed5cc52 bellard
/*
231 bed5cc52 bellard
 * offset and count are in bytes, but must be multiples of 512 for files
232 bed5cc52 bellard
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
233 bed5cc52 bellard
 *
234 bed5cc52 bellard
 * This function may be called without alignment if the caller ensures
235 bed5cc52 bellard
 * that O_DIRECT is not in effect.
236 bed5cc52 bellard
 */
237 bed5cc52 bellard
static int raw_pread_aligned(BlockDriverState *bs, int64_t offset,
238 83f64091 bellard
                     uint8_t *buf, int count)
239 83f64091 bellard
{
240 83f64091 bellard
    BDRVRawState *s = bs->opaque;
241 83f64091 bellard
    int ret;
242 3b46e624 ths
243 19cb3738 bellard
    ret = fd_open(bs);
244 19cb3738 bellard
    if (ret < 0)
245 19cb3738 bellard
        return ret;
246 19cb3738 bellard
247 985a03b0 ths
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
248 8c05dbf9 ths
        ++(s->lseek_err_cnt);
249 8c05dbf9 ths
        if(s->lseek_err_cnt <= 10) {
250 92868412 j_mayer
            DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
251 92868412 j_mayer
                              "] lseek failed : %d = %s\n",
252 8c05dbf9 ths
                              s->fd, bs->filename, offset, buf, count,
253 8c05dbf9 ths
                              bs->total_sectors, errno, strerror(errno));
254 8c05dbf9 ths
        }
255 8c05dbf9 ths
        return -1;
256 8c05dbf9 ths
    }
257 8c05dbf9 ths
    s->lseek_err_cnt=0;
258 8c05dbf9 ths
259 83f64091 bellard
    ret = read(s->fd, buf, count);
260 8c05dbf9 ths
    if (ret == count)
261 8c05dbf9 ths
        goto label__raw_read__success;
262 8c05dbf9 ths
263 22afa7b5 Kevin Wolf
    /* Allow reads beyond the end (needed for pwrite) */
264 22afa7b5 Kevin Wolf
    if ((ret == 0) && bs->growable) {
265 22afa7b5 Kevin Wolf
        int64_t size = raw_getlength(bs);
266 22afa7b5 Kevin Wolf
        if (offset >= size) {
267 22afa7b5 Kevin Wolf
            memset(buf, 0, count);
268 22afa7b5 Kevin Wolf
            ret = count;
269 22afa7b5 Kevin Wolf
            goto label__raw_read__success;
270 22afa7b5 Kevin Wolf
        }
271 22afa7b5 Kevin Wolf
    }
272 22afa7b5 Kevin Wolf
273 92868412 j_mayer
    DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
274 92868412 j_mayer
                      "] read failed %d : %d = %s\n",
275 8c05dbf9 ths
                      s->fd, bs->filename, offset, buf, count,
276 8c05dbf9 ths
                      bs->total_sectors, ret, errno, strerror(errno));
277 8c05dbf9 ths
278 8c05dbf9 ths
    /* Try harder for CDrom. */
279 8c05dbf9 ths
    if (bs->type == BDRV_TYPE_CDROM) {
280 8c05dbf9 ths
        lseek(s->fd, offset, SEEK_SET);
281 8c05dbf9 ths
        ret = read(s->fd, buf, count);
282 8c05dbf9 ths
        if (ret == count)
283 8c05dbf9 ths
            goto label__raw_read__success;
284 8c05dbf9 ths
        lseek(s->fd, offset, SEEK_SET);
285 8c05dbf9 ths
        ret = read(s->fd, buf, count);
286 8c05dbf9 ths
        if (ret == count)
287 8c05dbf9 ths
            goto label__raw_read__success;
288 8c05dbf9 ths
289 92868412 j_mayer
        DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
290 92868412 j_mayer
                          "] retry read failed %d : %d = %s\n",
291 8c05dbf9 ths
                          s->fd, bs->filename, offset, buf, count,
292 8c05dbf9 ths
                          bs->total_sectors, ret, errno, strerror(errno));
293 8c05dbf9 ths
    }
294 8c05dbf9 ths
295 8c05dbf9 ths
label__raw_read__success:
296 8c05dbf9 ths
297 94c6d6d8 Christoph Hellwig
    return  (ret < 0) ? -errno : ret;
298 83f64091 bellard
}
299 83f64091 bellard
300 bed5cc52 bellard
/*
301 bed5cc52 bellard
 * offset and count are in bytes, but must be multiples of 512 for files
302 bed5cc52 bellard
 * opened with O_DIRECT. buf must be aligned to 512 bytes then.
303 bed5cc52 bellard
 *
304 bed5cc52 bellard
 * This function may be called without alignment if the caller ensures
305 bed5cc52 bellard
 * that O_DIRECT is not in effect.
306 bed5cc52 bellard
 */
307 bed5cc52 bellard
static int raw_pwrite_aligned(BlockDriverState *bs, int64_t offset,
308 83f64091 bellard
                      const uint8_t *buf, int count)
309 83f64091 bellard
{
310 83f64091 bellard
    BDRVRawState *s = bs->opaque;
311 83f64091 bellard
    int ret;
312 3b46e624 ths
313 19cb3738 bellard
    ret = fd_open(bs);
314 19cb3738 bellard
    if (ret < 0)
315 4141d4c2 aliguori
        return -errno;
316 19cb3738 bellard
317 985a03b0 ths
    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
318 8c05dbf9 ths
        ++(s->lseek_err_cnt);
319 8c05dbf9 ths
        if(s->lseek_err_cnt) {
320 92868412 j_mayer
            DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
321 92868412 j_mayer
                              PRId64 "] lseek failed : %d = %s\n",
322 8c05dbf9 ths
                              s->fd, bs->filename, offset, buf, count,
323 8c05dbf9 ths
                              bs->total_sectors, errno, strerror(errno));
324 8c05dbf9 ths
        }
325 4141d4c2 aliguori
        return -EIO;
326 8c05dbf9 ths
    }
327 8c05dbf9 ths
    s->lseek_err_cnt = 0;
328 8c05dbf9 ths
329 83f64091 bellard
    ret = write(s->fd, buf, count);
330 8c05dbf9 ths
    if (ret == count)
331 8c05dbf9 ths
        goto label__raw_write__success;
332 8c05dbf9 ths
333 92868412 j_mayer
    DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
334 92868412 j_mayer
                      "] write failed %d : %d = %s\n",
335 8c05dbf9 ths
                      s->fd, bs->filename, offset, buf, count,
336 8c05dbf9 ths
                      bs->total_sectors, ret, errno, strerror(errno));
337 8c05dbf9 ths
338 8c05dbf9 ths
label__raw_write__success:
339 8c05dbf9 ths
340 4141d4c2 aliguori
    return  (ret < 0) ? -errno : ret;
341 83f64091 bellard
}
342 83f64091 bellard
343 bed5cc52 bellard
344 bed5cc52 bellard
/*
345 bed5cc52 bellard
 * offset and count are in bytes and possibly not aligned. For files opened
346 bed5cc52 bellard
 * with O_DIRECT, necessary alignments are ensured before calling
347 bed5cc52 bellard
 * raw_pread_aligned to do the actual read.
348 bed5cc52 bellard
 */
349 bed5cc52 bellard
static int raw_pread(BlockDriverState *bs, int64_t offset,
350 bed5cc52 bellard
                     uint8_t *buf, int count)
351 bed5cc52 bellard
{
352 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
353 bed5cc52 bellard
    int size, ret, shift, sum;
354 bed5cc52 bellard
355 bed5cc52 bellard
    sum = 0;
356 bed5cc52 bellard
357 bed5cc52 bellard
    if (s->aligned_buf != NULL)  {
358 bed5cc52 bellard
359 bed5cc52 bellard
        if (offset & 0x1ff) {
360 bed5cc52 bellard
            /* align offset on a 512 bytes boundary */
361 bed5cc52 bellard
362 bed5cc52 bellard
            shift = offset & 0x1ff;
363 bed5cc52 bellard
            size = (shift + count + 0x1ff) & ~0x1ff;
364 bed5cc52 bellard
            if (size > ALIGNED_BUFFER_SIZE)
365 bed5cc52 bellard
                size = ALIGNED_BUFFER_SIZE;
366 bed5cc52 bellard
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, size);
367 bed5cc52 bellard
            if (ret < 0)
368 bed5cc52 bellard
                return ret;
369 bed5cc52 bellard
370 bed5cc52 bellard
            size = 512 - shift;
371 bed5cc52 bellard
            if (size > count)
372 bed5cc52 bellard
                size = count;
373 bed5cc52 bellard
            memcpy(buf, s->aligned_buf + shift, size);
374 bed5cc52 bellard
375 bed5cc52 bellard
            buf += size;
376 bed5cc52 bellard
            offset += size;
377 bed5cc52 bellard
            count -= size;
378 bed5cc52 bellard
            sum += size;
379 bed5cc52 bellard
380 bed5cc52 bellard
            if (count == 0)
381 bed5cc52 bellard
                return sum;
382 bed5cc52 bellard
        }
383 bed5cc52 bellard
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
384 bed5cc52 bellard
385 bed5cc52 bellard
            /* read on aligned buffer */
386 bed5cc52 bellard
387 bed5cc52 bellard
            while (count) {
388 bed5cc52 bellard
389 bed5cc52 bellard
                size = (count + 0x1ff) & ~0x1ff;
390 bed5cc52 bellard
                if (size > ALIGNED_BUFFER_SIZE)
391 bed5cc52 bellard
                    size = ALIGNED_BUFFER_SIZE;
392 bed5cc52 bellard
393 bed5cc52 bellard
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, size);
394 bed5cc52 bellard
                if (ret < 0)
395 bed5cc52 bellard
                    return ret;
396 bed5cc52 bellard
397 bed5cc52 bellard
                size = ret;
398 bed5cc52 bellard
                if (size > count)
399 bed5cc52 bellard
                    size = count;
400 bed5cc52 bellard
401 bed5cc52 bellard
                memcpy(buf, s->aligned_buf, size);
402 bed5cc52 bellard
403 bed5cc52 bellard
                buf += size;
404 bed5cc52 bellard
                offset += size;
405 bed5cc52 bellard
                count -= size;
406 bed5cc52 bellard
                sum += size;
407 bed5cc52 bellard
            }
408 bed5cc52 bellard
409 bed5cc52 bellard
            return sum;
410 bed5cc52 bellard
        }
411 bed5cc52 bellard
    }
412 bed5cc52 bellard
413 bed5cc52 bellard
    return raw_pread_aligned(bs, offset, buf, count) + sum;
414 bed5cc52 bellard
}
415 bed5cc52 bellard
416 eda578e5 aliguori
static int raw_read(BlockDriverState *bs, int64_t sector_num,
417 eda578e5 aliguori
                    uint8_t *buf, int nb_sectors)
418 eda578e5 aliguori
{
419 537a1d4b aliguori
    int ret;
420 537a1d4b aliguori
421 537a1d4b aliguori
    ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
422 537a1d4b aliguori
    if (ret == (nb_sectors * 512))
423 537a1d4b aliguori
        ret = 0;
424 537a1d4b aliguori
    return ret;
425 eda578e5 aliguori
}
426 eda578e5 aliguori
427 bed5cc52 bellard
/*
428 bed5cc52 bellard
 * offset and count are in bytes and possibly not aligned. For files opened
429 bed5cc52 bellard
 * with O_DIRECT, necessary alignments are ensured before calling
430 bed5cc52 bellard
 * raw_pwrite_aligned to do the actual write.
431 bed5cc52 bellard
 */
432 bed5cc52 bellard
static int raw_pwrite(BlockDriverState *bs, int64_t offset,
433 bed5cc52 bellard
                      const uint8_t *buf, int count)
434 bed5cc52 bellard
{
435 bed5cc52 bellard
    BDRVRawState *s = bs->opaque;
436 bed5cc52 bellard
    int size, ret, shift, sum;
437 bed5cc52 bellard
438 bed5cc52 bellard
    sum = 0;
439 bed5cc52 bellard
440 bed5cc52 bellard
    if (s->aligned_buf != NULL) {
441 bed5cc52 bellard
442 bed5cc52 bellard
        if (offset & 0x1ff) {
443 bed5cc52 bellard
            /* align offset on a 512 bytes boundary */
444 bed5cc52 bellard
            shift = offset & 0x1ff;
445 bed5cc52 bellard
            ret = raw_pread_aligned(bs, offset - shift, s->aligned_buf, 512);
446 bed5cc52 bellard
            if (ret < 0)
447 bed5cc52 bellard
                return ret;
448 bed5cc52 bellard
449 bed5cc52 bellard
            size = 512 - shift;
450 bed5cc52 bellard
            if (size > count)
451 bed5cc52 bellard
                size = count;
452 bed5cc52 bellard
            memcpy(s->aligned_buf + shift, buf, size);
453 bed5cc52 bellard
454 bed5cc52 bellard
            ret = raw_pwrite_aligned(bs, offset - shift, s->aligned_buf, 512);
455 bed5cc52 bellard
            if (ret < 0)
456 bed5cc52 bellard
                return ret;
457 bed5cc52 bellard
458 bed5cc52 bellard
            buf += size;
459 bed5cc52 bellard
            offset += size;
460 bed5cc52 bellard
            count -= size;
461 bed5cc52 bellard
            sum += size;
462 bed5cc52 bellard
463 bed5cc52 bellard
            if (count == 0)
464 bed5cc52 bellard
                return sum;
465 bed5cc52 bellard
        }
466 bed5cc52 bellard
        if (count & 0x1ff || (uintptr_t) buf & 0x1ff) {
467 bed5cc52 bellard
468 bed5cc52 bellard
            while ((size = (count & ~0x1ff)) != 0) {
469 bed5cc52 bellard
470 bed5cc52 bellard
                if (size > ALIGNED_BUFFER_SIZE)
471 bed5cc52 bellard
                    size = ALIGNED_BUFFER_SIZE;
472 bed5cc52 bellard
473 bed5cc52 bellard
                memcpy(s->aligned_buf, buf, size);
474 bed5cc52 bellard
475 bed5cc52 bellard
                ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, size);
476 bed5cc52 bellard
                if (ret < 0)
477 bed5cc52 bellard
                    return ret;
478 bed5cc52 bellard
479 bed5cc52 bellard
                buf += ret;
480 bed5cc52 bellard
                offset += ret;
481 bed5cc52 bellard
                count -= ret;
482 bed5cc52 bellard
                sum += ret;
483 bed5cc52 bellard
            }
484 bed5cc52 bellard
            /* here, count < 512 because (count & ~0x1ff) == 0 */
485 bed5cc52 bellard
            if (count) {
486 bed5cc52 bellard
                ret = raw_pread_aligned(bs, offset, s->aligned_buf, 512);
487 bed5cc52 bellard
                if (ret < 0)
488 bed5cc52 bellard
                    return ret;
489 bed5cc52 bellard
                 memcpy(s->aligned_buf, buf, count);
490 bed5cc52 bellard
491 bed5cc52 bellard
                 ret = raw_pwrite_aligned(bs, offset, s->aligned_buf, 512);
492 bed5cc52 bellard
                 if (ret < 0)
493 bed5cc52 bellard
                     return ret;
494 bed5cc52 bellard
                 if (count < ret)
495 bed5cc52 bellard
                     ret = count;
496 bed5cc52 bellard
497 bed5cc52 bellard
                 sum += ret;
498 bed5cc52 bellard
            }
499 bed5cc52 bellard
            return sum;
500 bed5cc52 bellard
        }
501 bed5cc52 bellard
    }
502 bed5cc52 bellard
    return raw_pwrite_aligned(bs, offset, buf, count) + sum;
503 bed5cc52 bellard
}
504 bed5cc52 bellard
505 eda578e5 aliguori
static int raw_write(BlockDriverState *bs, int64_t sector_num,
506 eda578e5 aliguori
                     const uint8_t *buf, int nb_sectors)
507 eda578e5 aliguori
{
508 537a1d4b aliguori
    int ret;
509 537a1d4b aliguori
    ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
510 537a1d4b aliguori
    if (ret == (nb_sectors * 512))
511 537a1d4b aliguori
        ret = 0;
512 537a1d4b aliguori
    return ret;
513 eda578e5 aliguori
}
514 eda578e5 aliguori
515 9ef91a67 Christoph Hellwig
/*
516 9ef91a67 Christoph Hellwig
 * Check if all memory in this vector is sector aligned.
517 9ef91a67 Christoph Hellwig
 */
518 9ef91a67 Christoph Hellwig
static int qiov_is_aligned(QEMUIOVector *qiov)
519 a76bab49 aliguori
{
520 9ef91a67 Christoph Hellwig
    int i;
521 83f64091 bellard
522 9ef91a67 Christoph Hellwig
    for (i = 0; i < qiov->niov; i++) {
523 9ef91a67 Christoph Hellwig
        if ((uintptr_t) qiov->iov[i].iov_base % 512) {
524 9ef91a67 Christoph Hellwig
            return 0;
525 c16b5a2c Christoph Hellwig
        }
526 c16b5a2c Christoph Hellwig
    }
527 c16b5a2c Christoph Hellwig
528 9ef91a67 Christoph Hellwig
    return 1;
529 c16b5a2c Christoph Hellwig
}
530 c16b5a2c Christoph Hellwig
531 9ef91a67 Christoph Hellwig
static BlockDriverAIOCB *raw_aio_submit(BlockDriverState *bs,
532 9ef91a67 Christoph Hellwig
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
533 9ef91a67 Christoph Hellwig
        BlockDriverCompletionFunc *cb, void *opaque, int type)
534 83f64091 bellard
{
535 ce1a14dc pbrook
    BDRVRawState *s = bs->opaque;
536 ce1a14dc pbrook
537 19cb3738 bellard
    if (fd_open(bs) < 0)
538 19cb3738 bellard
        return NULL;
539 19cb3738 bellard
540 f141eafe aliguori
    /*
541 f141eafe aliguori
     * If O_DIRECT is used the buffer needs to be aligned on a sector
542 9ef91a67 Christoph Hellwig
     * boundary.  Check if this is the case or telll the low-level
543 9ef91a67 Christoph Hellwig
     * driver that it needs to copy the buffer.
544 f141eafe aliguori
     */
545 5c6c3a6c Christoph Hellwig
    if (s->aligned_buf) {
546 5c6c3a6c Christoph Hellwig
        if (!qiov_is_aligned(qiov)) {
547 5c6c3a6c Christoph Hellwig
            type |= QEMU_AIO_MISALIGNED;
548 e44bd6fc Stefan Weil
#ifdef CONFIG_LINUX_AIO
549 5c6c3a6c Christoph Hellwig
        } else if (s->use_aio) {
550 5c6c3a6c Christoph Hellwig
            return laio_submit(bs, s->aio_ctx, s->fd, sector_num, qiov,
551 e44bd6fc Stefan Weil
                               nb_sectors, cb, opaque, type);
552 e44bd6fc Stefan Weil
#endif
553 5c6c3a6c Christoph Hellwig
        }
554 9ef91a67 Christoph Hellwig
    }
555 f141eafe aliguori
556 1e5b9d2f Kevin Wolf
    return paio_submit(bs, s->fd, sector_num, qiov, nb_sectors,
557 9ef91a67 Christoph Hellwig
                       cb, opaque, type);
558 83f64091 bellard
}
559 83f64091 bellard
560 f141eafe aliguori
static BlockDriverAIOCB *raw_aio_readv(BlockDriverState *bs,
561 f141eafe aliguori
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
562 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
563 83f64091 bellard
{
564 9ef91a67 Christoph Hellwig
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
565 9ef91a67 Christoph Hellwig
                          cb, opaque, QEMU_AIO_READ);
566 83f64091 bellard
}
567 83f64091 bellard
568 f141eafe aliguori
static BlockDriverAIOCB *raw_aio_writev(BlockDriverState *bs,
569 f141eafe aliguori
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
570 ce1a14dc pbrook
        BlockDriverCompletionFunc *cb, void *opaque)
571 83f64091 bellard
{
572 9ef91a67 Christoph Hellwig
    return raw_aio_submit(bs, sector_num, qiov, nb_sectors,
573 9ef91a67 Christoph Hellwig
                          cb, opaque, QEMU_AIO_WRITE);
574 83f64091 bellard
}
575 53538725 aliguori
576 b2e12bc6 Christoph Hellwig
static BlockDriverAIOCB *raw_aio_flush(BlockDriverState *bs,
577 b2e12bc6 Christoph Hellwig
        BlockDriverCompletionFunc *cb, void *opaque)
578 b2e12bc6 Christoph Hellwig
{
579 b2e12bc6 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
580 b2e12bc6 Christoph Hellwig
581 b2e12bc6 Christoph Hellwig
    if (fd_open(bs) < 0)
582 b2e12bc6 Christoph Hellwig
        return NULL;
583 b2e12bc6 Christoph Hellwig
584 1e5b9d2f Kevin Wolf
    return paio_submit(bs, s->fd, 0, NULL, 0, cb, opaque, QEMU_AIO_FLUSH);
585 b2e12bc6 Christoph Hellwig
}
586 b2e12bc6 Christoph Hellwig
587 83f64091 bellard
static void raw_close(BlockDriverState *bs)
588 83f64091 bellard
{
589 83f64091 bellard
    BDRVRawState *s = bs->opaque;
590 19cb3738 bellard
    if (s->fd >= 0) {
591 19cb3738 bellard
        close(s->fd);
592 19cb3738 bellard
        s->fd = -1;
593 bed5cc52 bellard
        if (s->aligned_buf != NULL)
594 bed5cc52 bellard
            qemu_free(s->aligned_buf);
595 19cb3738 bellard
    }
596 83f64091 bellard
}
597 83f64091 bellard
598 83f64091 bellard
static int raw_truncate(BlockDriverState *bs, int64_t offset)
599 83f64091 bellard
{
600 83f64091 bellard
    BDRVRawState *s = bs->opaque;
601 19cb3738 bellard
    if (s->type != FTYPE_FILE)
602 19cb3738 bellard
        return -ENOTSUP;
603 83f64091 bellard
    if (ftruncate(s->fd, offset) < 0)
604 83f64091 bellard
        return -errno;
605 83f64091 bellard
    return 0;
606 83f64091 bellard
}
607 83f64091 bellard
608 128ab2ff blueswir1
#ifdef __OpenBSD__
609 128ab2ff blueswir1
static int64_t raw_getlength(BlockDriverState *bs)
610 128ab2ff blueswir1
{
611 128ab2ff blueswir1
    BDRVRawState *s = bs->opaque;
612 128ab2ff blueswir1
    int fd = s->fd;
613 128ab2ff blueswir1
    struct stat st;
614 128ab2ff blueswir1
615 128ab2ff blueswir1
    if (fstat(fd, &st))
616 128ab2ff blueswir1
        return -1;
617 128ab2ff blueswir1
    if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
618 128ab2ff blueswir1
        struct disklabel dl;
619 128ab2ff blueswir1
620 128ab2ff blueswir1
        if (ioctl(fd, DIOCGDINFO, &dl))
621 128ab2ff blueswir1
            return -1;
622 128ab2ff blueswir1
        return (uint64_t)dl.d_secsize *
623 128ab2ff blueswir1
            dl.d_partitions[DISKPART(st.st_rdev)].p_size;
624 128ab2ff blueswir1
    } else
625 128ab2ff blueswir1
        return st.st_size;
626 128ab2ff blueswir1
}
627 128ab2ff blueswir1
#else /* !__OpenBSD__ */
628 83f64091 bellard
static int64_t  raw_getlength(BlockDriverState *bs)
629 83f64091 bellard
{
630 83f64091 bellard
    BDRVRawState *s = bs->opaque;
631 83f64091 bellard
    int fd = s->fd;
632 83f64091 bellard
    int64_t size;
633 71e72a19 Juan Quintela
#ifdef CONFIG_BSD
634 83f64091 bellard
    struct stat sb;
635 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
636 9f23011a blueswir1
    int reopened = 0;
637 9f23011a blueswir1
#endif
638 83f64091 bellard
#endif
639 83f64091 bellard
#ifdef __sun__
640 83f64091 bellard
    struct dk_minfo minfo;
641 83f64091 bellard
    int rv;
642 83f64091 bellard
#endif
643 19cb3738 bellard
    int ret;
644 19cb3738 bellard
645 19cb3738 bellard
    ret = fd_open(bs);
646 19cb3738 bellard
    if (ret < 0)
647 19cb3738 bellard
        return ret;
648 83f64091 bellard
649 71e72a19 Juan Quintela
#ifdef CONFIG_BSD
650 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
651 9f23011a blueswir1
again:
652 9f23011a blueswir1
#endif
653 83f64091 bellard
    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
654 83f64091 bellard
#ifdef DIOCGMEDIASIZE
655 83f64091 bellard
        if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
656 c5e97233 blueswir1
#elif defined(DIOCGPART)
657 c5e97233 blueswir1
        {
658 c5e97233 blueswir1
                struct partinfo pi;
659 c5e97233 blueswir1
                if (ioctl(fd, DIOCGPART, &pi) == 0)
660 c5e97233 blueswir1
                        size = pi.media_size;
661 c5e97233 blueswir1
                else
662 c5e97233 blueswir1
                        size = 0;
663 c5e97233 blueswir1
        }
664 c5e97233 blueswir1
        if (size == 0)
665 83f64091 bellard
#endif
666 83f64091 bellard
#ifdef CONFIG_COCOA
667 83f64091 bellard
        size = LONG_LONG_MAX;
668 83f64091 bellard
#else
669 83f64091 bellard
        size = lseek(fd, 0LL, SEEK_END);
670 83f64091 bellard
#endif
671 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
672 9f23011a blueswir1
        switch(s->type) {
673 9f23011a blueswir1
        case FTYPE_CD:
674 9f23011a blueswir1
            /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
675 9f23011a blueswir1
            if (size == 2048LL * (unsigned)-1)
676 9f23011a blueswir1
                size = 0;
677 9f23011a blueswir1
            /* XXX no disc?  maybe we need to reopen... */
678 f3a5d3f8 Christoph Hellwig
            if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
679 9f23011a blueswir1
                reopened = 1;
680 9f23011a blueswir1
                goto again;
681 9f23011a blueswir1
            }
682 9f23011a blueswir1
        }
683 9f23011a blueswir1
#endif
684 83f64091 bellard
    } else
685 83f64091 bellard
#endif
686 83f64091 bellard
#ifdef __sun__
687 83f64091 bellard
    /*
688 83f64091 bellard
     * use the DKIOCGMEDIAINFO ioctl to read the size.
689 83f64091 bellard
     */
690 83f64091 bellard
    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
691 83f64091 bellard
    if ( rv != -1 ) {
692 83f64091 bellard
        size = minfo.dki_lbsize * minfo.dki_capacity;
693 83f64091 bellard
    } else /* there are reports that lseek on some devices
694 83f64091 bellard
              fails, but irc discussion said that contingency
695 83f64091 bellard
              on contingency was overkill */
696 83f64091 bellard
#endif
697 83f64091 bellard
    {
698 83f64091 bellard
        size = lseek(fd, 0, SEEK_END);
699 83f64091 bellard
    }
700 83f64091 bellard
    return size;
701 83f64091 bellard
}
702 128ab2ff blueswir1
#endif
703 83f64091 bellard
704 0e7e1989 Kevin Wolf
static int raw_create(const char *filename, QEMUOptionParameter *options)
705 83f64091 bellard
{
706 83f64091 bellard
    int fd;
707 1e37d059 Stefan Weil
    int result = 0;
708 0e7e1989 Kevin Wolf
    int64_t total_size = 0;
709 83f64091 bellard
710 0e7e1989 Kevin Wolf
    /* Read out options */
711 0e7e1989 Kevin Wolf
    while (options && options->name) {
712 0e7e1989 Kevin Wolf
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
713 0e7e1989 Kevin Wolf
            total_size = options->value.n / 512;
714 0e7e1989 Kevin Wolf
        }
715 0e7e1989 Kevin Wolf
        options++;
716 0e7e1989 Kevin Wolf
    }
717 83f64091 bellard
718 5fafdf24 ths
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
719 83f64091 bellard
              0644);
720 1e37d059 Stefan Weil
    if (fd < 0) {
721 1e37d059 Stefan Weil
        result = -errno;
722 1e37d059 Stefan Weil
    } else {
723 1e37d059 Stefan Weil
        if (ftruncate(fd, total_size * 512) != 0) {
724 1e37d059 Stefan Weil
            result = -errno;
725 1e37d059 Stefan Weil
        }
726 1e37d059 Stefan Weil
        if (close(fd) != 0) {
727 1e37d059 Stefan Weil
            result = -errno;
728 1e37d059 Stefan Weil
        }
729 1e37d059 Stefan Weil
    }
730 1e37d059 Stefan Weil
    return result;
731 83f64091 bellard
}
732 83f64091 bellard
733 83f64091 bellard
static void raw_flush(BlockDriverState *bs)
734 83f64091 bellard
{
735 83f64091 bellard
    BDRVRawState *s = bs->opaque;
736 6f1953c4 Christoph Hellwig
    qemu_fdatasync(s->fd);
737 83f64091 bellard
}
738 83f64091 bellard
739 0e7e1989 Kevin Wolf
740 0e7e1989 Kevin Wolf
static QEMUOptionParameter raw_create_options[] = {
741 db08adf5 Kevin Wolf
    {
742 db08adf5 Kevin Wolf
        .name = BLOCK_OPT_SIZE,
743 db08adf5 Kevin Wolf
        .type = OPT_SIZE,
744 db08adf5 Kevin Wolf
        .help = "Virtual disk size"
745 db08adf5 Kevin Wolf
    },
746 0e7e1989 Kevin Wolf
    { NULL }
747 0e7e1989 Kevin Wolf
};
748 0e7e1989 Kevin Wolf
749 5efa9d5a Anthony Liguori
static BlockDriver bdrv_raw = {
750 856ae5c3 blueswir1
    .format_name = "raw",
751 856ae5c3 blueswir1
    .instance_size = sizeof(BDRVRawState),
752 856ae5c3 blueswir1
    .bdrv_probe = NULL, /* no probe for protocols */
753 856ae5c3 blueswir1
    .bdrv_open = raw_open,
754 856ae5c3 blueswir1
    .bdrv_read = raw_read,
755 856ae5c3 blueswir1
    .bdrv_write = raw_write,
756 856ae5c3 blueswir1
    .bdrv_close = raw_close,
757 856ae5c3 blueswir1
    .bdrv_create = raw_create,
758 856ae5c3 blueswir1
    .bdrv_flush = raw_flush,
759 3b46e624 ths
760 f141eafe aliguori
    .bdrv_aio_readv = raw_aio_readv,
761 f141eafe aliguori
    .bdrv_aio_writev = raw_aio_writev,
762 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush = raw_aio_flush,
763 3c529d93 aliguori
764 83f64091 bellard
    .bdrv_truncate = raw_truncate,
765 83f64091 bellard
    .bdrv_getlength = raw_getlength,
766 0e7e1989 Kevin Wolf
767 0e7e1989 Kevin Wolf
    .create_options = raw_create_options,
768 83f64091 bellard
};
769 83f64091 bellard
770 19cb3738 bellard
/***********************************************/
771 19cb3738 bellard
/* host device */
772 19cb3738 bellard
773 19cb3738 bellard
#ifdef CONFIG_COCOA
774 19cb3738 bellard
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
775 19cb3738 bellard
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
776 19cb3738 bellard
777 19cb3738 bellard
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
778 19cb3738 bellard
{
779 5fafdf24 ths
    kern_return_t       kernResult;
780 19cb3738 bellard
    mach_port_t     masterPort;
781 19cb3738 bellard
    CFMutableDictionaryRef  classesToMatch;
782 19cb3738 bellard
783 19cb3738 bellard
    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
784 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult ) {
785 19cb3738 bellard
        printf( "IOMasterPort returned %d\n", kernResult );
786 19cb3738 bellard
    }
787 3b46e624 ths
788 5fafdf24 ths
    classesToMatch = IOServiceMatching( kIOCDMediaClass );
789 19cb3738 bellard
    if ( classesToMatch == NULL ) {
790 19cb3738 bellard
        printf( "IOServiceMatching returned a NULL dictionary.\n" );
791 19cb3738 bellard
    } else {
792 19cb3738 bellard
    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
793 19cb3738 bellard
    }
794 19cb3738 bellard
    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
795 19cb3738 bellard
    if ( KERN_SUCCESS != kernResult )
796 19cb3738 bellard
    {
797 19cb3738 bellard
        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
798 19cb3738 bellard
    }
799 3b46e624 ths
800 19cb3738 bellard
    return kernResult;
801 19cb3738 bellard
}
802 19cb3738 bellard
803 19cb3738 bellard
kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
804 19cb3738 bellard
{
805 19cb3738 bellard
    io_object_t     nextMedia;
806 19cb3738 bellard
    kern_return_t   kernResult = KERN_FAILURE;
807 19cb3738 bellard
    *bsdPath = '\0';
808 19cb3738 bellard
    nextMedia = IOIteratorNext( mediaIterator );
809 19cb3738 bellard
    if ( nextMedia )
810 19cb3738 bellard
    {
811 19cb3738 bellard
        CFTypeRef   bsdPathAsCFString;
812 19cb3738 bellard
    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
813 19cb3738 bellard
        if ( bsdPathAsCFString ) {
814 19cb3738 bellard
            size_t devPathLength;
815 19cb3738 bellard
            strcpy( bsdPath, _PATH_DEV );
816 19cb3738 bellard
            strcat( bsdPath, "r" );
817 19cb3738 bellard
            devPathLength = strlen( bsdPath );
818 19cb3738 bellard
            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
819 19cb3738 bellard
                kernResult = KERN_SUCCESS;
820 19cb3738 bellard
            }
821 19cb3738 bellard
            CFRelease( bsdPathAsCFString );
822 19cb3738 bellard
        }
823 19cb3738 bellard
        IOObjectRelease( nextMedia );
824 19cb3738 bellard
    }
825 3b46e624 ths
826 19cb3738 bellard
    return kernResult;
827 19cb3738 bellard
}
828 19cb3738 bellard
829 19cb3738 bellard
#endif
830 19cb3738 bellard
831 508c7cb3 Christoph Hellwig
static int hdev_probe_device(const char *filename)
832 508c7cb3 Christoph Hellwig
{
833 508c7cb3 Christoph Hellwig
    struct stat st;
834 508c7cb3 Christoph Hellwig
835 508c7cb3 Christoph Hellwig
    /* allow a dedicated CD-ROM driver to match with a higher priority */
836 508c7cb3 Christoph Hellwig
    if (strstart(filename, "/dev/cdrom", NULL))
837 508c7cb3 Christoph Hellwig
        return 50;
838 508c7cb3 Christoph Hellwig
839 508c7cb3 Christoph Hellwig
    if (stat(filename, &st) >= 0 &&
840 508c7cb3 Christoph Hellwig
            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
841 508c7cb3 Christoph Hellwig
        return 100;
842 508c7cb3 Christoph Hellwig
    }
843 508c7cb3 Christoph Hellwig
844 508c7cb3 Christoph Hellwig
    return 0;
845 508c7cb3 Christoph Hellwig
}
846 508c7cb3 Christoph Hellwig
847 19cb3738 bellard
static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
848 19cb3738 bellard
{
849 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
850 a76bab49 aliguori
851 19cb3738 bellard
#ifdef CONFIG_COCOA
852 19cb3738 bellard
    if (strstart(filename, "/dev/cdrom", NULL)) {
853 19cb3738 bellard
        kern_return_t kernResult;
854 19cb3738 bellard
        io_iterator_t mediaIterator;
855 19cb3738 bellard
        char bsdPath[ MAXPATHLEN ];
856 19cb3738 bellard
        int fd;
857 5fafdf24 ths
858 19cb3738 bellard
        kernResult = FindEjectableCDMedia( &mediaIterator );
859 19cb3738 bellard
        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
860 3b46e624 ths
861 19cb3738 bellard
        if ( bsdPath[ 0 ] != '\0' ) {
862 19cb3738 bellard
            strcat(bsdPath,"s0");
863 19cb3738 bellard
            /* some CDs don't have a partition 0 */
864 19cb3738 bellard
            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
865 19cb3738 bellard
            if (fd < 0) {
866 19cb3738 bellard
                bsdPath[strlen(bsdPath)-1] = '1';
867 19cb3738 bellard
            } else {
868 19cb3738 bellard
                close(fd);
869 19cb3738 bellard
            }
870 19cb3738 bellard
            filename = bsdPath;
871 19cb3738 bellard
        }
872 3b46e624 ths
873 19cb3738 bellard
        if ( mediaIterator )
874 19cb3738 bellard
            IOObjectRelease( mediaIterator );
875 19cb3738 bellard
    }
876 19cb3738 bellard
#endif
877 19cb3738 bellard
878 19cb3738 bellard
    s->type = FTYPE_FILE;
879 4dd75c70 Christoph Hellwig
#if defined(__linux__)
880 f3a5d3f8 Christoph Hellwig
    if (strstart(filename, "/dev/sg", NULL)) {
881 985a03b0 ths
        bs->sg = 1;
882 19cb3738 bellard
    }
883 19cb3738 bellard
#endif
884 90babde0 Christoph Hellwig
885 19a3da7f Blue Swirl
    return raw_open_common(bs, filename, flags, 0);
886 19cb3738 bellard
}
887 19cb3738 bellard
888 03ff3ca3 aliguori
#if defined(__linux__)
889 19cb3738 bellard
/* Note: we do not have a reliable method to detect if the floppy is
890 19cb3738 bellard
   present. The current method is to try to open the floppy at every
891 19cb3738 bellard
   I/O and to keep it opened during a few hundreds of ms. */
892 19cb3738 bellard
static int fd_open(BlockDriverState *bs)
893 19cb3738 bellard
{
894 19cb3738 bellard
    BDRVRawState *s = bs->opaque;
895 19cb3738 bellard
    int last_media_present;
896 19cb3738 bellard
897 19cb3738 bellard
    if (s->type != FTYPE_FD)
898 19cb3738 bellard
        return 0;
899 19cb3738 bellard
    last_media_present = (s->fd >= 0);
900 5fafdf24 ths
    if (s->fd >= 0 &&
901 19cb3738 bellard
        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
902 19cb3738 bellard
        close(s->fd);
903 19cb3738 bellard
        s->fd = -1;
904 19cb3738 bellard
#ifdef DEBUG_FLOPPY
905 19cb3738 bellard
        printf("Floppy closed\n");
906 19cb3738 bellard
#endif
907 19cb3738 bellard
    }
908 19cb3738 bellard
    if (s->fd < 0) {
909 5fafdf24 ths
        if (s->fd_got_error &&
910 19cb3738 bellard
            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
911 19cb3738 bellard
#ifdef DEBUG_FLOPPY
912 19cb3738 bellard
            printf("No floppy (open delayed)\n");
913 19cb3738 bellard
#endif
914 19cb3738 bellard
            return -EIO;
915 19cb3738 bellard
        }
916 0e1d8f4c Christoph Hellwig
        s->fd = open(bs->filename, s->open_flags & ~O_NONBLOCK);
917 19cb3738 bellard
        if (s->fd < 0) {
918 19cb3738 bellard
            s->fd_error_time = qemu_get_clock(rt_clock);
919 19cb3738 bellard
            s->fd_got_error = 1;
920 19cb3738 bellard
            if (last_media_present)
921 19cb3738 bellard
                s->fd_media_changed = 1;
922 19cb3738 bellard
#ifdef DEBUG_FLOPPY
923 19cb3738 bellard
            printf("No floppy\n");
924 19cb3738 bellard
#endif
925 19cb3738 bellard
            return -EIO;
926 19cb3738 bellard
        }
927 19cb3738 bellard
#ifdef DEBUG_FLOPPY
928 19cb3738 bellard
        printf("Floppy opened\n");
929 19cb3738 bellard
#endif
930 19cb3738 bellard
    }
931 19cb3738 bellard
    if (!last_media_present)
932 19cb3738 bellard
        s->fd_media_changed = 1;
933 19cb3738 bellard
    s->fd_open_time = qemu_get_clock(rt_clock);
934 19cb3738 bellard
    s->fd_got_error = 0;
935 19cb3738 bellard
    return 0;
936 19cb3738 bellard
}
937 19cb3738 bellard
938 63ec93db Christoph Hellwig
static int hdev_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
939 985a03b0 ths
{
940 985a03b0 ths
    BDRVRawState *s = bs->opaque;
941 985a03b0 ths
942 985a03b0 ths
    return ioctl(s->fd, req, buf);
943 985a03b0 ths
}
944 221f715d aliguori
945 63ec93db Christoph Hellwig
static BlockDriverAIOCB *hdev_aio_ioctl(BlockDriverState *bs,
946 221f715d aliguori
        unsigned long int req, void *buf,
947 221f715d aliguori
        BlockDriverCompletionFunc *cb, void *opaque)
948 221f715d aliguori
{
949 f141eafe aliguori
    BDRVRawState *s = bs->opaque;
950 221f715d aliguori
951 f141eafe aliguori
    if (fd_open(bs) < 0)
952 f141eafe aliguori
        return NULL;
953 9ef91a67 Christoph Hellwig
    return paio_ioctl(bs, s->fd, req, buf, cb, opaque);
954 221f715d aliguori
}
955 221f715d aliguori
956 a167ba50 Aurelien Jarno
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
957 9f23011a blueswir1
static int fd_open(BlockDriverState *bs)
958 9f23011a blueswir1
{
959 9f23011a blueswir1
    BDRVRawState *s = bs->opaque;
960 9f23011a blueswir1
961 9f23011a blueswir1
    /* this is just to ensure s->fd is sane (its called by io ops) */
962 9f23011a blueswir1
    if (s->fd >= 0)
963 9f23011a blueswir1
        return 0;
964 9f23011a blueswir1
    return -EIO;
965 9f23011a blueswir1
}
966 9f23011a blueswir1
#else /* !linux && !FreeBSD */
967 19cb3738 bellard
968 08af02e2 aliguori
static int fd_open(BlockDriverState *bs)
969 08af02e2 aliguori
{
970 08af02e2 aliguori
    return 0;
971 08af02e2 aliguori
}
972 08af02e2 aliguori
973 221f715d aliguori
#endif /* !linux && !FreeBSD */
974 04eeb8b6 aliguori
975 0e7e1989 Kevin Wolf
static int hdev_create(const char *filename, QEMUOptionParameter *options)
976 93c65b47 aliguori
{
977 93c65b47 aliguori
    int fd;
978 93c65b47 aliguori
    int ret = 0;
979 93c65b47 aliguori
    struct stat stat_buf;
980 0e7e1989 Kevin Wolf
    int64_t total_size = 0;
981 93c65b47 aliguori
982 0e7e1989 Kevin Wolf
    /* Read out options */
983 0e7e1989 Kevin Wolf
    while (options && options->name) {
984 0e7e1989 Kevin Wolf
        if (!strcmp(options->name, "size")) {
985 0e7e1989 Kevin Wolf
            total_size = options->value.n / 512;
986 0e7e1989 Kevin Wolf
        }
987 0e7e1989 Kevin Wolf
        options++;
988 0e7e1989 Kevin Wolf
    }
989 93c65b47 aliguori
990 93c65b47 aliguori
    fd = open(filename, O_WRONLY | O_BINARY);
991 93c65b47 aliguori
    if (fd < 0)
992 93c65b47 aliguori
        return -EIO;
993 93c65b47 aliguori
994 93c65b47 aliguori
    if (fstat(fd, &stat_buf) < 0)
995 93c65b47 aliguori
        ret = -EIO;
996 4099df58 Christoph Hellwig
    else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
997 93c65b47 aliguori
        ret = -EIO;
998 93c65b47 aliguori
    else if (lseek(fd, 0, SEEK_END) < total_size * 512)
999 93c65b47 aliguori
        ret = -ENOSPC;
1000 93c65b47 aliguori
1001 93c65b47 aliguori
    close(fd);
1002 93c65b47 aliguori
    return ret;
1003 93c65b47 aliguori
}
1004 93c65b47 aliguori
1005 5efa9d5a Anthony Liguori
static BlockDriver bdrv_host_device = {
1006 0b4ce02e Kevin Wolf
    .format_name        = "host_device",
1007 0b4ce02e Kevin Wolf
    .instance_size      = sizeof(BDRVRawState),
1008 0b4ce02e Kevin Wolf
    .bdrv_probe_device  = hdev_probe_device,
1009 0b4ce02e Kevin Wolf
    .bdrv_open          = hdev_open,
1010 0b4ce02e Kevin Wolf
    .bdrv_close         = raw_close,
1011 93c65b47 aliguori
    .bdrv_create        = hdev_create,
1012 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1013 12c09b8c Kevin Wolf
    .no_zero_init       = 1,
1014 0b4ce02e Kevin Wolf
    .bdrv_flush         = raw_flush,
1015 3b46e624 ths
1016 f141eafe aliguori
    .bdrv_aio_readv        = raw_aio_readv,
1017 f141eafe aliguori
    .bdrv_aio_writev        = raw_aio_writev,
1018 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1019 3c529d93 aliguori
1020 eda578e5 aliguori
    .bdrv_read          = raw_read,
1021 eda578e5 aliguori
    .bdrv_write         = raw_write,
1022 e60f469c aurel32
    .bdrv_getlength        = raw_getlength,
1023 19cb3738 bellard
1024 f3a5d3f8 Christoph Hellwig
    /* generic scsi device */
1025 63ec93db Christoph Hellwig
#ifdef __linux__
1026 63ec93db Christoph Hellwig
    .bdrv_ioctl         = hdev_ioctl,
1027 63ec93db Christoph Hellwig
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1028 63ec93db Christoph Hellwig
#endif
1029 f3a5d3f8 Christoph Hellwig
};
1030 f3a5d3f8 Christoph Hellwig
1031 f3a5d3f8 Christoph Hellwig
#ifdef __linux__
1032 f3a5d3f8 Christoph Hellwig
static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
1033 f3a5d3f8 Christoph Hellwig
{
1034 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1035 f3a5d3f8 Christoph Hellwig
    int ret;
1036 f3a5d3f8 Christoph Hellwig
1037 f3a5d3f8 Christoph Hellwig
    s->type = FTYPE_FD;
1038 f3a5d3f8 Christoph Hellwig
1039 19a3da7f Blue Swirl
    /* open will not fail even if no floppy is inserted, so add O_NONBLOCK */
1040 19a3da7f Blue Swirl
    ret = raw_open_common(bs, filename, flags, O_NONBLOCK);
1041 f3a5d3f8 Christoph Hellwig
    if (ret)
1042 f3a5d3f8 Christoph Hellwig
        return ret;
1043 f3a5d3f8 Christoph Hellwig
1044 f3a5d3f8 Christoph Hellwig
    /* close fd so that we can reopen it as needed */
1045 f3a5d3f8 Christoph Hellwig
    close(s->fd);
1046 f3a5d3f8 Christoph Hellwig
    s->fd = -1;
1047 f3a5d3f8 Christoph Hellwig
    s->fd_media_changed = 1;
1048 f3a5d3f8 Christoph Hellwig
1049 f3a5d3f8 Christoph Hellwig
    return 0;
1050 f3a5d3f8 Christoph Hellwig
}
1051 f3a5d3f8 Christoph Hellwig
1052 508c7cb3 Christoph Hellwig
static int floppy_probe_device(const char *filename)
1053 508c7cb3 Christoph Hellwig
{
1054 2ebf7c4b Cole Robinson
    int fd, ret;
1055 2ebf7c4b Cole Robinson
    int prio = 0;
1056 2ebf7c4b Cole Robinson
    struct floppy_struct fdparam;
1057 2ebf7c4b Cole Robinson
1058 508c7cb3 Christoph Hellwig
    if (strstart(filename, "/dev/fd", NULL))
1059 2ebf7c4b Cole Robinson
        prio = 50;
1060 2ebf7c4b Cole Robinson
1061 2ebf7c4b Cole Robinson
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1062 2ebf7c4b Cole Robinson
    if (fd < 0) {
1063 2ebf7c4b Cole Robinson
        goto out;
1064 2ebf7c4b Cole Robinson
    }
1065 2ebf7c4b Cole Robinson
1066 2ebf7c4b Cole Robinson
    /* Attempt to detect via a floppy specific ioctl */
1067 2ebf7c4b Cole Robinson
    ret = ioctl(fd, FDGETPRM, &fdparam);
1068 2ebf7c4b Cole Robinson
    if (ret >= 0)
1069 2ebf7c4b Cole Robinson
        prio = 100;
1070 2ebf7c4b Cole Robinson
1071 2ebf7c4b Cole Robinson
    close(fd);
1072 2ebf7c4b Cole Robinson
out:
1073 2ebf7c4b Cole Robinson
    return prio;
1074 508c7cb3 Christoph Hellwig
}
1075 508c7cb3 Christoph Hellwig
1076 508c7cb3 Christoph Hellwig
1077 f3a5d3f8 Christoph Hellwig
static int floppy_is_inserted(BlockDriverState *bs)
1078 f3a5d3f8 Christoph Hellwig
{
1079 f3a5d3f8 Christoph Hellwig
    return fd_open(bs) >= 0;
1080 f3a5d3f8 Christoph Hellwig
}
1081 f3a5d3f8 Christoph Hellwig
1082 f3a5d3f8 Christoph Hellwig
static int floppy_media_changed(BlockDriverState *bs)
1083 f3a5d3f8 Christoph Hellwig
{
1084 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1085 f3a5d3f8 Christoph Hellwig
    int ret;
1086 f3a5d3f8 Christoph Hellwig
1087 f3a5d3f8 Christoph Hellwig
    /*
1088 f3a5d3f8 Christoph Hellwig
     * XXX: we do not have a true media changed indication.
1089 f3a5d3f8 Christoph Hellwig
     * It does not work if the floppy is changed without trying to read it.
1090 f3a5d3f8 Christoph Hellwig
     */
1091 f3a5d3f8 Christoph Hellwig
    fd_open(bs);
1092 f3a5d3f8 Christoph Hellwig
    ret = s->fd_media_changed;
1093 f3a5d3f8 Christoph Hellwig
    s->fd_media_changed = 0;
1094 f3a5d3f8 Christoph Hellwig
#ifdef DEBUG_FLOPPY
1095 f3a5d3f8 Christoph Hellwig
    printf("Floppy changed=%d\n", ret);
1096 f3a5d3f8 Christoph Hellwig
#endif
1097 f3a5d3f8 Christoph Hellwig
    return ret;
1098 f3a5d3f8 Christoph Hellwig
}
1099 f3a5d3f8 Christoph Hellwig
1100 f3a5d3f8 Christoph Hellwig
static int floppy_eject(BlockDriverState *bs, int eject_flag)
1101 f3a5d3f8 Christoph Hellwig
{
1102 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1103 f3a5d3f8 Christoph Hellwig
    int fd;
1104 f3a5d3f8 Christoph Hellwig
1105 f3a5d3f8 Christoph Hellwig
    if (s->fd >= 0) {
1106 f3a5d3f8 Christoph Hellwig
        close(s->fd);
1107 f3a5d3f8 Christoph Hellwig
        s->fd = -1;
1108 f3a5d3f8 Christoph Hellwig
    }
1109 f3a5d3f8 Christoph Hellwig
    fd = open(bs->filename, s->open_flags | O_NONBLOCK);
1110 f3a5d3f8 Christoph Hellwig
    if (fd >= 0) {
1111 f3a5d3f8 Christoph Hellwig
        if (ioctl(fd, FDEJECT, 0) < 0)
1112 f3a5d3f8 Christoph Hellwig
            perror("FDEJECT");
1113 f3a5d3f8 Christoph Hellwig
        close(fd);
1114 f3a5d3f8 Christoph Hellwig
    }
1115 f3a5d3f8 Christoph Hellwig
1116 f3a5d3f8 Christoph Hellwig
    return 0;
1117 f3a5d3f8 Christoph Hellwig
}
1118 f3a5d3f8 Christoph Hellwig
1119 f3a5d3f8 Christoph Hellwig
static BlockDriver bdrv_host_floppy = {
1120 f3a5d3f8 Christoph Hellwig
    .format_name        = "host_floppy",
1121 f3a5d3f8 Christoph Hellwig
    .instance_size      = sizeof(BDRVRawState),
1122 508c7cb3 Christoph Hellwig
    .bdrv_probe_device        = floppy_probe_device,
1123 f3a5d3f8 Christoph Hellwig
    .bdrv_open          = floppy_open,
1124 f3a5d3f8 Christoph Hellwig
    .bdrv_close         = raw_close,
1125 f3a5d3f8 Christoph Hellwig
    .bdrv_create        = hdev_create,
1126 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1127 12c09b8c Kevin Wolf
    .no_zero_init       = 1,
1128 f3a5d3f8 Christoph Hellwig
    .bdrv_flush         = raw_flush,
1129 f3a5d3f8 Christoph Hellwig
1130 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_readv     = raw_aio_readv,
1131 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_writev    = raw_aio_writev,
1132 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1133 f3a5d3f8 Christoph Hellwig
1134 f3a5d3f8 Christoph Hellwig
    .bdrv_read          = raw_read,
1135 f3a5d3f8 Christoph Hellwig
    .bdrv_write         = raw_write,
1136 f3a5d3f8 Christoph Hellwig
    .bdrv_getlength        = raw_getlength,
1137 f3a5d3f8 Christoph Hellwig
1138 f3a5d3f8 Christoph Hellwig
    /* removable device support */
1139 f3a5d3f8 Christoph Hellwig
    .bdrv_is_inserted   = floppy_is_inserted,
1140 f3a5d3f8 Christoph Hellwig
    .bdrv_media_changed = floppy_media_changed,
1141 f3a5d3f8 Christoph Hellwig
    .bdrv_eject         = floppy_eject,
1142 f3a5d3f8 Christoph Hellwig
};
1143 f3a5d3f8 Christoph Hellwig
1144 f3a5d3f8 Christoph Hellwig
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1145 f3a5d3f8 Christoph Hellwig
{
1146 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1147 f3a5d3f8 Christoph Hellwig
1148 f3a5d3f8 Christoph Hellwig
    s->type = FTYPE_CD;
1149 f3a5d3f8 Christoph Hellwig
1150 19a3da7f Blue Swirl
    /* open will not fail even if no CD is inserted, so add O_NONBLOCK */
1151 19a3da7f Blue Swirl
    return raw_open_common(bs, filename, flags, O_NONBLOCK);
1152 f3a5d3f8 Christoph Hellwig
}
1153 f3a5d3f8 Christoph Hellwig
1154 508c7cb3 Christoph Hellwig
static int cdrom_probe_device(const char *filename)
1155 508c7cb3 Christoph Hellwig
{
1156 3baf720e Cole Robinson
    int fd, ret;
1157 3baf720e Cole Robinson
    int prio = 0;
1158 3baf720e Cole Robinson
1159 508c7cb3 Christoph Hellwig
    if (strstart(filename, "/dev/cd", NULL))
1160 3baf720e Cole Robinson
        prio = 50;
1161 3baf720e Cole Robinson
1162 3baf720e Cole Robinson
    fd = open(filename, O_RDONLY | O_NONBLOCK);
1163 3baf720e Cole Robinson
    if (fd < 0) {
1164 3baf720e Cole Robinson
        goto out;
1165 3baf720e Cole Robinson
    }
1166 3baf720e Cole Robinson
1167 3baf720e Cole Robinson
    /* Attempt to detect via a CDROM specific ioctl */
1168 3baf720e Cole Robinson
    ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1169 3baf720e Cole Robinson
    if (ret >= 0)
1170 3baf720e Cole Robinson
        prio = 100;
1171 3baf720e Cole Robinson
1172 3baf720e Cole Robinson
    close(fd);
1173 3baf720e Cole Robinson
out:
1174 3baf720e Cole Robinson
    return prio;
1175 508c7cb3 Christoph Hellwig
}
1176 508c7cb3 Christoph Hellwig
1177 f3a5d3f8 Christoph Hellwig
static int cdrom_is_inserted(BlockDriverState *bs)
1178 f3a5d3f8 Christoph Hellwig
{
1179 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1180 f3a5d3f8 Christoph Hellwig
    int ret;
1181 f3a5d3f8 Christoph Hellwig
1182 f3a5d3f8 Christoph Hellwig
    ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
1183 f3a5d3f8 Christoph Hellwig
    if (ret == CDS_DISC_OK)
1184 f3a5d3f8 Christoph Hellwig
        return 1;
1185 f3a5d3f8 Christoph Hellwig
    return 0;
1186 f3a5d3f8 Christoph Hellwig
}
1187 f3a5d3f8 Christoph Hellwig
1188 f3a5d3f8 Christoph Hellwig
static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1189 f3a5d3f8 Christoph Hellwig
{
1190 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1191 f3a5d3f8 Christoph Hellwig
1192 f3a5d3f8 Christoph Hellwig
    if (eject_flag) {
1193 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
1194 f3a5d3f8 Christoph Hellwig
            perror("CDROMEJECT");
1195 f3a5d3f8 Christoph Hellwig
    } else {
1196 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
1197 f3a5d3f8 Christoph Hellwig
            perror("CDROMEJECT");
1198 f3a5d3f8 Christoph Hellwig
    }
1199 f3a5d3f8 Christoph Hellwig
1200 f3a5d3f8 Christoph Hellwig
    return 0;
1201 f3a5d3f8 Christoph Hellwig
}
1202 f3a5d3f8 Christoph Hellwig
1203 f3a5d3f8 Christoph Hellwig
static int cdrom_set_locked(BlockDriverState *bs, int locked)
1204 f3a5d3f8 Christoph Hellwig
{
1205 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1206 f3a5d3f8 Christoph Hellwig
1207 f3a5d3f8 Christoph Hellwig
    if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
1208 f3a5d3f8 Christoph Hellwig
        /*
1209 f3a5d3f8 Christoph Hellwig
         * Note: an error can happen if the distribution automatically
1210 f3a5d3f8 Christoph Hellwig
         * mounts the CD-ROM
1211 f3a5d3f8 Christoph Hellwig
         */
1212 f3a5d3f8 Christoph Hellwig
        /* perror("CDROM_LOCKDOOR"); */
1213 f3a5d3f8 Christoph Hellwig
    }
1214 f3a5d3f8 Christoph Hellwig
1215 f3a5d3f8 Christoph Hellwig
    return 0;
1216 f3a5d3f8 Christoph Hellwig
}
1217 f3a5d3f8 Christoph Hellwig
1218 f3a5d3f8 Christoph Hellwig
static BlockDriver bdrv_host_cdrom = {
1219 f3a5d3f8 Christoph Hellwig
    .format_name        = "host_cdrom",
1220 f3a5d3f8 Christoph Hellwig
    .instance_size      = sizeof(BDRVRawState),
1221 508c7cb3 Christoph Hellwig
    .bdrv_probe_device        = cdrom_probe_device,
1222 f3a5d3f8 Christoph Hellwig
    .bdrv_open          = cdrom_open,
1223 f3a5d3f8 Christoph Hellwig
    .bdrv_close         = raw_close,
1224 f3a5d3f8 Christoph Hellwig
    .bdrv_create        = hdev_create,
1225 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1226 12c09b8c Kevin Wolf
    .no_zero_init       = 1,
1227 f3a5d3f8 Christoph Hellwig
    .bdrv_flush         = raw_flush,
1228 f3a5d3f8 Christoph Hellwig
1229 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_readv     = raw_aio_readv,
1230 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_writev    = raw_aio_writev,
1231 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1232 f3a5d3f8 Christoph Hellwig
1233 f3a5d3f8 Christoph Hellwig
    .bdrv_read          = raw_read,
1234 f3a5d3f8 Christoph Hellwig
    .bdrv_write         = raw_write,
1235 f3a5d3f8 Christoph Hellwig
    .bdrv_getlength     = raw_getlength,
1236 f3a5d3f8 Christoph Hellwig
1237 f3a5d3f8 Christoph Hellwig
    /* removable device support */
1238 f3a5d3f8 Christoph Hellwig
    .bdrv_is_inserted   = cdrom_is_inserted,
1239 f3a5d3f8 Christoph Hellwig
    .bdrv_eject         = cdrom_eject,
1240 f3a5d3f8 Christoph Hellwig
    .bdrv_set_locked    = cdrom_set_locked,
1241 f3a5d3f8 Christoph Hellwig
1242 f3a5d3f8 Christoph Hellwig
    /* generic scsi device */
1243 63ec93db Christoph Hellwig
    .bdrv_ioctl         = hdev_ioctl,
1244 63ec93db Christoph Hellwig
    .bdrv_aio_ioctl     = hdev_aio_ioctl,
1245 f3a5d3f8 Christoph Hellwig
};
1246 f3a5d3f8 Christoph Hellwig
#endif /* __linux__ */
1247 f3a5d3f8 Christoph Hellwig
1248 a167ba50 Aurelien Jarno
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
1249 f3a5d3f8 Christoph Hellwig
static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
1250 f3a5d3f8 Christoph Hellwig
{
1251 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1252 f3a5d3f8 Christoph Hellwig
    int ret;
1253 f3a5d3f8 Christoph Hellwig
1254 f3a5d3f8 Christoph Hellwig
    s->type = FTYPE_CD;
1255 f3a5d3f8 Christoph Hellwig
1256 19a3da7f Blue Swirl
    ret = raw_open_common(bs, filename, flags, 0);
1257 f3a5d3f8 Christoph Hellwig
    if (ret)
1258 f3a5d3f8 Christoph Hellwig
        return ret;
1259 f3a5d3f8 Christoph Hellwig
1260 f3a5d3f8 Christoph Hellwig
    /* make sure the door isnt locked at this time */
1261 f3a5d3f8 Christoph Hellwig
    ioctl(s->fd, CDIOCALLOW);
1262 f3a5d3f8 Christoph Hellwig
    return 0;
1263 f3a5d3f8 Christoph Hellwig
}
1264 f3a5d3f8 Christoph Hellwig
1265 508c7cb3 Christoph Hellwig
static int cdrom_probe_device(const char *filename)
1266 508c7cb3 Christoph Hellwig
{
1267 508c7cb3 Christoph Hellwig
    if (strstart(filename, "/dev/cd", NULL) ||
1268 508c7cb3 Christoph Hellwig
            strstart(filename, "/dev/acd", NULL))
1269 508c7cb3 Christoph Hellwig
        return 100;
1270 508c7cb3 Christoph Hellwig
    return 0;
1271 508c7cb3 Christoph Hellwig
}
1272 508c7cb3 Christoph Hellwig
1273 f3a5d3f8 Christoph Hellwig
static int cdrom_reopen(BlockDriverState *bs)
1274 f3a5d3f8 Christoph Hellwig
{
1275 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1276 f3a5d3f8 Christoph Hellwig
    int fd;
1277 f3a5d3f8 Christoph Hellwig
1278 f3a5d3f8 Christoph Hellwig
    /*
1279 f3a5d3f8 Christoph Hellwig
     * Force reread of possibly changed/newly loaded disc,
1280 f3a5d3f8 Christoph Hellwig
     * FreeBSD seems to not notice sometimes...
1281 f3a5d3f8 Christoph Hellwig
     */
1282 f3a5d3f8 Christoph Hellwig
    if (s->fd >= 0)
1283 f3a5d3f8 Christoph Hellwig
        close(s->fd);
1284 f3a5d3f8 Christoph Hellwig
    fd = open(bs->filename, s->open_flags, 0644);
1285 f3a5d3f8 Christoph Hellwig
    if (fd < 0) {
1286 f3a5d3f8 Christoph Hellwig
        s->fd = -1;
1287 f3a5d3f8 Christoph Hellwig
        return -EIO;
1288 f3a5d3f8 Christoph Hellwig
    }
1289 f3a5d3f8 Christoph Hellwig
    s->fd = fd;
1290 f3a5d3f8 Christoph Hellwig
1291 f3a5d3f8 Christoph Hellwig
    /* make sure the door isnt locked at this time */
1292 f3a5d3f8 Christoph Hellwig
    ioctl(s->fd, CDIOCALLOW);
1293 f3a5d3f8 Christoph Hellwig
    return 0;
1294 f3a5d3f8 Christoph Hellwig
}
1295 f3a5d3f8 Christoph Hellwig
1296 f3a5d3f8 Christoph Hellwig
static int cdrom_is_inserted(BlockDriverState *bs)
1297 f3a5d3f8 Christoph Hellwig
{
1298 f3a5d3f8 Christoph Hellwig
    return raw_getlength(bs) > 0;
1299 f3a5d3f8 Christoph Hellwig
}
1300 f3a5d3f8 Christoph Hellwig
1301 f3a5d3f8 Christoph Hellwig
static int cdrom_eject(BlockDriverState *bs, int eject_flag)
1302 f3a5d3f8 Christoph Hellwig
{
1303 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1304 f3a5d3f8 Christoph Hellwig
1305 f3a5d3f8 Christoph Hellwig
    if (s->fd < 0)
1306 f3a5d3f8 Christoph Hellwig
        return -ENOTSUP;
1307 f3a5d3f8 Christoph Hellwig
1308 f3a5d3f8 Christoph Hellwig
    (void) ioctl(s->fd, CDIOCALLOW);
1309 f3a5d3f8 Christoph Hellwig
1310 f3a5d3f8 Christoph Hellwig
    if (eject_flag) {
1311 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDIOCEJECT) < 0)
1312 f3a5d3f8 Christoph Hellwig
            perror("CDIOCEJECT");
1313 f3a5d3f8 Christoph Hellwig
    } else {
1314 f3a5d3f8 Christoph Hellwig
        if (ioctl(s->fd, CDIOCCLOSE) < 0)
1315 f3a5d3f8 Christoph Hellwig
            perror("CDIOCCLOSE");
1316 f3a5d3f8 Christoph Hellwig
    }
1317 f3a5d3f8 Christoph Hellwig
1318 f3a5d3f8 Christoph Hellwig
    if (cdrom_reopen(bs) < 0)
1319 f3a5d3f8 Christoph Hellwig
        return -ENOTSUP;
1320 f3a5d3f8 Christoph Hellwig
    return 0;
1321 f3a5d3f8 Christoph Hellwig
}
1322 f3a5d3f8 Christoph Hellwig
1323 f3a5d3f8 Christoph Hellwig
static int cdrom_set_locked(BlockDriverState *bs, int locked)
1324 f3a5d3f8 Christoph Hellwig
{
1325 f3a5d3f8 Christoph Hellwig
    BDRVRawState *s = bs->opaque;
1326 f3a5d3f8 Christoph Hellwig
1327 f3a5d3f8 Christoph Hellwig
    if (s->fd < 0)
1328 f3a5d3f8 Christoph Hellwig
        return -ENOTSUP;
1329 f3a5d3f8 Christoph Hellwig
    if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
1330 f3a5d3f8 Christoph Hellwig
        /*
1331 f3a5d3f8 Christoph Hellwig
         * Note: an error can happen if the distribution automatically
1332 f3a5d3f8 Christoph Hellwig
         * mounts the CD-ROM
1333 f3a5d3f8 Christoph Hellwig
         */
1334 f3a5d3f8 Christoph Hellwig
        /* perror("CDROM_LOCKDOOR"); */
1335 f3a5d3f8 Christoph Hellwig
    }
1336 f3a5d3f8 Christoph Hellwig
1337 f3a5d3f8 Christoph Hellwig
    return 0;
1338 f3a5d3f8 Christoph Hellwig
}
1339 f3a5d3f8 Christoph Hellwig
1340 f3a5d3f8 Christoph Hellwig
static BlockDriver bdrv_host_cdrom = {
1341 f3a5d3f8 Christoph Hellwig
    .format_name        = "host_cdrom",
1342 f3a5d3f8 Christoph Hellwig
    .instance_size      = sizeof(BDRVRawState),
1343 508c7cb3 Christoph Hellwig
    .bdrv_probe_device        = cdrom_probe_device,
1344 f3a5d3f8 Christoph Hellwig
    .bdrv_open          = cdrom_open,
1345 f3a5d3f8 Christoph Hellwig
    .bdrv_close         = raw_close,
1346 f3a5d3f8 Christoph Hellwig
    .bdrv_create        = hdev_create,
1347 0b4ce02e Kevin Wolf
    .create_options     = raw_create_options,
1348 12c09b8c Kevin Wolf
    .no_zero_init       = 1,
1349 f3a5d3f8 Christoph Hellwig
    .bdrv_flush         = raw_flush,
1350 f3a5d3f8 Christoph Hellwig
1351 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_readv     = raw_aio_readv,
1352 f3a5d3f8 Christoph Hellwig
    .bdrv_aio_writev    = raw_aio_writev,
1353 b2e12bc6 Christoph Hellwig
    .bdrv_aio_flush        = raw_aio_flush,
1354 f3a5d3f8 Christoph Hellwig
1355 f3a5d3f8 Christoph Hellwig
    .bdrv_read          = raw_read,
1356 f3a5d3f8 Christoph Hellwig
    .bdrv_write         = raw_write,
1357 f3a5d3f8 Christoph Hellwig
    .bdrv_getlength     = raw_getlength,
1358 f3a5d3f8 Christoph Hellwig
1359 19cb3738 bellard
    /* removable device support */
1360 f3a5d3f8 Christoph Hellwig
    .bdrv_is_inserted   = cdrom_is_inserted,
1361 f3a5d3f8 Christoph Hellwig
    .bdrv_eject         = cdrom_eject,
1362 f3a5d3f8 Christoph Hellwig
    .bdrv_set_locked    = cdrom_set_locked,
1363 19cb3738 bellard
};
1364 f3a5d3f8 Christoph Hellwig
#endif /* __FreeBSD__ */
1365 5efa9d5a Anthony Liguori
1366 5efa9d5a Anthony Liguori
static void bdrv_raw_init(void)
1367 5efa9d5a Anthony Liguori
{
1368 508c7cb3 Christoph Hellwig
    /*
1369 508c7cb3 Christoph Hellwig
     * Register all the drivers.  Note that order is important, the driver
1370 508c7cb3 Christoph Hellwig
     * registered last will get probed first.
1371 508c7cb3 Christoph Hellwig
     */
1372 5efa9d5a Anthony Liguori
    bdrv_register(&bdrv_raw);
1373 5efa9d5a Anthony Liguori
    bdrv_register(&bdrv_host_device);
1374 f3a5d3f8 Christoph Hellwig
#ifdef __linux__
1375 f3a5d3f8 Christoph Hellwig
    bdrv_register(&bdrv_host_floppy);
1376 f3a5d3f8 Christoph Hellwig
    bdrv_register(&bdrv_host_cdrom);
1377 f3a5d3f8 Christoph Hellwig
#endif
1378 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1379 f3a5d3f8 Christoph Hellwig
    bdrv_register(&bdrv_host_cdrom);
1380 f3a5d3f8 Christoph Hellwig
#endif
1381 5efa9d5a Anthony Liguori
}
1382 5efa9d5a Anthony Liguori
1383 5efa9d5a Anthony Liguori
block_init(bdrv_raw_init);