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 55 #ifdef __FreeBSD__
56 56 #include <signal.h>
57 57 #include <sys/disk.h>
  58 +#include <sys/cdio.h>
58 59 #endif
59 60  
60 61 #ifdef __OpenBSD__
... ... @@ -110,6 +111,9 @@ typedef struct BDRVRawState {
110 111 int fd_got_error;
111 112 int fd_media_changed;
112 113 #endif
  114 +#if defined(__FreeBSD__)
  115 + int cd_open_flags;
  116 +#endif
113 117 uint8_t* aligned_buf;
114 118 } BDRVRawState;
115 119  
... ... @@ -117,6 +121,12 @@ static int posix_aio_init(void);
117 121  
118 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 130 static int raw_open(BlockDriverState *bs, const char *filename, int flags)
121 131 {
122 132 BDRVRawState *s = bs->opaque;
... ... @@ -773,6 +783,9 @@ static int64_t raw_getlength(BlockDriverState *bs)
773 783 int64_t size;
774 784 #ifdef HOST_BSD
775 785 struct stat sb;
  786 +#ifdef __FreeBSD__
  787 + int reopened = 0;
  788 +#endif
776 789 #endif
777 790 #ifdef __sun__
778 791 struct dk_minfo minfo;
... ... @@ -785,6 +798,9 @@ static int64_t raw_getlength(BlockDriverState *bs)
785 798 return ret;
786 799  
787 800 #ifdef HOST_BSD
  801 +#ifdef __FreeBSD__
  802 +again:
  803 +#endif
788 804 if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
789 805 #ifdef DIOCGMEDIASIZE
790 806 if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
... ... @@ -803,6 +819,19 @@ static int64_t raw_getlength(BlockDriverState *bs)
803 819 #else
804 820 size = lseek(fd, 0LL, SEEK_END);
805 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 835 } else
807 836 #endif
808 837 #ifdef __sun__
... ... @@ -993,6 +1022,14 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
993 1022 bs->sg = 1;
994 1023 }
995 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 1033 fd = open(filename, open_flags, 0644);
997 1034 if (fd < 0) {
998 1035 ret = -errno;
... ... @@ -1001,6 +1038,11 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
1001 1038 return ret;
1002 1039 }
1003 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 1046 #if defined(__linux__)
1005 1047 /* close fd so that we can reopen it as needed */
1006 1048 if (s->type == FTYPE_FD) {
... ... @@ -1167,7 +1209,116 @@ static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1167 1209  
1168 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 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 1349 {
1199 1350 return -ENOTSUP;
1200 1351 }
1201   -#endif /* !linux */
  1352 +#endif /* !linux && !FreeBSD */
1202 1353  
1203 1354 static int raw_sg_send_command(BlockDriverState *bs, void *buf, int count)
1204 1355 {
... ...