diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 00:55:47 -0400 |
commit | e86908614f2c7fec401827e5cefd7a6ea9407f85 (patch) | |
tree | fcb5d9e52422b37bdaf0e647126ebdfc1680f162 /drivers/cdrom/viocd.c | |
parent | 547307420931344a868275bd7ea7a30f117a15a9 (diff) | |
parent | 9b4b8feb962f4b3e74768b7205f1f8f6cce87238 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits)
[POWERPC] Add memchr() to the bootwrapper
[POWERPC] Implement logging of unhandled signals
[POWERPC] Add legacy serial support for OPB with flattened device tree
[POWERPC] Use 1TB segments
[POWERPC] XilinxFB: Allow fixed framebuffer base address
[POWERPC] XilinxFB: Add support for custom screen resolution
[POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters
[POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci
[POWERPC] 4xx: Kilauea defconfig file
[POWERPC] 4xx: Kilauea DTS
[POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x
[POWERPC] 4xx: Add AMCC 405EX support to cputable.c
[POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable
[POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers
[POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig
[POWERPC] 85xx: Killed <asm/mpc85xx.h>
[POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS
[POWERPC] 85xx: Convert mpc8560ads to the new CPM binding.
[POWERPC] mpc8272ads: Remove muram from the CPM reg property.
[POWERPC] Make clockevents work on PPC601 processors
...
Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
Diffstat (limited to 'drivers/cdrom/viocd.c')
-rw-r--r-- | drivers/cdrom/viocd.c | 128 |
1 files changed, 19 insertions, 109 deletions
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index e51550db1575..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,22 +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 | * This needs to be allocated since it is passed to the | ||
141 | * Hypervisor and we may be a module. | ||
142 | */ | ||
143 | static struct cdrom_info *viocd_unitinfo; | ||
144 | static dma_addr_t unitinfo_dmaaddr; | ||
145 | |||
146 | struct disk_info { | 110 | struct disk_info { |
147 | struct gendisk *viocd_disk; | 111 | struct gendisk *viocd_disk; |
148 | struct cdrom_device_info viocd_info; | 112 | struct cdrom_device_info viocd_info; |
149 | struct device *dev; | 113 | struct device *dev; |
114 | const char *rsrcname; | ||
115 | const char *type; | ||
116 | const char *model; | ||
150 | }; | 117 | }; |
151 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; | 118 | static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; |
152 | 119 | ||
@@ -164,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v) | |||
164 | for (i = 0; i < viocd_numdev; i++) { | 131 | for (i = 0; i < viocd_numdev; i++) { |
165 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" | 132 | seq_printf(m, "viocd device %d is iSeries resource %10.10s" |
166 | "type %4.4s, model %3.3s\n", | 133 | "type %4.4s, model %3.3s\n", |
167 | i, viocd_unitinfo[i].rsrcname, | 134 | i, viocd_diskinfo[i].rsrcname, |
168 | viocd_unitinfo[i].type, | 135 | viocd_diskinfo[i].type, |
169 | viocd_unitinfo[i].model); | 136 | viocd_diskinfo[i].model); |
170 | } | 137 | } |
171 | return 0; | 138 | return 0; |
172 | } | 139 | } |
@@ -216,61 +183,6 @@ struct block_device_operations viocd_fops = { | |||
216 | .media_changed = viocd_blk_media_changed, | 183 | .media_changed = viocd_blk_media_changed, |
217 | }; | 184 | }; |
218 | 185 | ||
219 | /* Get info on CD devices from OS/400 */ | ||
220 | static void __init get_viocd_info(void) | ||
221 | { | ||
222 | HvLpEvent_Rc hvrc; | ||
223 | int i; | ||
224 | struct viocd_waitevent we; | ||
225 | |||
226 | viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev, | ||
227 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
228 | &unitinfo_dmaaddr, GFP_ATOMIC); | ||
229 | if (viocd_unitinfo == NULL) { | ||
230 | printk(VIOCD_KERN_WARNING "error allocating unitinfo\n"); | ||
231 | return; | ||
232 | } | ||
233 | |||
234 | memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD); | ||
235 | |||
236 | init_completion(&we.com); | ||
237 | |||
238 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
239 | HvLpEvent_Type_VirtualIo, | ||
240 | viomajorsubtype_cdio | viocdgetinfo, | ||
241 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
242 | viopath_sourceinst(viopath_hostLp), | ||
243 | viopath_targetinst(viopath_hostLp), | ||
244 | (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0, | ||
245 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0); | ||
246 | if (hvrc != HvLpEvent_Rc_Good) { | ||
247 | printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n", | ||
248 | (int)hvrc); | ||
249 | goto error_ret; | ||
250 | } | ||
251 | |||
252 | wait_for_completion(&we.com); | ||
253 | |||
254 | if (we.rc) { | ||
255 | const struct vio_error_entry *err = | ||
256 | vio_lookup_rc(viocd_err_table, we.sub_result); | ||
257 | printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n", | ||
258 | we.rc, we.sub_result, err->msg); | ||
259 | goto error_ret; | ||
260 | } | ||
261 | |||
262 | for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) | ||
263 | viocd_numdev++; | ||
264 | |||
265 | error_ret: | ||
266 | if (viocd_numdev == 0) { | ||
267 | dma_free_coherent(iSeries_vio_dev, | ||
268 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
269 | viocd_unitinfo, unitinfo_dmaaddr); | ||
270 | viocd_unitinfo = NULL; | ||
271 | } | ||
272 | } | ||
273 | |||
274 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) | 186 | static int viocd_open(struct cdrom_device_info *cdi, int purpose) |
275 | { | 187 | { |
276 | struct disk_info *diskinfo = cdi->handle; | 188 | struct disk_info *diskinfo = cdi->handle; |
@@ -581,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event) | |||
581 | bevent->block_size / 512); | 493 | bevent->block_size / 512); |
582 | } | 494 | } |
583 | /* FALLTHROUGH !! */ | 495 | /* FALLTHROUGH !! */ |
584 | case viocdgetinfo: | ||
585 | case viocdlockdoor: | 496 | case viocdlockdoor: |
586 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; | 497 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; |
587 | return_complete: | 498 | return_complete: |
@@ -665,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
665 | int deviceno; | 576 | int deviceno; |
666 | struct disk_info *d; | 577 | struct disk_info *d; |
667 | struct cdrom_device_info *c; | 578 | struct cdrom_device_info *c; |
668 | struct cdrom_info *ci; | ||
669 | struct request_queue *q; | 579 | struct request_queue *q; |
580 | struct device_node *node = vdev->dev.archdata.of_node; | ||
670 | 581 | ||
671 | deviceno = vdev->unit_address; | 582 | deviceno = vdev->unit_address; |
672 | if (deviceno >= viocd_numdev) | 583 | if (deviceno > VIOCD_MAX_CD) |
673 | return -ENODEV; | 584 | return -ENODEV; |
585 | if (!node) | ||
586 | return -ENODEV; | ||
587 | |||
588 | if (deviceno >= viocd_numdev) | ||
589 | viocd_numdev = deviceno + 1; | ||
674 | 590 | ||
675 | 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 | |||
676 | c = &d->viocd_info; | 596 | c = &d->viocd_info; |
677 | ci = &viocd_unitinfo[deviceno]; | ||
678 | 597 | ||
679 | c->ops = &viocd_dops; | 598 | c->ops = &viocd_dops; |
680 | c->speed = 4; | 599 | c->speed = 4; |
681 | c->capacity = 1; | 600 | c->capacity = 1; |
682 | c->handle = d; | 601 | c->handle = d; |
683 | c->mask = ~find_capability(ci->type); | 602 | c->mask = ~find_capability(d->type); |
684 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); | 603 | sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); |
685 | 604 | ||
686 | if (register_cdrom(c) != 0) { | 605 | if (register_cdrom(c) != 0) { |
@@ -690,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
690 | } | 609 | } |
691 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " | 610 | printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " |
692 | "type %4.4s, model %3.3s\n", | 611 | "type %4.4s, model %3.3s\n", |
693 | c->name, ci->rsrcname, ci->type, ci->model); | 612 | c->name, d->rsrcname, d->type, d->model); |
694 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); | 613 | q = blk_init_queue(do_viocd_request, &viocd_reqlock); |
695 | if (q == NULL) { | 614 | if (q == NULL) { |
696 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", | 615 | printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n", |
@@ -799,8 +718,6 @@ static int __init viocd_init(void) | |||
799 | /* Initialize our request handler */ | 718 | /* Initialize our request handler */ |
800 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); | 719 | vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); |
801 | 720 | ||
802 | get_viocd_info(); | ||
803 | |||
804 | spin_lock_init(&viocd_reqlock); | 721 | spin_lock_init(&viocd_reqlock); |
805 | 722 | ||
806 | ret = vio_register_driver(&viocd_driver); | 723 | ret = vio_register_driver(&viocd_driver); |
@@ -816,9 +733,6 @@ static int __init viocd_init(void) | |||
816 | return 0; | 733 | return 0; |
817 | 734 | ||
818 | out_free_info: | 735 | out_free_info: |
819 | dma_free_coherent(iSeries_vio_dev, | ||
820 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
821 | viocd_unitinfo, unitinfo_dmaaddr); | ||
822 | vio_clearHandler(viomajorsubtype_cdio); | 736 | vio_clearHandler(viomajorsubtype_cdio); |
823 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); | 737 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); |
824 | out_unregister: | 738 | out_unregister: |
@@ -830,10 +744,6 @@ static void __exit viocd_exit(void) | |||
830 | { | 744 | { |
831 | remove_proc_entry("iSeries/viocd", NULL); | 745 | remove_proc_entry("iSeries/viocd", NULL); |
832 | vio_unregister_driver(&viocd_driver); | 746 | vio_unregister_driver(&viocd_driver); |
833 | if (viocd_unitinfo != NULL) | ||
834 | dma_free_coherent(iSeries_vio_dev, | ||
835 | sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, | ||
836 | viocd_unitinfo, unitinfo_dmaaddr); | ||
837 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); | 747 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); |
838 | vio_clearHandler(viomajorsubtype_cdio); | 748 | vio_clearHandler(viomajorsubtype_cdio); |
839 | unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); | 749 | unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); |