diff options
Diffstat (limited to 'drivers/cdrom/viocd.c')
-rw-r--r-- | drivers/cdrom/viocd.c | 116 |
1 files changed, 19 insertions, 97 deletions
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index c081e5400ce0..880b5dce3a62 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c | |||
@@ -56,30 +56,6 @@ | |||
56 | #define VIOCD_KERN_WARNING KERN_WARNING "viocd: " | 56 | #define VIOCD_KERN_WARNING KERN_WARNING "viocd: " |
57 | #define VIOCD_KERN_INFO KERN_INFO "viocd: " | 57 | #define VIOCD_KERN_INFO KERN_INFO "viocd: " |
58 | 58 | ||
59 | struct viocdlpevent { | ||
60 | struct HvLpEvent event; | ||
61 | u32 reserved; | ||
62 | u16 version; | ||
63 | u16 sub_result; | ||
64 | u16 disk; | ||
65 | u16 flags; | ||
66 | u32 token; | ||
67 | u64 offset; /* On open, max number of disks */ | ||
68 | u64 len; /* On open, size of the disk */ | ||
69 | u32 block_size; /* Only set on open */ | ||
70 | u32 media_size; /* Only set on open */ | ||
71 | }; | ||
72 | |||
73 | enum viocdsubtype { | ||
74 | viocdopen = 0x0001, | ||
75 | viocdclose = 0x0002, | ||
76 | viocdread = 0x0003, | ||
77 | viocdwrite = 0x0004, | ||
78 | viocdlockdoor = 0x0005, | ||
79 | viocdgetinfo = 0x0006, | ||
80 | viocdcheck = 0x0007 | ||
81 | }; | ||
82 | |||
83 | /* | 59 | /* |
84 | * Should probably make this a module parameter....sigh | 60 | * Should probably make this a module parameter....sigh |
85 | */ | 61 | */ |
@@ -131,17 +107,13 @@ static struct capability_entry capability_table[] __initdata = { | |||
131 | /* These are our internal structures for keeping track of devices */ | 107 | /* These are our internal structures for keeping track of devices */ |
132 | static int viocd_numdev; | 108 | static int viocd_numdev; |
133 | 109 | ||
134 | struct cdrom_info { | ||
135 | char rsrcname[10]; | ||
136 | char type[4]; | ||
137 | char model[3]; | ||
138 | }; | ||
139 | |||
140 | struct disk_info { | 110 | struct disk_info { |
141 | struct gendisk *viocd_disk; | 111 | struct gendisk *viocd_disk; |
142 | struct cdrom_device_info viocd_info; | 112 | struct cdrom_device_info viocd_info; |
143 | struct device *dev; | 113 | struct device *dev; |
144 | struct cdrom_info unitinfo; | 114 | const char *rsrcname; |
115 | const char *type; | ||
116 | const char *model; | ||
145 | }; | 117 | }; |
146 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; | 118 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; |
147 | 119 | ||
@@ -159,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v) | |||
159 | for (i = 0; i < viocd_numdev; i++) { | 131 | for (i = 0; i < viocd_numdev; i++) { |
160 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" | 132 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" |
161 | "type %4.4s, model %3.3s\n", | 133 | "type %4.4s, model %3.3s\n", |
162 | i, viocd_diskinfo[i].unitinfo.rsrcname, | 134 | i, viocd_diskinfo[i].rsrcname, |
163 | viocd_diskinfo[i].unitinfo.type, | 135 | viocd_diskinfo[i].type, |
164 | viocd_diskinfo[i].unitinfo.model); | 136 | viocd_diskinfo[i].model); |
165 | } | 137 | } |
166 | return 0; | 138 | return 0; |
167 | } | 139 | } |
@@ -211,61 +183,6 @@ struct block_device_operations viocd_fops = { | |||
211 | .media_changed = viocd_blk_media_changed, | 183 | .media_changed = viocd_blk_media_changed, |
212 | }; | 184 | }; |
213 | 185 | ||
214 | /* Get info on CD devices from OS/400 */ | ||
215 | static void __init get_viocd_info(void) | ||
216 | { | ||
217 | HvLpEvent_Rc hvrc; | ||
218 | int i; | ||
219 | struct viocd_waitevent we; | ||
220 | struct cdrom_info *viocd_unitinfo; | ||
221 | dma_addr_t unitinfo_dmaaddr; | ||
222 | |||
223 | viocd_unitinfo = iseries_hv_alloc( | ||
224 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
225 | &unitinfo_dmaaddr, GFP_ATOMIC); | ||
226 | if (viocd_unitinfo == NULL) { | ||
227 | printk(VIOCD_KERN_WARNING "error allocating unitinfo\n"); | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD); | ||
232 | |||
233 | init_completion(&we.com); | ||
234 | |||
235 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
236 | HvLpEvent_Type_VirtualIo, | ||
237 | viomajorsubtype_cdio | viocdgetinfo, | ||
238 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
239 | viopath_sourceinst(viopath_hostLp), | ||
240 | viopath_targetinst(viopath_hostLp), | ||
241 | (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0, | ||
242 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0); | ||
243 | if (hvrc != HvLpEvent_Rc_Good) { | ||
244 | printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n", | ||
245 | (int)hvrc); | ||
246 | goto error_ret; | ||
247 | } | ||
248 | |||
249 | wait_for_completion(&we.com); | ||
250 | |||
251 | if (we.rc) { | ||
252 | const struct vio_error_entry *err = | ||
253 | vio_lookup_rc(viocd_err_table, we.sub_result); | ||
254 | printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n", | ||
255 | we.rc, we.sub_result, err->msg); | ||
256 | goto error_ret; | ||
257 | } | ||
258 | |||
259 | for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) { | ||
260 | viocd_diskinfo[viocd_numdev].unitinfo = viocd_unitinfo[i]; | ||
261 | viocd_numdev++; | ||
262 | } | ||
263 | |||
264 | error_ret: | ||
265 | iseries_hv_free(sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
266 | viocd_unitinfo, unitinfo_dmaaddr); | ||
267 | } | ||
268 | |||
269 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) | 186 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) |
270 | { | 187 | { |
271 | struct disk_info *diskinfo = cdi->handle; | 188 | struct disk_info *diskinfo = cdi->handle; |
@@ -576,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event) | |||
576 | bevent->block_size / 512); | 493 | bevent->block_size / 512); |
577 | } | 494 | } |
578 | /* FALLTHROUGH !! */ | 495 | /* FALLTHROUGH !! */ |
579 | case viocdgetinfo: | ||
580 | case viocdlockdoor: | 496 | case viocdlockdoor: |
581 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; | 497 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; |
582 | return_complete: | 498 | return_complete: |
@@ -660,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
660 | int deviceno; | 576 | int deviceno; |
661 | struct disk_info *d; | 577 | struct disk_info *d; |
662 | struct cdrom_device_info *c; | 578 | struct cdrom_device_info *c; |
663 | struct cdrom_info *ci; | ||
664 | struct request_queue *q; | 579 | struct request_queue *q; |
580 | struct device_node *node = vdev->dev.archdata.of_node; | ||
665 | 581 | ||
666 | deviceno = vdev->unit_address; | 582 | deviceno = vdev->unit_address; |
667 | if (deviceno >= viocd_numdev) | 583 | if (deviceno > VIOCD_MAX_CD) |
668 | return -ENODEV; | 584 | return -ENODEV; |
585 | if (!node) | ||
586 | return -ENODEV; | ||
587 | |||
588 | if (deviceno >= viocd_numdev) | ||
589 | viocd_numdev = deviceno + 1; | ||
669 | 590 | ||
670 | d = &viocd_diskinfo[deviceno]; | 591 | d = &viocd_diskinfo[deviceno]; |
592 | d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL); | ||
593 | d->type = of_get_property(node, "linux,vio_type", NULL); | ||
594 | d->model = of_get_property(node, "linux,vio_model", NULL); | ||
595 | |||
671 | c = &d->viocd_info; | 596 | c = &d->viocd_info; |
672 | ci = &d->unitinfo; | ||
673 | 597 | ||
674 | c->ops = &viocd_dops; | 598 | c->ops = &viocd_dops; |
675 | c->speed = 4; | 599 | c->speed = 4; |
676 | c->capacity = 1; | 600 | c->capacity = 1; |
677 | c->handle = d; | 601 | c->handle = d; |
678 | c->mask = ~find_capability(ci->type); | 602 | c->mask = ~find_capability(d->type); |
679 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); | 603 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); |
680 | 604 | ||
681 | if (register_cdrom(c) != 0) { | 605 | if (register_cdrom(c) != 0) { |
@@ -685,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
685 | } | 609 | } |
686 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " | 610 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " |
687 | "type %4.4s, model %3.3s\n", | 611 | "type %4.4s, model %3.3s\n", |
688 | c->name, ci->rsrcname, ci->type, ci->model); | 612 | c->name, d->rsrcname, d->type, d->model); |
689 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); | 613 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); |
690 | if (q == NULL) { | 614 | if (q == NULL) { |
691 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", | 615 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", |
@@ -794,8 +718,6 @@ static int __init viocd_init(void) | |||
794 | /* Initialize our request handler */ | 718 | /* Initialize our request handler */ |
795 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); | 719 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); |
796 | 720 | ||
797 | get_viocd_info(); | ||
798 | |||
799 | spin_lock_init(&viocd_reqlock); | 721 | spin_lock_init(&viocd_reqlock); |
800 | 722 | ||
801 | ret = vio_register_driver(&viocd_driver); | 723 | ret = vio_register_driver(&viocd_driver); |