Imported xen patches.
[people/pmueller/ipfire-2.x.git] / src / patches / 60047_xen-blkfront-cdrom.patch1
1 From: plc@novell.com
2 Subject: implement forwarding of CD-ROM specific commands
3 Patch-mainline: obsolete
4 References: fate#300964
5
6 Index: head-2008-10-24/drivers/cdrom/Makefile
7 ===================================================================
8 --- head-2008-10-24.orig/drivers/cdrom/Makefile 2008-10-24 14:05:33.000000000 +0200
9 +++ head-2008-10-24/drivers/cdrom/Makefile 2008-10-01 16:35:07.000000000 +0200
10 @@ -9,6 +9,7 @@ obj-$(CONFIG_BLK_DEV_IDECD) +=
11 obj-$(CONFIG_BLK_DEV_SR) += cdrom.o
12 obj-$(CONFIG_PARIDE_PCD) += cdrom.o
13 obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o
14 +obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += cdrom.o
15
16 obj-$(CONFIG_VIOCD) += viocd.o cdrom.o
17 obj-$(CONFIG_GDROM) += gdrom.o cdrom.o
18 Index: head-2008-10-24/drivers/xen/blkfront/Makefile
19 ===================================================================
20 --- head-2008-10-24.orig/drivers/xen/blkfront/Makefile 2008-10-24 14:05:33.000000000 +0200
21 +++ head-2008-10-24/drivers/xen/blkfront/Makefile 2008-10-01 16:35:07.000000000 +0200
22 @@ -1,5 +1,5 @@
23
24 obj-$(CONFIG_XEN_BLKDEV_FRONTEND) := xenblk.o
25
26 -xenblk-objs := blkfront.o vbd.o
27 +xenblk-objs := blkfront.o vbd.o vcd.o
28
29 Index: head-2008-10-24/drivers/xen/blkfront/blkfront.c
30 ===================================================================
31 --- head-2008-10-24.orig/drivers/xen/blkfront/blkfront.c 2008-10-01 16:35:04.000000000 +0200
32 +++ head-2008-10-24/drivers/xen/blkfront/blkfront.c 2008-10-01 16:35:07.000000000 +0200
33 @@ -372,6 +372,8 @@ static void connect(struct blkfront_info
34 add_disk(info->gd);
35
36 info->is_ready = 1;
37 +
38 + register_vcd(info);
39 }
40
41 /**
42 @@ -402,6 +404,8 @@ static void blkfront_closing(struct xenb
43
44 xlvbd_sysfs_delif(info);
45
46 + unregister_vcd(info);
47 +
48 xlvbd_del(info);
49
50 out:
51 Index: head-2008-10-24/drivers/xen/blkfront/block.h
52 ===================================================================
53 --- head-2008-10-24.orig/drivers/xen/blkfront/block.h 2008-10-24 14:05:33.000000000 +0200
54 +++ head-2008-10-24/drivers/xen/blkfront/block.h 2008-10-01 16:35:07.000000000 +0200
55 @@ -154,4 +154,8 @@ static inline void xlvbd_sysfs_delif(str
56 }
57 #endif
58
59 +/* Virtual cdrom block-device */
60 +extern void register_vcd(struct blkfront_info *info);
61 +extern void unregister_vcd(struct blkfront_info *info);
62 +
63 #endif /* __XEN_DRIVERS_BLOCK_H__ */
64 Index: head-2008-10-24/drivers/xen/blkfront/vbd.c
65 ===================================================================
66 --- head-2008-10-24.orig/drivers/xen/blkfront/vbd.c 2008-10-24 14:05:33.000000000 +0200
67 +++ head-2008-10-24/drivers/xen/blkfront/vbd.c 2008-10-24 14:08:33.000000000 +0200
68 @@ -281,7 +281,8 @@ xlvbd_add(blkif_sector_t capacity, int v
69 goto out;
70 info->mi = mi;
71
72 - if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0)
73 + if (!(vdisk_info & VDISK_CDROM) &&
74 + (minor & ((1 << mi->type->partn_shift) - 1)) == 0)
75 nr_minors = 1 << mi->type->partn_shift;
76
77 gd = alloc_disk(nr_minors);
78 @@ -290,7 +291,7 @@ xlvbd_add(blkif_sector_t capacity, int v
79
80 offset = mi->index * mi->type->disks_per_major +
81 (minor >> mi->type->partn_shift);
82 - if (nr_minors > 1) {
83 + if (nr_minors > 1 || (vdisk_info & VDISK_CDROM)) {
84 if (offset < 26) {
85 sprintf(gd->disk_name, "%s%c",
86 mi->type->diskname, 'a' + offset );
87 Index: head-2008-10-24/drivers/xen/blkfront/vcd.c
88 ===================================================================
89 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
90 +++ head-2008-10-24/drivers/xen/blkfront/vcd.c 2008-10-01 16:35:07.000000000 +0200
91 @@ -0,0 +1,476 @@
92 +/*******************************************************************************
93 +* vcd.c
94 +*
95 +* Implements CDROM cmd packet passing between frontend guest and backend driver.
96 +*
97 +* Copyright (c) 2008, Pat Campell plc@novell.com
98 +*
99 +* Permission is hereby granted, free of charge, to any person obtaining a copy
100 +* of this source file (the "Software"), to deal in the Software without
101 +* restriction, including without limitation the rights to use, copy, modify,
102 +* merge, publish, distribute, sublicense, and/or sell copies of the Software,
103 +* and to permit persons to whom the Software is furnished to do so, subject to
104 +* the following conditions:
105 +*
106 +* The above copyright notice and this permission notice shall be included in
107 +* all copies or substantial portions of the Software.
108 +*
109 +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
110 +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
111 +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
112 +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
113 +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
114 +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
115 +* IN THE SOFTWARE.
116 +*/
117 +
118 +#define REVISION "$Revision: 1.0 $"
119 +
120 +#include <linux/module.h>
121 +#include <linux/blkdev.h>
122 +#include <linux/list.h>
123 +#include <linux/cdrom.h>
124 +#include <xen/interface/io/cdromif.h>
125 +#include "block.h"
126 +
127 +/* List of cdrom_device_info, can have as many as blkfront supports */
128 +struct vcd_disk {
129 + struct list_head vcd_entry;
130 + struct cdrom_device_info vcd_cdrom_info;
131 + spinlock_t vcd_cdrom_info_lock;
132 +};
133 +static LIST_HEAD(vcd_disks);
134 +static DEFINE_SPINLOCK(vcd_disks_lock);
135 +
136 +static struct vcd_disk * xencdrom_get_list_entry(struct gendisk *disk)
137 +{
138 + struct vcd_disk * ret_vcd = NULL;
139 + struct vcd_disk * vcd;
140 +
141 + spin_lock(&vcd_disks_lock);
142 + list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
143 + if (vcd->vcd_cdrom_info.disk == disk) {
144 + spin_lock(&vcd->vcd_cdrom_info_lock);
145 + ret_vcd = vcd;
146 + break;
147 + }
148 + }
149 + spin_unlock(&vcd_disks_lock);
150 + return ret_vcd;
151 +}
152 +
153 +static void submit_message(struct blkfront_info *info, void * sp)
154 +{
155 + struct request *req = NULL;
156 +
157 + req = blk_get_request(info->rq, READ, __GFP_WAIT);
158 + if (blk_rq_map_kern(info->rq, req, sp, PAGE_SIZE, __GFP_WAIT))
159 + goto out;
160 +
161 + req->rq_disk = info->gd;
162 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
163 + req->cmd_type = REQ_TYPE_BLOCK_PC;
164 + req->cmd_flags |= REQ_NOMERGE;
165 +#else
166 + req->flags |= REQ_BLOCK_PC;
167 +#endif
168 + req->sector = 0;
169 + req->nr_sectors = 1;
170 + req->timeout = 60*HZ;
171 +
172 + blk_execute_rq(req->q, info->gd, req, 1);
173 +
174 +out:
175 + blk_put_request(req);
176 +}
177 +
178 +static int submit_cdrom_cmd(struct blkfront_info *info,
179 + struct packet_command * cgc)
180 +{
181 + int ret = 0;
182 + struct page *page;
183 + size_t size;
184 + union xen_block_packet *sp;
185 + struct xen_cdrom_packet *xcp;
186 + struct vcd_generic_command * vgc;
187 +
188 + if (cgc->buffer && cgc->buflen > MAX_PACKET_DATA) {
189 + printk(KERN_WARNING "%s() Packet buffer length is to large \n", __func__);
190 + return -EIO;
191 + }
192 +
193 + page = alloc_page(GFP_NOIO);
194 + if (!page) {
195 + printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
196 + return -ENOMEM;
197 + }
198 +
199 + size = PAGE_SIZE;
200 + memset(page_address(page), 0, PAGE_SIZE);
201 + sp = page_address(page);
202 + xcp = &(sp->xcp);
203 + xcp->type = XEN_TYPE_CDROM_PACKET;
204 + xcp->payload_offset = PACKET_PAYLOAD_OFFSET;
205 +
206 + vgc = (struct vcd_generic_command *)((char *)sp + xcp->payload_offset);
207 + memcpy(vgc->cmd, cgc->cmd, CDROM_PACKET_SIZE);
208 + vgc->stat = cgc->stat;
209 + vgc->data_direction = cgc->data_direction;
210 + vgc->quiet = cgc->quiet;
211 + vgc->timeout = cgc->timeout;
212 + if (cgc->sense) {
213 + vgc->sense_offset = PACKET_SENSE_OFFSET;
214 + memcpy((char *)sp + vgc->sense_offset, cgc->sense, sizeof(struct request_sense));
215 + }
216 + if (cgc->buffer) {
217 + vgc->buffer_offset = PACKET_BUFFER_OFFSET;
218 + memcpy((char *)sp + vgc->buffer_offset, cgc->buffer, cgc->buflen);
219 + vgc->buflen = cgc->buflen;
220 + }
221 +
222 + submit_message(info,sp);
223 +
224 + if (xcp->ret)
225 + ret = xcp->err;
226 +
227 + if (cgc->sense) {
228 + memcpy(cgc->sense, (char *)sp + PACKET_SENSE_OFFSET, sizeof(struct request_sense));
229 + }
230 + if (cgc->buffer && cgc->buflen) {
231 + memcpy(cgc->buffer, (char *)sp + PACKET_BUFFER_OFFSET, cgc->buflen);
232 + }
233 +
234 + __free_page(page);
235 + return ret;
236 +}
237 +
238 +
239 +static int xencdrom_open(struct cdrom_device_info *cdi, int purpose)
240 +{
241 + int ret = 0;
242 + struct page *page;
243 + struct blkfront_info *info;
244 + union xen_block_packet *sp;
245 + struct xen_cdrom_open *xco;
246 +
247 + info = cdi->disk->private_data;
248 +
249 + if (strlen(info->xbdev->otherend) > MAX_PACKET_DATA) {
250 + return -EIO;
251 + }
252 +
253 + page = alloc_page(GFP_NOIO);
254 + if (!page) {
255 + printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
256 + return -ENOMEM;
257 + }
258 +
259 + memset(page_address(page), 0, PAGE_SIZE);
260 + sp = page_address(page);
261 + xco = &(sp->xco);
262 + xco->type = XEN_TYPE_CDROM_OPEN;
263 + xco->payload_offset = sizeof(struct xen_cdrom_open);
264 + strcpy((char *)sp + xco->payload_offset, info->xbdev->otherend);
265 +
266 + submit_message(info,sp);
267 +
268 + if (xco->ret) {
269 + ret = xco->err;
270 + goto out;
271 + }
272 +
273 + if (xco->media_present)
274 + set_capacity(cdi->disk, xco->sectors);
275 +
276 +out:
277 + __free_page(page);
278 + return ret;
279 +}
280 +
281 +static void xencdrom_release(struct cdrom_device_info *cdi)
282 +{
283 +}
284 +
285 +static int xencdrom_media_changed(struct cdrom_device_info *cdi, int disc_nr)
286 +{
287 + int ret;
288 + struct page *page;
289 + struct blkfront_info *info;
290 + union xen_block_packet *sp;
291 + struct xen_cdrom_media_changed *xcmc;
292 +
293 + info = cdi->disk->private_data;
294 +
295 + page = alloc_page(GFP_NOIO);
296 + if (!page) {
297 + printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
298 + return -ENOMEM;
299 + }
300 +
301 + memset(page_address(page), 0, PAGE_SIZE);
302 + sp = page_address(page);
303 + xcmc = &(sp->xcmc);
304 + xcmc->type = XEN_TYPE_CDROM_MEDIA_CHANGED;
305 + submit_message(info,sp);
306 + ret = xcmc->media_changed;
307 +
308 + __free_page(page);
309 +
310 + return ret;
311 +}
312 +
313 +static int xencdrom_tray_move(struct cdrom_device_info *cdi, int position)
314 +{
315 + int ret;
316 + struct packet_command cgc;
317 + struct blkfront_info *info;
318 +
319 + info = cdi->disk->private_data;
320 + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
321 + cgc.cmd[0] = GPCMD_START_STOP_UNIT;
322 + if (position)
323 + cgc.cmd[4] = 2;
324 + else
325 + cgc.cmd[4] = 3;
326 + ret = submit_cdrom_cmd(info, &cgc);
327 + return ret;
328 +}
329 +
330 +static int xencdrom_lock_door(struct cdrom_device_info *cdi, int lock)
331 +{
332 + int ret = 0;
333 + struct blkfront_info *info;
334 + struct packet_command cgc;
335 +
336 + info = cdi->disk->private_data;
337 + init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
338 + cgc.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
339 + cgc.cmd[4] = lock;
340 + ret = submit_cdrom_cmd(info, &cgc);
341 + return ret;
342 +}
343 +
344 +static int xencdrom_packet(struct cdrom_device_info *cdi,
345 + struct packet_command *cgc)
346 +{
347 + int ret = -EIO;
348 + struct blkfront_info *info;
349 +
350 + info = cdi->disk->private_data;
351 + ret = submit_cdrom_cmd(info, cgc);
352 + cgc->stat = ret;
353 + return ret;
354 +}
355 +
356 +static int xencdrom_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
357 + void *arg)
358 +{
359 + return -EINVAL;
360 +}
361 +
362 +/* Query backend to see if CDROM packets are supported */
363 +static int xencdrom_supported(struct blkfront_info *info)
364 +{
365 + struct page *page;
366 + union xen_block_packet *sp;
367 + struct xen_cdrom_support *xcs;
368 +
369 + page = alloc_page(GFP_NOIO);
370 + if (!page) {
371 + printk(KERN_CRIT "%s() Unable to allocate page\n", __func__);
372 + return -ENOMEM;
373 + }
374 +
375 + memset(page_address(page), 0, PAGE_SIZE);
376 + sp = page_address(page);
377 + xcs = &(sp->xcs);
378 + xcs->type = XEN_TYPE_CDROM_SUPPORT;
379 + submit_message(info,sp);
380 + return xcs->supported;
381 +}
382 +
383 +static struct cdrom_device_ops xencdrom_dops = {
384 + .open = xencdrom_open,
385 + .release = xencdrom_release,
386 + .media_changed = xencdrom_media_changed,
387 + .tray_move = xencdrom_tray_move,
388 + .lock_door = xencdrom_lock_door,
389 + .generic_packet = xencdrom_packet,
390 + .audio_ioctl = xencdrom_audio_ioctl,
391 + .capability = (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | \
392 + CDC_MEDIA_CHANGED | CDC_GENERIC_PACKET | CDC_DVD | \
393 + CDC_CD_R),
394 + .n_minors = 1,
395 +};
396 +
397 +static int xencdrom_block_open(struct inode *inode, struct file *file)
398 +{
399 + struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
400 + struct vcd_disk * vcd;
401 + int ret = 0;
402 +
403 + if ((vcd = xencdrom_get_list_entry(info->gd))) {
404 + ret = cdrom_open(&vcd->vcd_cdrom_info, inode, file);
405 + info->users = vcd->vcd_cdrom_info.use_count;
406 + spin_unlock(&vcd->vcd_cdrom_info_lock);
407 + }
408 + return ret;
409 +}
410 +
411 +static int xencdrom_block_release(struct inode *inode, struct file *file)
412 +{
413 + struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
414 + struct vcd_disk * vcd;
415 + int ret = 0;
416 +
417 + if ((vcd = xencdrom_get_list_entry(info->gd))) {
418 + ret = cdrom_release(&vcd->vcd_cdrom_info, file);
419 + spin_unlock(&vcd->vcd_cdrom_info_lock);
420 + if (vcd->vcd_cdrom_info.use_count == 0) {
421 + info->users = 1;
422 + blkif_release(inode, file);
423 + }
424 + }
425 + return ret;
426 +}
427 +
428 +static int xencdrom_block_ioctl(struct inode *inode, struct file *file,
429 + unsigned cmd, unsigned long arg)
430 +{
431 + struct blkfront_info *info = inode->i_bdev->bd_disk->private_data;
432 + struct vcd_disk * vcd;
433 + int ret = 0;
434 +
435 + if (!(vcd = xencdrom_get_list_entry(info->gd)))
436 + goto out;
437 +
438 + switch (cmd) {
439 + case 2285: /* SG_IO */
440 + ret = -ENOSYS;
441 + break;
442 + case CDROMEJECT:
443 + ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 1);
444 + break;
445 + case CDROMCLOSETRAY:
446 + ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 0);
447 + break;
448 + case CDROM_GET_CAPABILITY:
449 + ret = vcd->vcd_cdrom_info.ops->capability & ~vcd->vcd_cdrom_info.mask;
450 + break;
451 + case CDROM_SET_OPTIONS:
452 + ret = vcd->vcd_cdrom_info.options;
453 + break;
454 + case CDROM_SEND_PACKET:
455 + {
456 + struct packet_command * cgc = (struct packet_command *)arg;
457 + ret = submit_cdrom_cmd(info, cgc);
458 + }
459 + break;
460 + default:
461 + /* Not supported, augment supported above if necessary */
462 + printk( "%s():%d Unsupported IOCTL:%x \n", __func__, __LINE__, cmd);
463 + ret = -ENOTTY;
464 + break;
465 + }
466 + spin_unlock(&vcd->vcd_cdrom_info_lock);
467 +out:
468 + return ret;
469 +}
470 +
471 +/* Called as result of cdrom_open, vcd_cdrom_info_lock already held */
472 +static int xencdrom_block_media_changed(struct gendisk *disk)
473 +{
474 + struct vcd_disk * vcd;
475 + struct vcd_disk * ret_vcd = NULL;
476 + int ret = 0;
477 +
478 + spin_lock(&vcd_disks_lock);
479 + list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
480 + if (vcd->vcd_cdrom_info.disk == disk) {
481 + ret_vcd = vcd;
482 + break;
483 + }
484 + }
485 + spin_unlock(&vcd_disks_lock);
486 + if (ret_vcd) {
487 + ret = cdrom_media_changed(&ret_vcd->vcd_cdrom_info);
488 + }
489 + return ret;
490 +}
491 +
492 +static struct block_device_operations xencdrom_bdops =
493 +{
494 + .owner = THIS_MODULE,
495 + .open = xencdrom_block_open,
496 + .release = xencdrom_block_release,
497 + .ioctl = xencdrom_block_ioctl,
498 + .media_changed = xencdrom_block_media_changed,
499 +};
500 +
501 +void register_vcd(struct blkfront_info *info)
502 +{
503 + struct gendisk * gd = info->gd;
504 + struct vcd_disk * vcd;
505 +
506 + /* Make sure this is for a CD device */
507 + if (!(gd->flags & GENHD_FL_CD))
508 + goto out;
509 +
510 + /* Make sure we have backend support */
511 + if (!xencdrom_supported(info)) {
512 + goto out;
513 + }
514 +
515 + /* Create new vcd_disk and fill in cdrom_info */
516 + vcd = (struct vcd_disk *)kzalloc(sizeof(struct vcd_disk), GFP_KERNEL);
517 + if (!vcd) {
518 + printk(KERN_INFO "%s(): Unable to allocate vcd struct!\n", __func__);
519 + goto out;
520 + }
521 + spin_lock_init(&vcd->vcd_cdrom_info_lock);
522 +
523 + vcd->vcd_cdrom_info.ops = &xencdrom_dops;
524 + vcd->vcd_cdrom_info.speed = 4;
525 + vcd->vcd_cdrom_info.capacity = 1;
526 + vcd->vcd_cdrom_info.options = 0;
527 + strcpy(vcd->vcd_cdrom_info.name, gd->disk_name);
528 + vcd->vcd_cdrom_info.mask = ( CDC_CD_RW | CDC_DVD_R | CDC_DVD_RAM |
529 + CDC_SELECT_DISC | CDC_SELECT_SPEED |
530 + CDC_MRW | CDC_MRW_W | CDC_RAM);
531 +
532 + if (register_cdrom(&(vcd->vcd_cdrom_info)) != 0) {
533 + printk(KERN_WARNING "%s() Cannot register blkdev as a cdrom %d!\n", __func__,
534 + gd->major);
535 + goto err_out;
536 + }
537 + xencdrom_bdops.owner = gd->fops->owner;
538 + gd->fops = &xencdrom_bdops;
539 + vcd->vcd_cdrom_info.disk = gd;
540 +
541 + spin_lock(&vcd_disks_lock);
542 + list_add(&(vcd->vcd_entry), &vcd_disks);
543 + spin_unlock(&vcd_disks_lock);
544 +out:
545 + return;
546 +err_out:
547 + kfree(vcd);
548 +}
549 +
550 +void unregister_vcd(struct blkfront_info *info) {
551 + struct gendisk * gd = info->gd;
552 + struct vcd_disk * vcd;
553 +
554 + spin_lock(&vcd_disks_lock);
555 + list_for_each_entry(vcd, &vcd_disks, vcd_entry) {
556 + if (vcd->vcd_cdrom_info.disk == gd) {
557 + spin_lock(&vcd->vcd_cdrom_info_lock);
558 + unregister_cdrom(&vcd->vcd_cdrom_info);
559 + list_del(&vcd->vcd_entry);
560 + spin_unlock(&vcd->vcd_cdrom_info_lock);
561 + kfree(vcd);
562 + break;
563 + }
564 + }
565 + spin_unlock(&vcd_disks_lock);
566 +}
567 +
568 Index: head-2008-10-24/include/xen/interface/io/cdromif.h
569 ===================================================================
570 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
571 +++ head-2008-10-24/include/xen/interface/io/cdromif.h 2008-10-01 16:35:07.000000000 +0200
572 @@ -0,0 +1,120 @@
573 +/******************************************************************************
574 + * cdromif.h
575 + *
576 + * Shared definitions between backend driver and Xen guest Virtual CDROM
577 + * block device.
578 + *
579 + * Copyright (c) 2008, Pat Campell plc@novell.com
580 + *
581 + * Permission is hereby granted, free of charge, to any person obtaining a copy
582 + * of this source file (the "Software"), to deal in the Software without
583 + * restriction, including without limitation the rights to use, copy, modify,
584 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
585 + * and to permit persons to whom the Software is furnished to do so, subject to
586 + * the following conditions:
587 + *
588 + * The above copyright notice and this permission notice shall be included in
589 + * all copies or substantial portions of the Software.
590 + *
591 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
592 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
593 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
594 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
595 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
596 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
597 + * IN THE SOFTWARE.
598 + */
599 +
600 +#ifndef __XEN_PUBLIC_IO_CDROMIF_H__
601 +#define __XEN_PUBLIC_IO_CDROMIF_H__
602 +
603 +/*
604 + * Queries backend for CDROM support
605 + */
606 +#define XEN_TYPE_CDROM_SUPPORT _IO('c', 1)
607 +
608 +struct xen_cdrom_support
609 +{
610 + uint32_t type;
611 + int8_t ret; /* returned, 0 succeded, -1 error */
612 + int8_t err; /* returned, backend errno */
613 + int8_t supported; /* returned, 1 supported */
614 +};
615 +
616 +/*
617 + * Opens backend device, returns drive geometry or
618 + * any encountered errors
619 + */
620 +#define XEN_TYPE_CDROM_OPEN _IO('c', 2)
621 +
622 +struct xen_cdrom_open
623 +{
624 + uint32_t type;
625 + int8_t ret;
626 + int8_t err;
627 + int8_t pad;
628 + int8_t media_present; /* returned */
629 + uint32_t sectors; /* returned */
630 + uint32_t sector_size; /* returned */
631 + int32_t payload_offset; /* offset to backend node name payload */
632 +};
633 +
634 +/*
635 + * Queries backend for media changed status
636 + */
637 +#define XEN_TYPE_CDROM_MEDIA_CHANGED _IO('c', 3)
638 +
639 +struct xen_cdrom_media_changed
640 +{
641 + uint32_t type;
642 + int8_t ret;
643 + int8_t err;
644 + int8_t media_changed; /* returned */
645 +};
646 +
647 +/*
648 + * Sends vcd generic CDROM packet to backend, followed
649 + * immediately by the vcd_generic_command payload
650 + */
651 +#define XEN_TYPE_CDROM_PACKET _IO('c', 4)
652 +
653 +struct xen_cdrom_packet
654 +{
655 + uint32_t type;
656 + int8_t ret;
657 + int8_t err;
658 + int8_t pad[2];
659 + int32_t payload_offset; /* offset to vcd_generic_command payload */
660 +};
661 +
662 +/* CDROM_PACKET_COMMAND, payload for XEN_TYPE_CDROM_PACKET */
663 +struct vcd_generic_command
664 +{
665 + uint8_t cmd[CDROM_PACKET_SIZE];
666 + uint8_t pad[4];
667 + uint32_t buffer_offset;
668 + uint32_t buflen;
669 + int32_t stat;
670 + uint32_t sense_offset;
671 + uint8_t data_direction;
672 + uint8_t pad1[3];
673 + int32_t quiet;
674 + int32_t timeout;
675 +};
676 +
677 +union xen_block_packet
678 +{
679 + uint32_t type;
680 + struct xen_cdrom_support xcs;
681 + struct xen_cdrom_open xco;
682 + struct xen_cdrom_media_changed xcmc;
683 + struct xen_cdrom_packet xcp;
684 +};
685 +
686 +#define PACKET_PAYLOAD_OFFSET (sizeof(struct xen_cdrom_packet))
687 +#define PACKET_SENSE_OFFSET (PACKET_PAYLOAD_OFFSET + sizeof(struct vcd_generic_command))
688 +#define PACKET_BUFFER_OFFSET (PACKET_SENSE_OFFSET + sizeof(struct request_sense))
689 +#define MAX_PACKET_DATA (PAGE_SIZE - sizeof(struct xen_cdrom_packet) - \
690 + sizeof(struct vcd_generic_command) - sizeof(struct request_sense))
691 +
692 +#endif