summaryrefslogtreecommitdiff
path: root/emulators/qemu/files/phys-cdrom-freebsd-patch
diff options
context:
space:
mode:
Diffstat (limited to 'emulators/qemu/files/phys-cdrom-freebsd-patch')
-rw-r--r--emulators/qemu/files/phys-cdrom-freebsd-patch282
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 000000000000..6f477c4339cb
--- /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);