diff options
Diffstat (limited to 'emulators/qemu/files/phys-cdrom-freebsd-patch')
-rw-r--r-- | emulators/qemu/files/phys-cdrom-freebsd-patch | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/emulators/qemu/files/phys-cdrom-freebsd-patch b/emulators/qemu/files/phys-cdrom-freebsd-patch new file mode 100644 index 00000000000..6f477c4339c --- /dev/null +++ b/emulators/qemu/files/phys-cdrom-freebsd-patch @@ -0,0 +1,282 @@ +Index: qemu/block-raw-posix.c +@@ -55,6 +55,7 @@ + #ifdef __FreeBSD__ + #include <signal.h> + #include <sys/disk.h> ++#include <sys/cdio.h> + #endif + + #ifdef __OpenBSD__ +@@ -105,6 +106,9 @@ + int fd_got_error; + int fd_media_changed; + #endif ++#if defined(__FreeBSD__) ++ int cd_open_flags; ++#endif + uint8_t* aligned_buf; + } BDRVRawState; + +@@ -112,6 +116,12 @@ + + static int fd_open(BlockDriverState *bs); + ++#if defined(__FreeBSD__) ++static int cd_open(BlockDriverState *bs); ++#endif ++ ++static int raw_is_inserted(BlockDriverState *bs); ++ + static int raw_open(BlockDriverState *bs, const char *filename, int flags) + { + BDRVRawState *s = bs->opaque; +@@ -747,6 +757,9 @@ + int64_t size; + #ifdef _BSD + struct stat sb; ++#ifdef __FreeBSD__ ++ int reopened = 0; ++#endif + #endif + #ifdef __sun__ + struct dk_minfo minfo; +@@ -759,6 +772,9 @@ + return ret; + + #ifdef _BSD ++#ifdef __FreeBSD__ ++again: ++#endif + if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { + #ifdef DIOCGMEDIASIZE + if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) +@@ -768,6 +784,19 @@ + #else + size = lseek(fd, 0LL, SEEK_END); + #endif ++#ifdef __FreeBSD__ ++ switch(s->type) { ++ case FTYPE_CD: ++ /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */ ++ if (size == 2048LL * (unsigned)-1) ++ size = 0; ++ /* XXX no disc? maybe we need to reopen... */ ++ if (size <= 0 && !reopened && cd_open(bs) >= 0) { ++ reopened = 1; ++ goto again; ++ } ++ } ++#endif + } else + #endif + #ifdef __sun__ +@@ -958,6 +987,14 @@ + bs->sg = 1; + } + #endif ++#if defined(__FreeBSD__) ++ if (strstart(filename, "/dev/cd", NULL) || ++ strstart(filename, "/dev/acd", NULL)) { ++ s->type = FTYPE_CD; ++ s->cd_open_flags = open_flags; ++ } ++#endif ++ s->fd = -1; + fd = open(filename, open_flags, 0644); + if (fd < 0) { + ret = -errno; +@@ -966,6 +1003,11 @@ + return ret; + } + s->fd = fd; ++#if defined(__FreeBSD__) ++ /* make sure the door isnt locked at this time */ ++ if (s->type == FTYPE_CD) ++ ioctl (s->fd, CDIOCALLOW); ++#endif + #if defined(__linux__) + /* close fd so that we can reopen it as needed */ + if (s->type == FTYPE_FD) { +@@ -1132,7 +1174,116 @@ + + return ioctl(s->fd, req, buf); + } +-#else ++#elif defined(__FreeBSD__) ++ ++static int fd_open(BlockDriverState *bs) ++{ ++ BDRVRawState *s = bs->opaque; ++ ++ /* this is just to ensure s->fd is sane (its called by io ops) */ ++ if (s->fd >= 0) ++ return 0; ++ return -EIO; ++} ++ ++static int cd_open(BlockDriverState *bs) ++{ ++#if defined(__FreeBSD__) ++ BDRVRawState *s = bs->opaque; ++ int fd; ++ ++ switch(s->type) { ++ case FTYPE_CD: ++ /* XXX force reread of possibly changed/newly loaded disc, ++ * FreeBSD seems to not notice sometimes... */ ++ if (s->fd >= 0) ++ close (s->fd); ++ fd = open(bs->filename, s->cd_open_flags, 0644); ++ if (fd < 0) { ++ s->fd = -1; ++ return -EIO; ++ } ++ s->fd = fd; ++ /* make sure the door isnt locked at this time */ ++ ioctl (s->fd, CDIOCALLOW); ++ } ++#endif ++ return 0; ++} ++ ++static int raw_is_inserted(BlockDriverState *bs) ++{ ++ BDRVRawState *s = bs->opaque; ++ ++ switch(s->type) { ++ case FTYPE_CD: ++ return (raw_getlength(bs) > 0); ++ case FTYPE_FD: ++ /* XXX handle this */ ++ /* FALLTHRU */ ++ default: ++ return 1; ++ } ++} ++ ++static int raw_media_changed(BlockDriverState *bs) ++{ ++ return -ENOTSUP; ++} ++ ++static int raw_eject(BlockDriverState *bs, int eject_flag) ++{ ++ BDRVRawState *s = bs->opaque; ++ ++ switch(s->type) { ++ case FTYPE_CD: ++ if (s->fd < 0) ++ return -ENOTSUP; ++ (void) ioctl (s->fd, CDIOCALLOW); ++ if (eject_flag) { ++ if (ioctl (s->fd, CDIOCEJECT) < 0) ++ perror("CDIOCEJECT"); ++ } else { ++ if (ioctl (s->fd, CDIOCCLOSE) < 0) ++ perror("CDIOCCLOSE"); ++ } ++ if (cd_open(bs) < 0) ++ return -ENOTSUP; ++ break; ++ case FTYPE_FD: ++ /* XXX handle this */ ++ /* FALLTHRU */ ++ default: ++ return -ENOTSUP; ++ } ++ return 0; ++} ++ ++static int raw_set_locked(BlockDriverState *bs, int locked) ++{ ++ BDRVRawState *s = bs->opaque; ++ ++ switch(s->type) { ++ case FTYPE_CD: ++ if (s->fd < 0) ++ return -ENOTSUP; ++ if (ioctl (s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) { ++ /* Note: an error can happen if the distribution automatically ++ mounts the CD-ROM */ ++ // perror("CDROM_LOCKDOOR"); ++ } ++ break; ++ default: ++ return -ENOTSUP; ++ } ++ return 0; ++} ++ ++static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) ++{ ++ return -ENOTSUP; ++} ++#else /* !linux && !FreeBSD */ + + static int fd_open(BlockDriverState *bs) + { +@@ -1163,7 +1314,7 @@ + { + return -ENOTSUP; + } +-#endif /* !linux */ ++#endif /* !linux && !FreeBSD */ + + BlockDriver bdrv_host_device = { + "host_device", +Index: qemu/hw/scsi-disk.c +@@ -417,16 +417,26 @@ + switch (command) { + case 0x0: + DPRINTF("Test Unit Ready\n"); ++ if (!bdrv_is_inserted(s->bdrv)) ++ goto notready; + break; + case 0x03: + DPRINTF("Request Sense (len %d)\n", len); + if (len < 4) + goto fail; + memset(outbuf, 0, 4); ++ r->buf_len = 4; ++ if (s->sense == SENSE_NOT_READY && len >= 18) { ++ memset(outbuf, 0, 18); ++ r->buf_len = 18; ++ outbuf[7] = 10; ++ /* asc 0x3a, ascq 0: Medium not present */ ++ outbuf[12] = 0x3a; ++ outbuf[13] = 0; ++ } + outbuf[0] = 0xf0; + outbuf[1] = 0; + outbuf[2] = s->sense; +- r->buf_len = 4; + break; + case 0x12: + DPRINTF("Inquiry (len %d)\n", len); +@@ -725,6 +735,10 @@ + break; + case 0x1b: + DPRINTF("Start Stop Unit\n"); ++ if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM && ++ (buf[4] & 2)) ++ /* load/eject medium */ ++ bdrv_eject(s->bdrv, !(buf[4] & 1)); + break; + case 0x1e: + DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3); +@@ -754,6 +768,7 @@ + outbuf[7] = 0; + r->buf_len = 8; + } else { ++ notready: + scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY); + return 0; + } +@@ -790,6 +805,7 @@ + start_track = buf[6]; + bdrv_get_geometry(s->bdrv, &nb_sectors); + DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1); ++ nb_sectors /= s->cluster_size; + switch(format) { + case 0: + toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track); |