Commit f3a5d3f8a1a992376e3dd128ceee917cd1281da7

Authored by Christoph Hellwig
Committed by Christoph Hellwig
1 parent 90babde0

raw-posix: split hdev drivers

Instead of declaring one BlockDriver for all host devices declared one
for each type:  a generic one for normal disk devices, a Linux floppy
driver and a CDROM driver for Linux and FreeBSD.  This gets rid of a lot
of messy ifdefs and switching based on the type in the various removal
device methods.

block.c grows a new method to find the correct host device driver based
on OS-sepcific criteria, which will later into the actual drivers in a
later patch in this series.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Showing 2 changed files with 347 additions and 277 deletions
@@ -249,32 +249,55 @@ static BlockDriver *find_protocol(const char *filename) @@ -249,32 +249,55 @@ static BlockDriver *find_protocol(const char *filename)
249 return NULL; 249 return NULL;
250 } 250 }
251 251
252 -/* XXX: force raw format if block or character device ? It would  
253 - simplify the BSD case */  
254 -static BlockDriver *find_image_format(const char *filename) 252 +/*
  253 + * Detect host devices. By convention, /dev/cdrom[N] is always
  254 + * recognized as a host CDROM.
  255 + */
  256 +#ifdef _WIN32
  257 +static BlockDriver *find_hdev_driver(const char *filename)
255 { 258 {
256 - int ret, score, score_max;  
257 - BlockDriver *drv1, *drv;  
258 - uint8_t buf[2048];  
259 - BlockDriverState *bs;  
260 -  
261 - /* detect host devices. By convention, /dev/cdrom[N] is always  
262 - recognized as a host CDROM */  
263 if (strstart(filename, "/dev/cdrom", NULL)) 259 if (strstart(filename, "/dev/cdrom", NULL))
264 return bdrv_find_format("host_device"); 260 return bdrv_find_format("host_device");
265 -#ifdef _WIN32  
266 if (is_windows_drive(filename)) 261 if (is_windows_drive(filename))
267 return bdrv_find_format("host_device"); 262 return bdrv_find_format("host_device");
  263 + return NULL;
  264 +}
268 #else 265 #else
269 - {  
270 - struct stat st;  
271 - if (stat(filename, &st) >= 0 && 266 +static BlockDriver *find_hdev_driver(const char *filename)
  267 +{
  268 + struct stat st;
  269 +
  270 +#ifdef __linux__
  271 + if (strstart(filename, "/dev/fd", NULL))
  272 + return bdrv_find_format("host_floppy");
  273 + if (strstart(filename, "/dev/cd", NULL))
  274 + return bdrv_find_format("host_cdrom");
  275 +#elif defined(__FreeBSD__)
  276 + if (strstart(filename, "/dev/cd", NULL) ||
  277 + strstart(filename, "/dev/acd", NULL)) {
  278 + return bdrv_find_format("host_cdrom");
  279 + }
  280 +#else
  281 + if (strstart(filename, "/dev/cdrom", NULL))
  282 + return bdrv_find_format("host_device");
  283 +#endif
  284 +
  285 + if (stat(filename, &st) >= 0 &&
272 (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) { 286 (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
273 - return bdrv_find_format("host_device");  
274 - } 287 + return bdrv_find_format("host_device");
275 } 288 }
  289 +
  290 + return NULL;
  291 +}
276 #endif 292 #endif
277 293
  294 +static BlockDriver *find_image_format(const char *filename)
  295 +{
  296 + int ret, score, score_max;
  297 + BlockDriver *drv1, *drv;
  298 + uint8_t buf[2048];
  299 + BlockDriverState *bs;
  300 +
278 drv = find_protocol(filename); 301 drv = find_protocol(filename);
279 /* no need to test disk image formats for vvfat */ 302 /* no need to test disk image formats for vvfat */
280 if (drv && strcmp(drv->format_name, "vvfat") == 0) 303 if (drv && strcmp(drv->format_name, "vvfat") == 0)
@@ -394,7 +417,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags, @@ -394,7 +417,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
394 if (flags & BDRV_O_FILE) { 417 if (flags & BDRV_O_FILE) {
395 drv = find_protocol(filename); 418 drv = find_protocol(filename);
396 } else if (!drv) { 419 } else if (!drv) {
397 - drv = find_image_format(filename); 420 + drv = find_hdev_driver(filename);
  421 + if (!drv) {
  422 + drv = find_image_format(filename);
  423 + }
398 } 424 }
399 if (!drv) { 425 if (!drv) {
400 ret = -ENOENT; 426 ret = -ENOENT;
block/raw-posix.c
@@ -119,11 +119,9 @@ static int posix_aio_init(void); @@ -119,11 +119,9 @@ static int posix_aio_init(void);
119 static int fd_open(BlockDriverState *bs); 119 static int fd_open(BlockDriverState *bs);
120 120
121 #if defined(__FreeBSD__) 121 #if defined(__FreeBSD__)
122 -static int cd_open(BlockDriverState *bs); 122 +static int cdrom_reopen(BlockDriverState *bs);
123 #endif 123 #endif
124 124
125 -static int raw_is_inserted(BlockDriverState *bs);  
126 -  
127 static int raw_open_common(BlockDriverState *bs, const char *filename, 125 static int raw_open_common(BlockDriverState *bs, const char *filename,
128 int flags) 126 int flags)
129 { 127 {
@@ -808,7 +806,7 @@ again: @@ -808,7 +806,7 @@ again:
808 if (size == 2048LL * (unsigned)-1) 806 if (size == 2048LL * (unsigned)-1)
809 size = 0; 807 size = 0;
810 /* XXX no disc? maybe we need to reopen... */ 808 /* XXX no disc? maybe we need to reopen... */
811 - if (size <= 0 && !reopened && cd_open(bs) >= 0) { 809 + if (size <= 0 && !reopened && cdrom_reopen(bs) >= 0) {
812 reopened = 1; 810 reopened = 1;
813 goto again; 811 goto again;
814 } 812 }
@@ -958,7 +956,6 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma @@ -958,7 +956,6 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma
958 static int hdev_open(BlockDriverState *bs, const char *filename, int flags) 956 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
959 { 957 {
960 BDRVRawState *s = bs->opaque; 958 BDRVRawState *s = bs->opaque;
961 - int ret;  
962 959
963 #ifdef CONFIG_COCOA 960 #ifdef CONFIG_COCOA
964 if (strstart(filename, "/dev/cdrom", NULL)) { 961 if (strstart(filename, "/dev/cdrom", NULL)) {
@@ -988,46 +985,13 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags) @@ -988,46 +985,13 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
988 #endif 985 #endif
989 986
990 s->type = FTYPE_FILE; 987 s->type = FTYPE_FILE;
991 -#if defined(__linux__)  
992 - if (strstart(filename, "/dev/cd", NULL)) {  
993 - /* open will not fail even if no CD is inserted */  
994 - s->open_flags |= O_NONBLOCK;  
995 - s->type = FTYPE_CD;  
996 - } else if (strstart(filename, "/dev/fd", NULL)) {  
997 - s->type = FTYPE_FD;  
998 - /* open will not fail even if no floppy is inserted */  
999 - s->open_flags |= O_NONBLOCK;  
1000 -#ifdef CONFIG_AIO  
1001 - } else if (strstart(filename, "/dev/sg", NULL)) { 988 +#if defined(__linux__) && defined(CONFIG_AIO)
  989 + if (strstart(filename, "/dev/sg", NULL)) {
1002 bs->sg = 1; 990 bs->sg = 1;
1003 -#endif  
1004 } 991 }
1005 #endif 992 #endif
1006 -#if defined(__FreeBSD__)  
1007 - if (strstart(filename, "/dev/cd", NULL) ||  
1008 - strstart(filename, "/dev/acd", NULL)) {  
1009 - s->type = FTYPE_CD;  
1010 - }  
1011 -#endif  
1012 -  
1013 - ret = raw_open_common(bs, filename, flags);  
1014 - if (ret)  
1015 - return ret;  
1016 993
1017 -#if defined(__FreeBSD__)  
1018 - /* make sure the door isnt locked at this time */  
1019 - if (s->type == FTYPE_CD)  
1020 - ioctl (s->fd, CDIOCALLOW);  
1021 -#endif  
1022 -#if defined(__linux__)  
1023 - /* close fd so that we can reopen it as needed */  
1024 - if (s->type == FTYPE_FD) {  
1025 - close(s->fd);  
1026 - s->fd = -1;  
1027 - s->fd_media_changed = 1;  
1028 - }  
1029 -#endif  
1030 - return 0; 994 + return raw_open_common(bs, filename, flags);
1031 } 995 }
1032 996
1033 #if defined(__linux__) 997 #if defined(__linux__)
@@ -1080,105 +1044,6 @@ static int fd_open(BlockDriverState *bs) @@ -1080,105 +1044,6 @@ static int fd_open(BlockDriverState *bs)
1080 return 0; 1044 return 0;
1081 } 1045 }
1082 1046
1083 -static int raw_is_inserted(BlockDriverState *bs)  
1084 -{  
1085 - BDRVRawState *s = bs->opaque;  
1086 - int ret;  
1087 -  
1088 - switch(s->type) {  
1089 - case FTYPE_CD:  
1090 - ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);  
1091 - if (ret == CDS_DISC_OK)  
1092 - return 1;  
1093 - else  
1094 - return 0;  
1095 - break;  
1096 - case FTYPE_FD:  
1097 - ret = fd_open(bs);  
1098 - return (ret >= 0);  
1099 - default:  
1100 - return 1;  
1101 - }  
1102 -}  
1103 -  
1104 -/* currently only used by fdc.c, but a CD version would be good too */  
1105 -static int raw_media_changed(BlockDriverState *bs)  
1106 -{  
1107 - BDRVRawState *s = bs->opaque;  
1108 -  
1109 - switch(s->type) {  
1110 - case FTYPE_FD:  
1111 - {  
1112 - int ret;  
1113 - /* XXX: we do not have a true media changed indication. It  
1114 - does not work if the floppy is changed without trying  
1115 - to read it */  
1116 - fd_open(bs);  
1117 - ret = s->fd_media_changed;  
1118 - s->fd_media_changed = 0;  
1119 -#ifdef DEBUG_FLOPPY  
1120 - printf("Floppy changed=%d\n", ret);  
1121 -#endif  
1122 - return ret;  
1123 - }  
1124 - default:  
1125 - return -ENOTSUP;  
1126 - }  
1127 -}  
1128 -  
1129 -static int raw_eject(BlockDriverState *bs, int eject_flag)  
1130 -{  
1131 - BDRVRawState *s = bs->opaque;  
1132 -  
1133 - switch(s->type) {  
1134 - case FTYPE_CD:  
1135 - if (eject_flag) {  
1136 - if (ioctl (s->fd, CDROMEJECT, NULL) < 0)  
1137 - perror("CDROMEJECT");  
1138 - } else {  
1139 - if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)  
1140 - perror("CDROMEJECT");  
1141 - }  
1142 - break;  
1143 - case FTYPE_FD:  
1144 - {  
1145 - int fd;  
1146 - if (s->fd >= 0) {  
1147 - close(s->fd);  
1148 - s->fd = -1;  
1149 - }  
1150 - fd = open(bs->filename, s->open_flags | O_NONBLOCK);  
1151 - if (fd >= 0) {  
1152 - if (ioctl(fd, FDEJECT, 0) < 0)  
1153 - perror("FDEJECT");  
1154 - close(fd);  
1155 - }  
1156 - }  
1157 - break;  
1158 - default:  
1159 - return -ENOTSUP;  
1160 - }  
1161 - return 0;  
1162 -}  
1163 -  
1164 -static int raw_set_locked(BlockDriverState *bs, int locked)  
1165 -{  
1166 - BDRVRawState *s = bs->opaque;  
1167 -  
1168 - switch(s->type) {  
1169 - case FTYPE_CD:  
1170 - if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {  
1171 - /* Note: an error can happen if the distribution automatically  
1172 - mounts the CD-ROM */  
1173 - // perror("CDROM_LOCKDOOR");  
1174 - }  
1175 - break;  
1176 - default:  
1177 - return -ENOTSUP;  
1178 - }  
1179 - return 0;  
1180 -}  
1181 -  
1182 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) 1047 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1183 { 1048 {
1184 BDRVRawState *s = bs->opaque; 1049 BDRVRawState *s = bs->opaque;
@@ -1220,7 +1085,6 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs, @@ -1220,7 +1085,6 @@ static BlockDriverAIOCB *raw_aio_ioctl(BlockDriverState *bs,
1220 #endif 1085 #endif
1221 1086
1222 #elif defined(__FreeBSD__) 1087 #elif defined(__FreeBSD__)
1223 -  
1224 static int fd_open(BlockDriverState *bs) 1088 static int fd_open(BlockDriverState *bs)
1225 { 1089 {
1226 BDRVRawState *s = bs->opaque; 1090 BDRVRawState *s = bs->opaque;
@@ -1231,99 +1095,6 @@ static int fd_open(BlockDriverState *bs) @@ -1231,99 +1095,6 @@ static int fd_open(BlockDriverState *bs)
1231 return -EIO; 1095 return -EIO;
1232 } 1096 }
1233 1097
1234 -static int cd_open(BlockDriverState *bs)  
1235 -{  
1236 -#if defined(__FreeBSD__)  
1237 - BDRVRawState *s = bs->opaque;  
1238 - int fd;  
1239 -  
1240 - switch(s->type) {  
1241 - case FTYPE_CD:  
1242 - /* XXX force reread of possibly changed/newly loaded disc,  
1243 - * FreeBSD seems to not notice sometimes... */  
1244 - if (s->fd >= 0)  
1245 - close (s->fd);  
1246 - fd = open(bs->filename, s->open_flags, 0644);  
1247 - if (fd < 0) {  
1248 - s->fd = -1;  
1249 - return -EIO;  
1250 - }  
1251 - s->fd = fd;  
1252 - /* make sure the door isnt locked at this time */  
1253 - ioctl (s->fd, CDIOCALLOW);  
1254 - }  
1255 -#endif  
1256 - return 0;  
1257 -}  
1258 -  
1259 -static int raw_is_inserted(BlockDriverState *bs)  
1260 -{  
1261 - BDRVRawState *s = bs->opaque;  
1262 -  
1263 - switch(s->type) {  
1264 - case FTYPE_CD:  
1265 - return (raw_getlength(bs) > 0);  
1266 - case FTYPE_FD:  
1267 - /* XXX handle this */  
1268 - /* FALLTHRU */  
1269 - default:  
1270 - return 1;  
1271 - }  
1272 -}  
1273 -  
1274 -static int raw_media_changed(BlockDriverState *bs)  
1275 -{  
1276 - return -ENOTSUP;  
1277 -}  
1278 -  
1279 -static int raw_eject(BlockDriverState *bs, int eject_flag)  
1280 -{  
1281 - BDRVRawState *s = bs->opaque;  
1282 -  
1283 - switch(s->type) {  
1284 - case FTYPE_CD:  
1285 - if (s->fd < 0)  
1286 - return -ENOTSUP;  
1287 - (void) ioctl (s->fd, CDIOCALLOW);  
1288 - if (eject_flag) {  
1289 - if (ioctl (s->fd, CDIOCEJECT) < 0)  
1290 - perror("CDIOCEJECT");  
1291 - } else {  
1292 - if (ioctl (s->fd, CDIOCCLOSE) < 0)  
1293 - perror("CDIOCCLOSE");  
1294 - }  
1295 - if (cd_open(bs) < 0)  
1296 - return -ENOTSUP;  
1297 - break;  
1298 - case FTYPE_FD:  
1299 - /* XXX handle this */  
1300 - /* FALLTHRU */  
1301 - default:  
1302 - return -ENOTSUP;  
1303 - }  
1304 - return 0;  
1305 -}  
1306 -  
1307 -static int raw_set_locked(BlockDriverState *bs, int locked)  
1308 -{  
1309 - BDRVRawState *s = bs->opaque;  
1310 -  
1311 - switch(s->type) {  
1312 - case FTYPE_CD:  
1313 - if (s->fd < 0)  
1314 - return -ENOTSUP;  
1315 - if (ioctl (s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {  
1316 - /* Note: an error can happen if the distribution automatically  
1317 - mounts the CD-ROM */  
1318 - // perror("CDROM_LOCKDOOR");  
1319 - }  
1320 - break;  
1321 - default:  
1322 - return -ENOTSUP;  
1323 - }  
1324 - return 0;  
1325 -}  
1326 -  
1327 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) 1098 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1328 { 1099 {
1329 return -ENOTSUP; 1100 return -ENOTSUP;
@@ -1335,26 +1106,6 @@ static int fd_open(BlockDriverState *bs) @@ -1335,26 +1106,6 @@ static int fd_open(BlockDriverState *bs)
1335 return 0; 1106 return 0;
1336 } 1107 }
1337 1108
1338 -static int raw_is_inserted(BlockDriverState *bs)  
1339 -{  
1340 - return 1;  
1341 -}  
1342 -  
1343 -static int raw_media_changed(BlockDriverState *bs)  
1344 -{  
1345 - return -ENOTSUP;  
1346 -}  
1347 -  
1348 -static int raw_eject(BlockDriverState *bs, int eject_flag)  
1349 -{  
1350 - return -ENOTSUP;  
1351 -}  
1352 -  
1353 -static int raw_set_locked(BlockDriverState *bs, int locked)  
1354 -{  
1355 - return -ENOTSUP;  
1356 -}  
1357 -  
1358 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) 1109 static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
1359 { 1110 {
1360 return -ENOTSUP; 1111 return -ENOTSUP;
@@ -1415,22 +1166,315 @@ static BlockDriver bdrv_host_device = { @@ -1415,22 +1166,315 @@ static BlockDriver bdrv_host_device = {
1415 .bdrv_write = raw_write, 1166 .bdrv_write = raw_write,
1416 .bdrv_getlength = raw_getlength, 1167 .bdrv_getlength = raw_getlength,
1417 1168
  1169 + /* generic scsi device */
  1170 + .bdrv_ioctl = raw_ioctl,
  1171 +#ifdef CONFIG_AIO
  1172 + .bdrv_aio_ioctl = raw_aio_ioctl,
  1173 +#endif
  1174 +};
  1175 +
  1176 +#ifdef __linux__
  1177 +static int floppy_open(BlockDriverState *bs, const char *filename, int flags)
  1178 +{
  1179 + BDRVRawState *s = bs->opaque;
  1180 + int ret;
  1181 +
  1182 + posix_aio_init();
  1183 +
  1184 + s->type = FTYPE_FD;
  1185 + /* open will not fail even if no floppy is inserted */
  1186 + s->open_flags |= O_NONBLOCK;
  1187 +
  1188 + ret = raw_open_common(bs, filename, flags);
  1189 + if (ret)
  1190 + return ret;
  1191 +
  1192 + /* close fd so that we can reopen it as needed */
  1193 + close(s->fd);
  1194 + s->fd = -1;
  1195 + s->fd_media_changed = 1;
  1196 +
  1197 + return 0;
  1198 +}
  1199 +
  1200 +static int floppy_is_inserted(BlockDriverState *bs)
  1201 +{
  1202 + return fd_open(bs) >= 0;
  1203 +}
  1204 +
  1205 +static int floppy_media_changed(BlockDriverState *bs)
  1206 +{
  1207 + BDRVRawState *s = bs->opaque;
  1208 + int ret;
  1209 +
  1210 + /*
  1211 + * XXX: we do not have a true media changed indication.
  1212 + * It does not work if the floppy is changed without trying to read it.
  1213 + */
  1214 + fd_open(bs);
  1215 + ret = s->fd_media_changed;
  1216 + s->fd_media_changed = 0;
  1217 +#ifdef DEBUG_FLOPPY
  1218 + printf("Floppy changed=%d\n", ret);
  1219 +#endif
  1220 + return ret;
  1221 +}
  1222 +
  1223 +static int floppy_eject(BlockDriverState *bs, int eject_flag)
  1224 +{
  1225 + BDRVRawState *s = bs->opaque;
  1226 + int fd;
  1227 +
  1228 + if (s->fd >= 0) {
  1229 + close(s->fd);
  1230 + s->fd = -1;
  1231 + }
  1232 + fd = open(bs->filename, s->open_flags | O_NONBLOCK);
  1233 + if (fd >= 0) {
  1234 + if (ioctl(fd, FDEJECT, 0) < 0)
  1235 + perror("FDEJECT");
  1236 + close(fd);
  1237 + }
  1238 +
  1239 + return 0;
  1240 +}
  1241 +
  1242 +static BlockDriver bdrv_host_floppy = {
  1243 + .format_name = "host_floppy",
  1244 + .instance_size = sizeof(BDRVRawState),
  1245 + .bdrv_open = floppy_open,
  1246 + .bdrv_close = raw_close,
  1247 + .bdrv_create = hdev_create,
  1248 + .bdrv_flush = raw_flush,
  1249 +
  1250 +#ifdef CONFIG_AIO
  1251 + .bdrv_aio_readv = raw_aio_readv,
  1252 + .bdrv_aio_writev = raw_aio_writev,
  1253 +#endif
  1254 +
  1255 + .bdrv_read = raw_read,
  1256 + .bdrv_write = raw_write,
  1257 + .bdrv_getlength = raw_getlength,
  1258 +
  1259 + /* removable device support */
  1260 + .bdrv_is_inserted = floppy_is_inserted,
  1261 + .bdrv_media_changed = floppy_media_changed,
  1262 + .bdrv_eject = floppy_eject,
  1263 +
  1264 + /* generic scsi device */
  1265 + .bdrv_ioctl = raw_ioctl,
  1266 +#ifdef CONFIG_AIO
  1267 + .bdrv_aio_ioctl = raw_aio_ioctl,
  1268 +#endif
  1269 +};
  1270 +
  1271 +static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
  1272 +{
  1273 + BDRVRawState *s = bs->opaque;
  1274 +
  1275 + /* open will not fail even if no CD is inserted */
  1276 + s->open_flags |= O_NONBLOCK;
  1277 + s->type = FTYPE_CD;
  1278 +
  1279 + return raw_open_common(bs, filename, flags);
  1280 +}
  1281 +
  1282 +static int cdrom_is_inserted(BlockDriverState *bs)
  1283 +{
  1284 + BDRVRawState *s = bs->opaque;
  1285 + int ret;
  1286 +
  1287 + ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
  1288 + if (ret == CDS_DISC_OK)
  1289 + return 1;
  1290 + return 0;
  1291 +}
  1292 +
  1293 +static int cdrom_eject(BlockDriverState *bs, int eject_flag)
  1294 +{
  1295 + BDRVRawState *s = bs->opaque;
  1296 +
  1297 + if (eject_flag) {
  1298 + if (ioctl(s->fd, CDROMEJECT, NULL) < 0)
  1299 + perror("CDROMEJECT");
  1300 + } else {
  1301 + if (ioctl(s->fd, CDROMCLOSETRAY, NULL) < 0)
  1302 + perror("CDROMEJECT");
  1303 + }
  1304 +
  1305 + return 0;
  1306 +}
  1307 +
  1308 +static int cdrom_set_locked(BlockDriverState *bs, int locked)
  1309 +{
  1310 + BDRVRawState *s = bs->opaque;
  1311 +
  1312 + if (ioctl(s->fd, CDROM_LOCKDOOR, locked) < 0) {
  1313 + /*
  1314 + * Note: an error can happen if the distribution automatically
  1315 + * mounts the CD-ROM
  1316 + */
  1317 + /* perror("CDROM_LOCKDOOR"); */
  1318 + }
  1319 +
  1320 + return 0;
  1321 +}
  1322 +
  1323 +static BlockDriver bdrv_host_cdrom = {
  1324 + .format_name = "host_cdrom",
  1325 + .instance_size = sizeof(BDRVRawState),
  1326 + .bdrv_open = cdrom_open,
  1327 + .bdrv_close = raw_close,
  1328 + .bdrv_create = hdev_create,
  1329 + .bdrv_flush = raw_flush,
  1330 +
  1331 +#ifdef CONFIG_AIO
  1332 + .bdrv_aio_readv = raw_aio_readv,
  1333 + .bdrv_aio_writev = raw_aio_writev,
  1334 +#endif
  1335 +
  1336 + .bdrv_read = raw_read,
  1337 + .bdrv_write = raw_write,
  1338 + .bdrv_getlength = raw_getlength,
  1339 +
  1340 + /* removable device support */
  1341 + .bdrv_is_inserted = cdrom_is_inserted,
  1342 + .bdrv_eject = cdrom_eject,
  1343 + .bdrv_set_locked = cdrom_set_locked,
  1344 +
  1345 + /* generic scsi device */
  1346 + .bdrv_ioctl = raw_ioctl,
  1347 +#ifdef CONFIG_AIO
  1348 + .bdrv_aio_ioctl = raw_aio_ioctl,
  1349 +#endif
  1350 +};
  1351 +#endif /* __linux__ */
  1352 +
  1353 +#ifdef __FreeBSD__
  1354 +static int cdrom_open(BlockDriverState *bs, const char *filename, int flags)
  1355 +{
  1356 + BDRVRawState *s = bs->opaque;
  1357 + int ret;
  1358 +
  1359 + s->type = FTYPE_CD;
  1360 +
  1361 + ret = raw_open_common(bs, filename, flags);
  1362 + if (ret)
  1363 + return ret;
  1364 +
  1365 + /* make sure the door isnt locked at this time */
  1366 + ioctl(s->fd, CDIOCALLOW);
  1367 + return 0;
  1368 +}
  1369 +
  1370 +static int cdrom_reopen(BlockDriverState *bs)
  1371 +{
  1372 + BDRVRawState *s = bs->opaque;
  1373 + int fd;
  1374 +
  1375 + /*
  1376 + * Force reread of possibly changed/newly loaded disc,
  1377 + * FreeBSD seems to not notice sometimes...
  1378 + */
  1379 + if (s->fd >= 0)
  1380 + close(s->fd);
  1381 + fd = open(bs->filename, s->open_flags, 0644);
  1382 + if (fd < 0) {
  1383 + s->fd = -1;
  1384 + return -EIO;
  1385 + }
  1386 + s->fd = fd;
  1387 +
  1388 + /* make sure the door isnt locked at this time */
  1389 + ioctl(s->fd, CDIOCALLOW);
  1390 + return 0;
  1391 +}
  1392 +
  1393 +static int cdrom_is_inserted(BlockDriverState *bs)
  1394 +{
  1395 + return raw_getlength(bs) > 0;
  1396 +}
  1397 +
  1398 +static int cdrom_eject(BlockDriverState *bs, int eject_flag)
  1399 +{
  1400 + BDRVRawState *s = bs->opaque;
  1401 +
  1402 + if (s->fd < 0)
  1403 + return -ENOTSUP;
  1404 +
  1405 + (void) ioctl(s->fd, CDIOCALLOW);
  1406 +
  1407 + if (eject_flag) {
  1408 + if (ioctl(s->fd, CDIOCEJECT) < 0)
  1409 + perror("CDIOCEJECT");
  1410 + } else {
  1411 + if (ioctl(s->fd, CDIOCCLOSE) < 0)
  1412 + perror("CDIOCCLOSE");
  1413 + }
  1414 +
  1415 + if (cdrom_reopen(bs) < 0)
  1416 + return -ENOTSUP;
  1417 + return 0;
  1418 +}
  1419 +
  1420 +static int cdrom_set_locked(BlockDriverState *bs, int locked)
  1421 +{
  1422 + BDRVRawState *s = bs->opaque;
  1423 +
  1424 + if (s->fd < 0)
  1425 + return -ENOTSUP;
  1426 + if (ioctl(s->fd, (locked ? CDIOCPREVENT : CDIOCALLOW)) < 0) {
  1427 + /*
  1428 + * Note: an error can happen if the distribution automatically
  1429 + * mounts the CD-ROM
  1430 + */
  1431 + /* perror("CDROM_LOCKDOOR"); */
  1432 + }
  1433 +
  1434 + return 0;
  1435 +}
  1436 +
  1437 +static BlockDriver bdrv_host_cdrom = {
  1438 + .format_name = "host_cdrom",
  1439 + .instance_size = sizeof(BDRVRawState),
  1440 + .bdrv_open = cdrom_open,
  1441 + .bdrv_close = raw_close,
  1442 + .bdrv_create = hdev_create,
  1443 + .bdrv_flush = raw_flush,
  1444 +
  1445 +#ifdef CONFIG_AIO
  1446 + .bdrv_aio_readv = raw_aio_readv,
  1447 + .bdrv_aio_writev = raw_aio_writev,
  1448 +#endif
  1449 +
  1450 + .bdrv_read = raw_read,
  1451 + .bdrv_write = raw_write,
  1452 + .bdrv_getlength = raw_getlength,
  1453 +
1418 /* removable device support */ 1454 /* removable device support */
1419 - .bdrv_is_inserted = raw_is_inserted,  
1420 - .bdrv_media_changed = raw_media_changed,  
1421 - .bdrv_eject = raw_eject,  
1422 - .bdrv_set_locked = raw_set_locked, 1455 + .bdrv_is_inserted = cdrom_is_inserted,
  1456 + .bdrv_eject = cdrom_eject,
  1457 + .bdrv_set_locked = cdrom_set_locked,
  1458 +
1423 /* generic scsi device */ 1459 /* generic scsi device */
1424 - .bdrv_ioctl = raw_ioctl, 1460 + .bdrv_ioctl = raw_ioctl,
1425 #ifdef CONFIG_AIO 1461 #ifdef CONFIG_AIO
1426 - .bdrv_aio_ioctl = raw_aio_ioctl, 1462 + .bdrv_aio_ioctl = raw_aio_ioctl,
1427 #endif 1463 #endif
1428 }; 1464 };
  1465 +#endif /* __FreeBSD__ */
1429 1466
1430 static void bdrv_raw_init(void) 1467 static void bdrv_raw_init(void)
1431 { 1468 {
1432 bdrv_register(&bdrv_raw); 1469 bdrv_register(&bdrv_raw);
1433 bdrv_register(&bdrv_host_device); 1470 bdrv_register(&bdrv_host_device);
  1471 +#ifdef __linux__
  1472 + bdrv_register(&bdrv_host_floppy);
  1473 + bdrv_register(&bdrv_host_cdrom);
  1474 +#endif
  1475 +#ifdef __FreeBSD__
  1476 + bdrv_register(&bdrv_host_cdrom);
  1477 +#endif
1434 } 1478 }
1435 1479
1436 block_init(bdrv_raw_init); 1480 block_init(bdrv_raw_init);