[POWERPC] iSeries: Move detection of virtual cdroms
Now we will only have entries in the device tree for the actual existing devices (including their OS/400 properties). This way viocd.c gets all the information about the devices from the device tree. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Acked-by: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
dd9b67ab37
commit
b833b481c1
|
@ -247,9 +247,6 @@ static int __init vio_bus_init(void)
|
|||
int err;
|
||||
struct device_node *node_vroot;
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
iommu_vio_init();
|
||||
|
||||
err = bus_register(&vio_bus_type);
|
||||
if (err) {
|
||||
printk(KERN_ERR "failed to register VIO bus\n");
|
||||
|
|
|
@ -7,7 +7,7 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
|
|||
hvcall.o proc.o htab.o iommu.o misc.o irq.o
|
||||
obj-$(CONFIG_PCI) += pci.o vpdinfo.o
|
||||
obj-$(CONFIG_SMP) += smp.o
|
||||
obj-$(CONFIG_VIOPATH) += viopath.o
|
||||
obj-$(CONFIG_VIOPATH) += viopath.o vio.o
|
||||
obj-$(CONFIG_MODULES) += ksyms.o
|
||||
|
||||
quiet_cmd_dt_strings = DT_STR $@
|
||||
|
|
|
@ -381,10 +381,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
|
|||
dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
|
||||
"IBM,iSeries-viodasd", 1);
|
||||
reg += HVMAXARCHITECTEDVIRTUALDISKS;
|
||||
|
||||
for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
|
||||
dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
|
||||
"IBM,iSeries-viocd", 1);
|
||||
reg += HVMAXARCHITECTEDVIRTUALCDROMS;
|
||||
|
||||
for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
|
||||
|
|
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* Legacy iSeries specific vio initialisation
|
||||
* that needs to be built in (not a module).
|
||||
*
|
||||
* © Copyright 2007 IBM Corporation
|
||||
* Author: Stephen Rothwell
|
||||
* Some parts collected from various other files
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/of.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/iseries/vio.h>
|
||||
#include <asm/iseries/iommu.h>
|
||||
#include <asm/iseries/hv_types.h>
|
||||
#include <asm/iseries/hv_lp_event.h>
|
||||
|
||||
#define FIRST_VTY 0
|
||||
#define NUM_VTYS 1
|
||||
#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS)
|
||||
#define NUM_VSCSIS 1
|
||||
#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS)
|
||||
#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS
|
||||
#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS)
|
||||
#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS
|
||||
#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS)
|
||||
#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS
|
||||
#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
|
||||
#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
|
||||
|
||||
static struct property * __init new_property(const char *name, int length,
|
||||
const void *value)
|
||||
{
|
||||
struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!np)
|
||||
return NULL;
|
||||
np->name = (char *)(np + 1);
|
||||
np->value = np->name + strlen(name) + 1;
|
||||
strcpy(np->name, name);
|
||||
memcpy(np->value, value, length);
|
||||
np->length = length;
|
||||
return np;
|
||||
}
|
||||
|
||||
static void __init free_property(struct property *np)
|
||||
{
|
||||
kfree(np);
|
||||
}
|
||||
|
||||
static struct device_node * __init new_node(const char *path,
|
||||
struct device_node *parent)
|
||||
{
|
||||
struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
|
||||
|
||||
if (!np)
|
||||
return NULL;
|
||||
np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
|
||||
if (!np->full_name) {
|
||||
kfree(np);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(np->full_name, path);
|
||||
of_node_set_flag(np, OF_DYNAMIC);
|
||||
kref_init(&np->kref);
|
||||
np->parent = of_node_get(parent);
|
||||
return np;
|
||||
}
|
||||
|
||||
static void __init free_node(struct device_node *np)
|
||||
{
|
||||
struct property *next;
|
||||
struct property *prop;
|
||||
|
||||
next = np->properties;
|
||||
while (next) {
|
||||
prop = next;
|
||||
next = prop->next;
|
||||
free_property(prop);
|
||||
}
|
||||
of_node_put(np->parent);
|
||||
kfree(np->full_name);
|
||||
kfree(np);
|
||||
}
|
||||
|
||||
static int __init add_string_property(struct device_node *np, const char *name,
|
||||
const char *value)
|
||||
{
|
||||
struct property *nprop = new_property(name, strlen(value) + 1, value);
|
||||
|
||||
if (!nprop)
|
||||
return 0;
|
||||
prom_add_property(np, nprop);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init add_raw_property(struct device_node *np, const char *name,
|
||||
int length, const void *value)
|
||||
{
|
||||
struct property *nprop = new_property(name, length, value);
|
||||
|
||||
if (!nprop)
|
||||
return 0;
|
||||
prom_add_property(np, nprop);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct viocd_waitevent {
|
||||
struct completion com;
|
||||
int rc;
|
||||
u16 sub_result;
|
||||
};
|
||||
|
||||
struct cdrom_info {
|
||||
char rsrcname[10];
|
||||
char type[4];
|
||||
char model[3];
|
||||
};
|
||||
|
||||
static void __init handle_cd_event(struct HvLpEvent *event)
|
||||
{
|
||||
struct viocdlpevent *bevent;
|
||||
struct viocd_waitevent *pwe;
|
||||
|
||||
if (!event)
|
||||
/* Notification that a partition went away! */
|
||||
return;
|
||||
|
||||
/* First, we should NEVER get an int here...only acks */
|
||||
if (hvlpevent_is_int(event)) {
|
||||
printk(KERN_WARNING "handle_cd_event: got an unexpected int\n");
|
||||
if (hvlpevent_need_ack(event)) {
|
||||
event->xRc = HvLpEvent_Rc_InvalidSubtype;
|
||||
HvCallEvent_ackLpEvent(event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bevent = (struct viocdlpevent *)event;
|
||||
|
||||
switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
|
||||
case viocdgetinfo:
|
||||
pwe = (struct viocd_waitevent *)event->xCorrelationToken;
|
||||
pwe->rc = event->xRc;
|
||||
pwe->sub_result = bevent->sub_result;
|
||||
complete(&pwe->com);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_WARNING "handle_cd_event: "
|
||||
"message with unexpected subtype %0x04X!\n",
|
||||
event->xSubtype & VIOMINOR_SUBTYPE_MASK);
|
||||
if (hvlpevent_need_ack(event)) {
|
||||
event->xRc = HvLpEvent_Rc_InvalidSubtype;
|
||||
HvCallEvent_ackLpEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __init get_viocd_info(struct device_node *vio_root)
|
||||
{
|
||||
HvLpEvent_Rc hvrc;
|
||||
u32 unit;
|
||||
struct viocd_waitevent we;
|
||||
struct cdrom_info *unitinfo;
|
||||
dma_addr_t unitinfo_dmaaddr;
|
||||
int ret;
|
||||
|
||||
ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2);
|
||||
if (ret) {
|
||||
printk(KERN_WARNING
|
||||
"get_viocd_info: error opening path to host partition %d\n",
|
||||
viopath_hostLp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize our request handler */
|
||||
vio_setHandler(viomajorsubtype_cdio, handle_cd_event);
|
||||
|
||||
unitinfo = iseries_hv_alloc(
|
||||
sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
|
||||
&unitinfo_dmaaddr, GFP_ATOMIC);
|
||||
if (!unitinfo) {
|
||||
printk(KERN_WARNING
|
||||
"get_viocd_info: error allocating unitinfo\n");
|
||||
goto clear_handler;
|
||||
}
|
||||
|
||||
memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS);
|
||||
|
||||
init_completion(&we.com);
|
||||
|
||||
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
|
||||
HvLpEvent_Type_VirtualIo,
|
||||
viomajorsubtype_cdio | viocdgetinfo,
|
||||
HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
|
||||
viopath_sourceinst(viopath_hostLp),
|
||||
viopath_targetinst(viopath_hostLp),
|
||||
(u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
|
||||
sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0);
|
||||
if (hvrc != HvLpEvent_Rc_Good) {
|
||||
printk(KERN_WARNING
|
||||
"get_viocd_info: cdrom error sending event. rc %d\n",
|
||||
(int)hvrc);
|
||||
goto hv_free;
|
||||
}
|
||||
|
||||
wait_for_completion(&we.com);
|
||||
|
||||
if (we.rc) {
|
||||
printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n",
|
||||
we.rc, we.sub_result);
|
||||
goto hv_free;
|
||||
}
|
||||
|
||||
for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
|
||||
unitinfo[unit].rsrcname[0]; unit++) {
|
||||
struct device_node *np;
|
||||
char name[64];
|
||||
u32 reg = FIRST_VIOCD + unit;
|
||||
|
||||
snprintf(name, sizeof(name), "/vdevice/viocd@%08x", reg);
|
||||
np = new_node(name, vio_root);
|
||||
if (!np)
|
||||
goto hv_free;
|
||||
if (!add_string_property(np, "name", "viocd") ||
|
||||
!add_string_property(np, "device_type", "block") ||
|
||||
!add_string_property(np, "compatible",
|
||||
"IBM,iSeries-viocd") ||
|
||||
!add_raw_property(np, "reg", sizeof(reg), ®) ||
|
||||
!add_raw_property(np, "linux,unit_address",
|
||||
sizeof(unit), &unit) ||
|
||||
!add_raw_property(np, "linux,vio_rsrcname",
|
||||
sizeof(unitinfo[unit].rsrcname),
|
||||
unitinfo[unit].rsrcname) ||
|
||||
!add_raw_property(np, "linux,vio_type",
|
||||
sizeof(unitinfo[unit].type),
|
||||
unitinfo[unit].type) ||
|
||||
!add_raw_property(np, "linux,vio_model",
|
||||
sizeof(unitinfo[unit].model),
|
||||
unitinfo[unit].model))
|
||||
goto node_free;
|
||||
np->name = of_get_property(np, "name", NULL);
|
||||
np->type = of_get_property(np, "device_type", NULL);
|
||||
of_attach_node(np);
|
||||
#ifdef CONFIG_PROC_DEVICETREE
|
||||
if (vio_root->pde) {
|
||||
struct proc_dir_entry *ent;
|
||||
|
||||
ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
|
||||
vio_root->pde);
|
||||
if (ent)
|
||||
proc_device_tree_add_node(np, ent);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
|
||||
node_free:
|
||||
free_node(np);
|
||||
break;
|
||||
}
|
||||
|
||||
hv_free:
|
||||
iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
|
||||
unitinfo, unitinfo_dmaaddr);
|
||||
clear_handler:
|
||||
vio_clearHandler(viomajorsubtype_cdio);
|
||||
viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
|
||||
}
|
||||
|
||||
static int __init iseries_vio_init(void)
|
||||
{
|
||||
struct device_node *vio_root;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return -ENODEV;
|
||||
|
||||
iommu_vio_init();
|
||||
|
||||
vio_root = of_find_node_by_path("/vdevice");
|
||||
if (!vio_root)
|
||||
return -ENODEV;
|
||||
|
||||
if (viopath_hostLp == HvLpIndexInvalid) {
|
||||
vio_set_hostlp();
|
||||
/* If we don't have a host, bail out */
|
||||
if (viopath_hostLp == HvLpIndexInvalid)
|
||||
goto put_node;
|
||||
}
|
||||
|
||||
get_viocd_info(vio_root);
|
||||
|
||||
return 0;
|
||||
|
||||
put_node:
|
||||
of_node_put(vio_root);
|
||||
return -ENODEV;
|
||||
}
|
||||
arch_initcall(iseries_vio_init);
|
|
@ -56,30 +56,6 @@
|
|||
#define VIOCD_KERN_WARNING KERN_WARNING "viocd: "
|
||||
#define VIOCD_KERN_INFO KERN_INFO "viocd: "
|
||||
|
||||
struct viocdlpevent {
|
||||
struct HvLpEvent event;
|
||||
u32 reserved;
|
||||
u16 version;
|
||||
u16 sub_result;
|
||||
u16 disk;
|
||||
u16 flags;
|
||||
u32 token;
|
||||
u64 offset; /* On open, max number of disks */
|
||||
u64 len; /* On open, size of the disk */
|
||||
u32 block_size; /* Only set on open */
|
||||
u32 media_size; /* Only set on open */
|
||||
};
|
||||
|
||||
enum viocdsubtype {
|
||||
viocdopen = 0x0001,
|
||||
viocdclose = 0x0002,
|
||||
viocdread = 0x0003,
|
||||
viocdwrite = 0x0004,
|
||||
viocdlockdoor = 0x0005,
|
||||
viocdgetinfo = 0x0006,
|
||||
viocdcheck = 0x0007
|
||||
};
|
||||
|
||||
/*
|
||||
* Should probably make this a module parameter....sigh
|
||||
*/
|
||||
|
@ -131,17 +107,13 @@ static struct capability_entry capability_table[] __initdata = {
|
|||
/* These are our internal structures for keeping track of devices */
|
||||
static int viocd_numdev;
|
||||
|
||||
struct cdrom_info {
|
||||
char rsrcname[10];
|
||||
char type[4];
|
||||
char model[3];
|
||||
};
|
||||
|
||||
struct disk_info {
|
||||
struct gendisk *viocd_disk;
|
||||
struct cdrom_device_info viocd_info;
|
||||
struct device *dev;
|
||||
struct cdrom_info unitinfo;
|
||||
const char *rsrcname;
|
||||
const char *type;
|
||||
const char *model;
|
||||
};
|
||||
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
|
||||
|
||||
|
@ -159,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v)
|
|||
for (i = 0; i < viocd_numdev; i++) {
|
||||
seq_printf(m, "viocd device %d is iSeries resource %10.10s"
|
||||
"type %4.4s, model %3.3s\n",
|
||||
i, viocd_diskinfo[i].unitinfo.rsrcname,
|
||||
viocd_diskinfo[i].unitinfo.type,
|
||||
viocd_diskinfo[i].unitinfo.model);
|
||||
i, viocd_diskinfo[i].rsrcname,
|
||||
viocd_diskinfo[i].type,
|
||||
viocd_diskinfo[i].model);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -211,61 +183,6 @@ struct block_device_operations viocd_fops = {
|
|||
.media_changed = viocd_blk_media_changed,
|
||||
};
|
||||
|
||||
/* Get info on CD devices from OS/400 */
|
||||
static void __init get_viocd_info(void)
|
||||
{
|
||||
HvLpEvent_Rc hvrc;
|
||||
int i;
|
||||
struct viocd_waitevent we;
|
||||
struct cdrom_info *viocd_unitinfo;
|
||||
dma_addr_t unitinfo_dmaaddr;
|
||||
|
||||
viocd_unitinfo = iseries_hv_alloc(
|
||||
sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
|
||||
&unitinfo_dmaaddr, GFP_ATOMIC);
|
||||
if (viocd_unitinfo == NULL) {
|
||||
printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
|
||||
|
||||
init_completion(&we.com);
|
||||
|
||||
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
|
||||
HvLpEvent_Type_VirtualIo,
|
||||
viomajorsubtype_cdio | viocdgetinfo,
|
||||
HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
|
||||
viopath_sourceinst(viopath_hostLp),
|
||||
viopath_targetinst(viopath_hostLp),
|
||||
(u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
|
||||
sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
|
||||
if (hvrc != HvLpEvent_Rc_Good) {
|
||||
printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
|
||||
(int)hvrc);
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
wait_for_completion(&we.com);
|
||||
|
||||
if (we.rc) {
|
||||
const struct vio_error_entry *err =
|
||||
vio_lookup_rc(viocd_err_table, we.sub_result);
|
||||
printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
|
||||
we.rc, we.sub_result, err->msg);
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) {
|
||||
viocd_diskinfo[viocd_numdev].unitinfo = viocd_unitinfo[i];
|
||||
viocd_numdev++;
|
||||
}
|
||||
|
||||
error_ret:
|
||||
iseries_hv_free(sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
|
||||
viocd_unitinfo, unitinfo_dmaaddr);
|
||||
}
|
||||
|
||||
static int viocd_open(struct cdrom_device_info *cdi, int purpose)
|
||||
{
|
||||
struct disk_info *diskinfo = cdi->handle;
|
||||
|
@ -576,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event)
|
|||
bevent->block_size / 512);
|
||||
}
|
||||
/* FALLTHROUGH !! */
|
||||
case viocdgetinfo:
|
||||
case viocdlockdoor:
|
||||
pwe = (struct viocd_waitevent *)event->xCorrelationToken;
|
||||
return_complete:
|
||||
|
@ -660,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|||
int deviceno;
|
||||
struct disk_info *d;
|
||||
struct cdrom_device_info *c;
|
||||
struct cdrom_info *ci;
|
||||
struct request_queue *q;
|
||||
struct device_node *node = vdev->dev.archdata.of_node;
|
||||
|
||||
deviceno = vdev->unit_address;
|
||||
if (deviceno >= viocd_numdev)
|
||||
if (deviceno > VIOCD_MAX_CD)
|
||||
return -ENODEV;
|
||||
if (!node)
|
||||
return -ENODEV;
|
||||
|
||||
if (deviceno >= viocd_numdev)
|
||||
viocd_numdev = deviceno + 1;
|
||||
|
||||
d = &viocd_diskinfo[deviceno];
|
||||
d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL);
|
||||
d->type = of_get_property(node, "linux,vio_type", NULL);
|
||||
d->model = of_get_property(node, "linux,vio_model", NULL);
|
||||
|
||||
c = &d->viocd_info;
|
||||
ci = &d->unitinfo;
|
||||
|
||||
c->ops = &viocd_dops;
|
||||
c->speed = 4;
|
||||
c->capacity = 1;
|
||||
c->handle = d;
|
||||
c->mask = ~find_capability(ci->type);
|
||||
c->mask = ~find_capability(d->type);
|
||||
sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno);
|
||||
|
||||
if (register_cdrom(c) != 0) {
|
||||
|
@ -685,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
|||
}
|
||||
printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s "
|
||||
"type %4.4s, model %3.3s\n",
|
||||
c->name, ci->rsrcname, ci->type, ci->model);
|
||||
c->name, d->rsrcname, d->type, d->model);
|
||||
q = blk_init_queue(do_viocd_request, &viocd_reqlock);
|
||||
if (q == NULL) {
|
||||
printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n",
|
||||
|
@ -794,8 +718,6 @@ static int __init viocd_init(void)
|
|||
/* Initialize our request handler */
|
||||
vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event);
|
||||
|
||||
get_viocd_info();
|
||||
|
||||
spin_lock_init(&viocd_reqlock);
|
||||
|
||||
ret = vio_register_driver(&viocd_driver);
|
||||
|
|
|
@ -51,6 +51,30 @@
|
|||
*/
|
||||
#define VIO_MAX_SUBTYPES 8
|
||||
|
||||
struct viocdlpevent {
|
||||
struct HvLpEvent event;
|
||||
u32 reserved;
|
||||
u16 version;
|
||||
u16 sub_result;
|
||||
u16 disk;
|
||||
u16 flags;
|
||||
u32 token;
|
||||
u64 offset; /* On open, max number of disks */
|
||||
u64 len; /* On open, size of the disk */
|
||||
u32 block_size; /* Only set on open */
|
||||
u32 media_size; /* Only set on open */
|
||||
};
|
||||
|
||||
enum viocdsubtype {
|
||||
viocdopen = 0x0001,
|
||||
viocdclose = 0x0002,
|
||||
viocdread = 0x0003,
|
||||
viocdwrite = 0x0004,
|
||||
viocdlockdoor = 0x0005,
|
||||
viocdgetinfo = 0x0006,
|
||||
viocdcheck = 0x0007
|
||||
};
|
||||
|
||||
/*
|
||||
* Each subtype can register a handler to process their events.
|
||||
* The handler must have this interface.
|
||||
|
|
Loading…
Reference in New Issue