Commit 9f23011ad5abd4520a7c7080b57e6ace21085223

Authored by blueswir1
1 parent a718acec

FreeBSD host physical cdrom fixes

This improves physical cdrom support on FreeBSD hosts to be almost as
good as on Linux, with the only notable exception that you still need to
either have the guest itself eject the disc if you want to take it
out/change it, or do a change command in the monitor after taking out
a disc in case a guest cannot eject it itself - otherwise the guest may
continue using state (like size) of the old disc.

Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6888 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 153 additions and 2 deletions
block-raw-posix.c
@@ -55,6 +55,7 @@ @@ -55,6 +55,7 @@
55 #ifdef __FreeBSD__ 55 #ifdef __FreeBSD__
56 #include <signal.h> 56 #include <signal.h>
57 #include <sys/disk.h> 57 #include <sys/disk.h>
  58 +#include <sys/cdio.h>
58 #endif 59 #endif
59 60
60 #ifdef __OpenBSD__ 61 #ifdef __OpenBSD__
@@ -110,6 +111,9 @@ typedef struct BDRVRawState { @@ -110,6 +111,9 @@ typedef struct BDRVRawState {
110 int fd_got_error; 111 int fd_got_error;
111 int fd_media_changed; 112 int fd_media_changed;
112 #endif 113 #endif
  114 +#if defined(__FreeBSD__)
  115 + int cd_open_flags;
  116 +#endif
113 uint8_t* aligned_buf; 117 uint8_t* aligned_buf;
114 } BDRVRawState; 118 } BDRVRawState;
115 119
@@ -117,6 +121,12 @@ static int posix_aio_init(void); @@ -117,6 +121,12 @@ static int posix_aio_init(void);
117 121
118 static int fd_open(BlockDriverState *bs); 122 static int fd_open(BlockDriverState *bs);
119 123
  124 +#if defined(__FreeBSD__)
  125 +static int cd_open(BlockDriverState *bs);
  126 +#endif
  127 +
  128 +static int raw_is_inserted(BlockDriverState *bs);
  129 +
120 static int raw_open(BlockDriverState *bs, const char *filename, int flags) 130 static int raw_open(BlockDriverState *bs, const char *filename, int flags)
121 { 131 {
122 BDRVRawState *s = bs->opaque; 132 BDRVRawState *s = bs->opaque;
@@ -773,6 +783,9 @@ static int64_t raw_getlength(BlockDriverState *bs) @@ -773,6 +783,9 @@ static int64_t raw_getlength(BlockDriverState *bs)
773 int64_t size; 783 int64_t size;
774 #ifdef HOST_BSD 784 #ifdef HOST_BSD
775 struct stat sb; 785 struct stat sb;
  786 +#ifdef __FreeBSD__
  787 + int reopened = 0;
  788 +#endif
776 #endif 789 #endif
777 #ifdef __sun__ 790 #ifdef __sun__
778 struct dk_minfo minfo; 791 struct dk_minfo minfo;
@@ -785,6 +798,9 @@ static int64_t raw_getlength(BlockDriverState *bs) @@ -785,6 +798,9 @@ static int64_t raw_getlength(BlockDriverState *bs)
785 return ret; 798 return ret;
786 799
787 #ifdef HOST_BSD 800 #ifdef HOST_BSD
  801 +#ifdef __FreeBSD__
  802 +again:
  803 +#endif
788 if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) { 804 if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
789 #ifdef DIOCGMEDIASIZE 805 #ifdef DIOCGMEDIASIZE
790 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size)) 806 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
@@ -803,6 +819,19 @@ static int64_t raw_getlength(BlockDriverState *bs) @@ -803,6 +819,19 @@ static int64_t raw_getlength(BlockDriverState *bs)
803 #else 819 #else
804 size = lseek(fd, 0LL, SEEK_END); 820 size = lseek(fd, 0LL, SEEK_END);
805 #endif 821 #endif
  822 +#ifdef __FreeBSD__
  823 + switch(s->type) {
  824 + case FTYPE_CD:
  825 + /* XXX FreeBSD acd returns UINT_MAX sectors for an empty drive */
  826 + if (size == 2048LL * (unsigned)-1)
  827 + size = 0;
  828 + /* XXX no disc? maybe we need to reopen... */
  829 + if (size <= 0 && !reopened && cd_open(bs) >= 0) {
  830 + reopened = 1;
  831 + goto again;
  832 + }
  833 + }
  834 +#endif
806 } else 835 } else
807 #endif 836 #endif
808 #ifdef __sun__ 837 #ifdef __sun__
@@ -993,6 +1022,14 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) @@ -993,6 +1022,14 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
993 bs->sg = 1; 1022 bs->sg = 1;
994 } 1023 }
995 #endif 1024 #endif
  1025 +#if defined(__FreeBSD__)
  1026 + if (strstart(filename, "/dev/cd", NULL) ||
  1027 + strstart(filename, "/dev/acd", NULL)) {
  1028 + s->type = FTYPE_CD;
  1029 + s->cd_open_flags = open_flags;
  1030 + }
  1031 +#endif
  1032 + s->fd = -1;
996 fd = open(filename, open_flags, 0644); 1033 fd = open(filename, open_flags, 0644);
997 if (fd < 0) { 1034 if (fd < 0) {
998 ret = -errno; 1035 ret = -errno;
@@ -1001,6 +1038,11 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) @@ -1001,6 +1038,11 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
1001 return ret; 1038 return ret;
1002 } 1039 }
1003 s->fd = fd; 1040 s->fd = fd;
  1041 +#if defined(__FreeBSD__)
  1042 + /* make sure the door isnt locked at this time */
  1043 + if (s->type == FTYPE_CD)
  1044 + ioctl (s->fd, CDIOCALLOW);
  1045 +#endif
1004 #if defined(__linux__) 1046 #if defined(__linux__)
1005 /* close fd so that we can reopen it as needed */ 1047 /* close fd so that we can reopen it as needed */
1006 if (s->type == FTYPE_FD) { 1048 if (s->type == FTYPE_FD) {
@@ -1167,7 +1209,116 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) @@ -1167,7 +1209,116 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1167 1209
1168 return ioctl(s->fd, req, buf); 1210 return ioctl(s->fd, req, buf);
1169 } 1211 }
1170 -#else 1212 +#elif defined(__FreeBSD__)
  1213 +
  1214 +static int fd_open(BlockDriverState *bs)
  1215 +{
  1216 + BDRVRawState *s = bs->opaque;
  1217 +
  1218 + /* this is just to ensure s->fd is sane (its called by io ops) */
  1219 + if (s->fd >= 0)
  1220 + return 0;
  1221 + return -EIO;
  1222 +}
  1223 +
  1224 +static int cd_open(BlockDriverState *bs)
  1225 +{
  1226 +#if defined(__FreeBSD__)
  1227 + BDRVRawState *s = bs->opaque;
  1228 + int fd;
  1229 +
  1230 + switch(s->type) {
  1231 + case FTYPE_CD:
  1232 + /* XXX force reread of possibly changed/newly loaded disc,
  1233 + * FreeBSD seems to not notice sometimes... */
  1234 + if (s->fd >= 0)
  1235 + close (s->fd);
  1236 + fd = open(bs->filename, s->cd_open_flags, 0644);
  1237 + if (fd < 0) {
  1238 + s->fd = -1;
  1239 + return -EIO;
  1240 + }
  1241 + s->fd = fd;
  1242 + /* make sure the door isnt locked at this time */
  1243 + ioctl (s->fd, CDIOCALLOW);
  1244 + }
  1245 +#endif
  1246 + return 0;
  1247 +}
  1248 +
  1249 +static int raw_is_inserted(BlockDriverState *bs)
  1250 +{
  1251 + BDRVRawState *s = bs->opaque;
  1252 +
  1253 + switch(s->type) {
  1254 + case FTYPE_CD:
  1255 + return (raw_getlength(bs) > 0);
  1256 + case FTYPE_FD:
  1257 + /* XXX handle this */
  1258 + /* FALLTHRU */
  1259 + default:
  1260 + return 1;
  1261 + }
  1262 +}
  1263 +
  1264 +static int raw_media_changed(BlockDriverState *bs)
  1265 +{
  1266 + return -ENOTSUP;
  1267 +}
  1268 +
  1269 +static int raw_eject(BlockDriverState *bs, int eject_flag)
  1270 +{
  1271 + BDRVRawState *s = bs->opaque;
  1272 +
  1273 + switch(s->type) {
  1274 + case FTYPE_CD:
  1275 + if (s->fd < 0)
  1276 + return -ENOTSUP;
  1277 + (void) ioctl (s->fd, CDIOCALLOW);
  1278 + if (eject_flag) {
  1279 + if (ioctl (s->fd, CDIOCEJECT) < 0)
  1280 + perror("CDIOCEJECT");
  1281 + } else {
  1282 + if (ioctl (s->fd, CDIOCCLOSE) < 0)
  1283 + perror("CDIOCCLOSE");
  1284 + }
  1285 + if (cd_open(bs) < 0)
  1286 + return -ENOTSUP;
  1287 + break;
  1288 + case FTYPE_FD:
  1289 + /* XXX handle this */
  1290 + /* FALLTHRU */
  1291 + default:
  1292 + return -ENOTSUP;
  1293 + }
  1294 + return 0;
  1295 +}
  1296 +
  1297 +static int raw_set_locked(BlockDriverState *bs, int locked)
  1298 +{
  1299 + BDRVRawState *s = bs->opaque;
  1300 +
  1301 + switch(s->type) {
  1302 + case FTYPE_CD:
  1303 + if (s->fd < 0)
  1304 + return -ENOTSUP;
  1305 + if (ioctl (s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
  1306 + /* Note: an error can happen if the distribution automatically
  1307 + mounts the CD-ROM */
  1308 + // perror("CDROM_LOCKDOOR");
  1309 + }
  1310 + break;
  1311 + default:
  1312 + return -ENOTSUP;
  1313 + }
  1314 + return 0;
  1315 +}
  1316 +
  1317 +static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
  1318 +{
  1319 + return -ENOTSUP;
  1320 +}
  1321 +#else /* !linux && !FreeBSD */
1171 1322
1172 static int fd_open(BlockDriverState *bs) 1323 static int fd_open(BlockDriverState *bs)
1173 { 1324 {
@@ -1198,7 +1349,7 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) @@ -1198,7 +1349,7 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1198 { 1349 {
1199 return -ENOTSUP; 1350 return -ENOTSUP;
1200 } 1351 }
1201 -#endif /* !linux */ 1352 +#endif /* !linux && !FreeBSD */
1202 1353
1203 static int raw_sg_send_command(BlockDriverState *bs, void *buf, int count) 1354 static int raw_sg_send_command(BlockDriverState *bs, void *buf, int count)
1204 { 1355 {