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