]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/60047_xen-blkfront-cdrom.patch1
Stop dhcpcd before starting if it was running
[people/pmueller/ipfire-2.x.git] / src / patches / 60047_xen-blkfront-cdrom.patch1
CommitLineData
cc90b958
BS
1From: plc@novell.com
2Subject: implement forwarding of CD-ROM specific commands
3Patch-mainline: obsolete
4References: fate#300964
5
6Index: 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
18Index: 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
29Index: 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:
51Index: 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__ */
64Index: 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 );
87Index: 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+
568Index: 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