diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2007-10-11 00:58:31 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-10-11 06:40:47 -0400 |
commit | 7465ce0db310d2fa29f721da7e3aacd1dad7090f (patch) | |
tree | ce8cd473877948310b2e86f685ab09686b79ea23 | |
parent | b833b481c10cf591b15cc674948cc514e55d3b94 (diff) |
[POWERPC] iSeries: Move detection of virtual tapes
Now we will only have entries in the device tree for the actual existing
devices (including their OS/400 properties). This way viotape.c gets
all the information about the devices from the device tree.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/platforms/iseries/dt.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/vio.c | 149 | ||||
-rw-r--r-- | drivers/char/viotape.c | 124 | ||||
-rw-r--r-- | include/asm-powerpc/iseries/vio.h | 41 |
4 files changed, 192 insertions, 129 deletions
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 84fcee15eb25..2e4ad6b34506 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c | |||
@@ -73,7 +73,6 @@ static char __initdata device_type_memory[] = "memory"; | |||
73 | static char __initdata device_type_serial[] = "serial"; | 73 | static char __initdata device_type_serial[] = "serial"; |
74 | static char __initdata device_type_network[] = "network"; | 74 | static char __initdata device_type_network[] = "network"; |
75 | static char __initdata device_type_block[] = "block"; | 75 | static char __initdata device_type_block[] = "block"; |
76 | static char __initdata device_type_byte[] = "byte"; | ||
77 | static char __initdata device_type_pci[] = "pci"; | 76 | static char __initdata device_type_pci[] = "pci"; |
78 | static char __initdata device_type_vdevice[] = "vdevice"; | 77 | static char __initdata device_type_vdevice[] = "vdevice"; |
79 | static char __initdata device_type_vscsi[] = "vscsi"; | 78 | static char __initdata device_type_vscsi[] = "vscsi"; |
@@ -380,12 +379,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt) | |||
380 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) | 379 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) |
381 | dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, | 380 | dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, |
382 | "IBM,iSeries-viodasd", 1); | 381 | "IBM,iSeries-viodasd", 1); |
383 | reg += HVMAXARCHITECTEDVIRTUALDISKS; | ||
384 | reg += HVMAXARCHITECTEDVIRTUALCDROMS; | ||
385 | |||
386 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) | ||
387 | dt_do_vdevice(dt, "viotape", reg, i, device_type_byte, | ||
388 | "IBM,iSeries-viotape", 1); | ||
389 | 382 | ||
390 | dt_end_node(dt); | 383 | dt_end_node(dt); |
391 | } | 384 | } |
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index f61a97441c3d..a4cc990a26a0 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c | |||
@@ -45,6 +45,18 @@ | |||
45 | #define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS) | 45 | #define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS) |
46 | #define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES | 46 | #define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES |
47 | 47 | ||
48 | struct vio_waitevent { | ||
49 | struct completion com; | ||
50 | int rc; | ||
51 | u16 sub_result; | ||
52 | }; | ||
53 | |||
54 | struct vio_resource { | ||
55 | char rsrcname[10]; | ||
56 | char type[4]; | ||
57 | char model[3]; | ||
58 | }; | ||
59 | |||
48 | static struct property * __init new_property(const char *name, int length, | 60 | static struct property * __init new_property(const char *name, int length, |
49 | const void *value) | 61 | const void *value) |
50 | { | 62 | { |
@@ -123,22 +135,10 @@ static int __init add_raw_property(struct device_node *np, const char *name, | |||
123 | return 1; | 135 | return 1; |
124 | } | 136 | } |
125 | 137 | ||
126 | struct viocd_waitevent { | ||
127 | struct completion com; | ||
128 | int rc; | ||
129 | u16 sub_result; | ||
130 | }; | ||
131 | |||
132 | struct cdrom_info { | ||
133 | char rsrcname[10]; | ||
134 | char type[4]; | ||
135 | char model[3]; | ||
136 | }; | ||
137 | |||
138 | static void __init handle_cd_event(struct HvLpEvent *event) | 138 | static void __init handle_cd_event(struct HvLpEvent *event) |
139 | { | 139 | { |
140 | struct viocdlpevent *bevent; | 140 | struct viocdlpevent *bevent; |
141 | struct viocd_waitevent *pwe; | 141 | struct vio_waitevent *pwe; |
142 | 142 | ||
143 | if (!event) | 143 | if (!event) |
144 | /* Notification that a partition went away! */ | 144 | /* Notification that a partition went away! */ |
@@ -158,7 +158,7 @@ static void __init handle_cd_event(struct HvLpEvent *event) | |||
158 | 158 | ||
159 | switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { | 159 | switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { |
160 | case viocdgetinfo: | 160 | case viocdgetinfo: |
161 | pwe = (struct viocd_waitevent *)event->xCorrelationToken; | 161 | pwe = (struct vio_waitevent *)event->xCorrelationToken; |
162 | pwe->rc = event->xRc; | 162 | pwe->rc = event->xRc; |
163 | pwe->sub_result = bevent->sub_result; | 163 | pwe->sub_result = bevent->sub_result; |
164 | complete(&pwe->com); | 164 | complete(&pwe->com); |
@@ -179,8 +179,8 @@ static void __init get_viocd_info(struct device_node *vio_root) | |||
179 | { | 179 | { |
180 | HvLpEvent_Rc hvrc; | 180 | HvLpEvent_Rc hvrc; |
181 | u32 unit; | 181 | u32 unit; |
182 | struct viocd_waitevent we; | 182 | struct vio_waitevent we; |
183 | struct cdrom_info *unitinfo; | 183 | struct vio_resource *unitinfo; |
184 | dma_addr_t unitinfo_dmaaddr; | 184 | dma_addr_t unitinfo_dmaaddr; |
185 | int ret; | 185 | int ret; |
186 | 186 | ||
@@ -286,6 +286,122 @@ static void __init get_viocd_info(struct device_node *vio_root) | |||
286 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2); | 286 | viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2); |
287 | } | 287 | } |
288 | 288 | ||
289 | /* Handle interrupt events for tape */ | ||
290 | static void __init handle_tape_event(struct HvLpEvent *event) | ||
291 | { | ||
292 | struct vio_waitevent *we; | ||
293 | struct viotapelpevent *tevent = (struct viotapelpevent *)event; | ||
294 | |||
295 | if (event == NULL) | ||
296 | /* Notification that a partition went away! */ | ||
297 | return; | ||
298 | |||
299 | we = (struct vio_waitevent *)event->xCorrelationToken; | ||
300 | switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { | ||
301 | case viotapegetinfo: | ||
302 | we->rc = tevent->sub_type_result; | ||
303 | complete(&we->com); | ||
304 | break; | ||
305 | default: | ||
306 | printk(KERN_WARNING "handle_tape_event: weird ack\n"); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void __init get_viotape_info(struct device_node *vio_root) | ||
311 | { | ||
312 | HvLpEvent_Rc hvrc; | ||
313 | u32 unit; | ||
314 | struct vio_resource *unitinfo; | ||
315 | dma_addr_t unitinfo_dmaaddr; | ||
316 | size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES; | ||
317 | struct vio_waitevent we; | ||
318 | int ret; | ||
319 | |||
320 | ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2); | ||
321 | if (ret) { | ||
322 | printk(KERN_WARNING "get_viotape_info: " | ||
323 | "error on viopath_open to hostlp %d\n", ret); | ||
324 | return; | ||
325 | } | ||
326 | |||
327 | vio_setHandler(viomajorsubtype_tape, handle_tape_event); | ||
328 | |||
329 | unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC); | ||
330 | if (!unitinfo) | ||
331 | goto clear_handler; | ||
332 | |||
333 | memset(unitinfo, 0, len); | ||
334 | |||
335 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
336 | HvLpEvent_Type_VirtualIo, | ||
337 | viomajorsubtype_tape | viotapegetinfo, | ||
338 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
339 | viopath_sourceinst(viopath_hostLp), | ||
340 | viopath_targetinst(viopath_hostLp), | ||
341 | (u64)(unsigned long)&we, VIOVERSION << 16, | ||
342 | unitinfo_dmaaddr, len, 0, 0); | ||
343 | if (hvrc != HvLpEvent_Rc_Good) { | ||
344 | printk(KERN_WARNING "get_viotape_info: hv error on op %d\n", | ||
345 | (int)hvrc); | ||
346 | goto hv_free; | ||
347 | } | ||
348 | |||
349 | wait_for_completion(&we.com); | ||
350 | |||
351 | for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) && | ||
352 | unitinfo[unit].rsrcname[0]; unit++) { | ||
353 | struct device_node *np; | ||
354 | char name[64]; | ||
355 | u32 reg = FIRST_VIOTAPE + unit; | ||
356 | |||
357 | snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg); | ||
358 | np = new_node(name, vio_root); | ||
359 | if (!np) | ||
360 | goto hv_free; | ||
361 | if (!add_string_property(np, "name", "viotape") || | ||
362 | !add_string_property(np, "device_type", "byte") || | ||
363 | !add_string_property(np, "compatible", | ||
364 | "IBM,iSeries-viotape") || | ||
365 | !add_raw_property(np, "reg", sizeof(reg), ®) || | ||
366 | !add_raw_property(np, "linux,unit_address", | ||
367 | sizeof(unit), &unit) || | ||
368 | !add_raw_property(np, "linux,vio_rsrcname", | ||
369 | sizeof(unitinfo[unit].rsrcname), | ||
370 | unitinfo[unit].rsrcname) || | ||
371 | !add_raw_property(np, "linux,vio_type", | ||
372 | sizeof(unitinfo[unit].type), | ||
373 | unitinfo[unit].type) || | ||
374 | !add_raw_property(np, "linux,vio_model", | ||
375 | sizeof(unitinfo[unit].model), | ||
376 | unitinfo[unit].model)) | ||
377 | goto node_free; | ||
378 | np->name = of_get_property(np, "name", NULL); | ||
379 | np->type = of_get_property(np, "device_type", NULL); | ||
380 | of_attach_node(np); | ||
381 | #ifdef CONFIG_PROC_DEVICETREE | ||
382 | if (vio_root->pde) { | ||
383 | struct proc_dir_entry *ent; | ||
384 | |||
385 | ent = proc_mkdir(strrchr(np->full_name, '/') + 1, | ||
386 | vio_root->pde); | ||
387 | if (ent) | ||
388 | proc_device_tree_add_node(np, ent); | ||
389 | } | ||
390 | #endif | ||
391 | continue; | ||
392 | |||
393 | node_free: | ||
394 | free_node(np); | ||
395 | break; | ||
396 | } | ||
397 | |||
398 | hv_free: | ||
399 | iseries_hv_free(len, unitinfo, unitinfo_dmaaddr); | ||
400 | clear_handler: | ||
401 | vio_clearHandler(viomajorsubtype_tape); | ||
402 | viopath_close(viopath_hostLp, viomajorsubtype_tape, 2); | ||
403 | } | ||
404 | |||
289 | static int __init iseries_vio_init(void) | 405 | static int __init iseries_vio_init(void) |
290 | { | 406 | { |
291 | struct device_node *vio_root; | 407 | struct device_node *vio_root; |
@@ -307,6 +423,7 @@ static int __init iseries_vio_init(void) | |||
307 | } | 423 | } |
308 | 424 | ||
309 | get_viocd_info(vio_root); | 425 | get_viocd_info(vio_root); |
426 | get_viotape_info(vio_root); | ||
310 | 427 | ||
311 | return 0; | 428 | return 0; |
312 | 429 | ||
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 064c09195215..f1d60f0cef8f 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
@@ -92,47 +92,6 @@ struct viot_devinfo_struct { | |||
92 | #define VIOTAPOP_SETPART 14 | 92 | #define VIOTAPOP_SETPART 14 |
93 | #define VIOTAPOP_UNLOAD 15 | 93 | #define VIOTAPOP_UNLOAD 15 |
94 | 94 | ||
95 | struct viotapelpevent { | ||
96 | struct HvLpEvent event; | ||
97 | u32 reserved; | ||
98 | u16 version; | ||
99 | u16 sub_type_result; | ||
100 | u16 tape; | ||
101 | u16 flags; | ||
102 | u32 token; | ||
103 | u64 len; | ||
104 | union { | ||
105 | struct { | ||
106 | u32 tape_op; | ||
107 | u32 count; | ||
108 | } op; | ||
109 | struct { | ||
110 | u32 type; | ||
111 | u32 resid; | ||
112 | u32 dsreg; | ||
113 | u32 gstat; | ||
114 | u32 erreg; | ||
115 | u32 file_no; | ||
116 | u32 block_no; | ||
117 | } get_status; | ||
118 | struct { | ||
119 | u32 block_no; | ||
120 | } get_pos; | ||
121 | } u; | ||
122 | }; | ||
123 | |||
124 | enum viotapesubtype { | ||
125 | viotapeopen = 0x0001, | ||
126 | viotapeclose = 0x0002, | ||
127 | viotaperead = 0x0003, | ||
128 | viotapewrite = 0x0004, | ||
129 | viotapegetinfo = 0x0005, | ||
130 | viotapeop = 0x0006, | ||
131 | viotapegetpos = 0x0007, | ||
132 | viotapesetpos = 0x0008, | ||
133 | viotapegetstatus = 0x0009 | ||
134 | }; | ||
135 | |||
136 | enum viotaperc { | 95 | enum viotaperc { |
137 | viotape_InvalidRange = 0x0601, | 96 | viotape_InvalidRange = 0x0601, |
138 | viotape_InvalidToken = 0x0602, | 97 | viotape_InvalidToken = 0x0602, |
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = { | |||
223 | #define VIOT_WRITING 2 | 182 | #define VIOT_WRITING 2 |
224 | 183 | ||
225 | /* Our info on the tapes */ | 184 | /* Our info on the tapes */ |
226 | struct tape_descr { | 185 | static struct { |
227 | char rsrcname[10]; | 186 | const char *rsrcname; |
228 | char type[4]; | 187 | const char *type; |
229 | char model[3]; | 188 | const char *model; |
230 | }; | 189 | } viotape_unitinfo[VIOTAPE_MAX_TAPE]; |
231 | |||
232 | static struct tape_descr *viotape_unitinfo; | ||
233 | static dma_addr_t viotape_unitinfo_token; | ||
234 | 190 | ||
235 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; | 191 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; |
236 | 192 | ||
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno) | |||
381 | return -err->errno; | 337 | return -err->errno; |
382 | } | 338 | } |
383 | 339 | ||
384 | /* Get info on all tapes from OS/400 */ | ||
385 | static int get_viotape_info(void) | ||
386 | { | ||
387 | HvLpEvent_Rc hvrc; | ||
388 | int i; | ||
389 | size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE; | ||
390 | struct op_struct *op = get_op_struct(); | ||
391 | |||
392 | if (op == NULL) | ||
393 | return -ENOMEM; | ||
394 | |||
395 | viotape_unitinfo = iseries_hv_alloc(len, &viotape_unitinfo_token, | ||
396 | GFP_ATOMIC); | ||
397 | if (viotape_unitinfo == NULL) { | ||
398 | free_op_struct(op); | ||
399 | return -ENOMEM; | ||
400 | } | ||
401 | |||
402 | memset(viotape_unitinfo, 0, len); | ||
403 | |||
404 | hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, | ||
405 | HvLpEvent_Type_VirtualIo, | ||
406 | viomajorsubtype_tape | viotapegetinfo, | ||
407 | HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, | ||
408 | viopath_sourceinst(viopath_hostLp), | ||
409 | viopath_targetinst(viopath_hostLp), | ||
410 | (u64) (unsigned long) op, VIOVERSION << 16, | ||
411 | viotape_unitinfo_token, len, 0, 0); | ||
412 | if (hvrc != HvLpEvent_Rc_Good) { | ||
413 | printk(VIOTAPE_KERN_WARN "hv error on op %d\n", | ||
414 | (int)hvrc); | ||
415 | free_op_struct(op); | ||
416 | return -EIO; | ||
417 | } | ||
418 | |||
419 | wait_for_completion(&op->com); | ||
420 | |||
421 | free_op_struct(op); | ||
422 | |||
423 | for (i = 0; | ||
424 | ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0])); | ||
425 | i++) | ||
426 | viotape_numdev++; | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | |||
431 | /* Write */ | 340 | /* Write */ |
432 | static ssize_t viotap_write(struct file *file, const char *buf, | 341 | static ssize_t viotap_write(struct file *file, const char *buf, |
433 | size_t count, loff_t * ppos) | 342 | size_t count, loff_t * ppos) |
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event) | |||
899 | tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; | 808 | tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; |
900 | op = (struct op_struct *)event->xCorrelationToken; | 809 | op = (struct op_struct *)event->xCorrelationToken; |
901 | switch (tapeminor) { | 810 | switch (tapeminor) { |
902 | case viotapegetinfo: | ||
903 | case viotapeopen: | 811 | case viotapeopen: |
904 | case viotapeclose: | 812 | case viotapeclose: |
905 | op->rc = tevent->sub_type_result; | 813 | op->rc = tevent->sub_type_result; |
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
942 | { | 850 | { |
943 | int i = vdev->unit_address; | 851 | int i = vdev->unit_address; |
944 | int j; | 852 | int j; |
853 | struct device_node *node = vdev->dev.archdata.of_node; | ||
945 | 854 | ||
946 | if (i >= viotape_numdev) | 855 | if (i > VIOTAPE_MAX_TAPE) |
856 | return -ENODEV; | ||
857 | if (!node) | ||
947 | return -ENODEV; | 858 | return -ENODEV; |
948 | 859 | ||
860 | if (i >= viotape_numdev) | ||
861 | viotape_numdev = i + 1; | ||
862 | |||
949 | tape_device[i] = &vdev->dev; | 863 | tape_device[i] = &vdev->dev; |
864 | viotape_unitinfo[i].rsrcname = of_get_property(node, | ||
865 | "linux,vio_rsrcname", NULL); | ||
866 | viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type", | ||
867 | NULL); | ||
868 | viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model", | ||
869 | NULL); | ||
950 | 870 | ||
951 | state[i].cur_part = 0; | 871 | state[i].cur_part = 0; |
952 | for (j = 0; j < MAX_PARTITIONS; ++j) | 872 | for (j = 0; j < MAX_PARTITIONS; ++j) |
@@ -1044,11 +964,6 @@ int __init viotap_init(void) | |||
1044 | goto unreg_chrdev; | 964 | goto unreg_chrdev; |
1045 | } | 965 | } |
1046 | 966 | ||
1047 | if ((ret = get_viotape_info()) < 0) { | ||
1048 | printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information"); | ||
1049 | goto unreg_class; | ||
1050 | } | ||
1051 | |||
1052 | ret = vio_register_driver(&viotape_driver); | 967 | ret = vio_register_driver(&viotape_driver); |
1053 | if (ret) | 968 | if (ret) |
1054 | goto unreg_class; | 969 | goto unreg_class; |
@@ -1102,9 +1017,6 @@ static void __exit viotap_exit(void) | |||
1102 | vio_unregister_driver(&viotape_driver); | 1017 | vio_unregister_driver(&viotape_driver); |
1103 | class_destroy(tape_class); | 1018 | class_destroy(tape_class); |
1104 | unregister_chrdev(VIOTAPE_MAJOR, "viotape"); | 1019 | unregister_chrdev(VIOTAPE_MAJOR, "viotape"); |
1105 | if (viotape_unitinfo) | ||
1106 | iseries_hv_free(sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE, | ||
1107 | viotape_unitinfo, viotape_unitinfo_token); | ||
1108 | viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2); | 1020 | viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2); |
1109 | vio_clearHandler(viomajorsubtype_tape); | 1021 | vio_clearHandler(viomajorsubtype_tape); |
1110 | clear_op_struct_pool(); | 1022 | clear_op_struct_pool(); |
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h index e5a405b8d461..2555dfd6fac6 100644 --- a/include/asm-powerpc/iseries/vio.h +++ b/include/asm-powerpc/iseries/vio.h | |||
@@ -75,6 +75,47 @@ enum viocdsubtype { | |||
75 | viocdcheck = 0x0007 | 75 | viocdcheck = 0x0007 |
76 | }; | 76 | }; |
77 | 77 | ||
78 | struct viotapelpevent { | ||
79 | struct HvLpEvent event; | ||
80 | u32 reserved; | ||
81 | u16 version; | ||
82 | u16 sub_type_result; | ||
83 | u16 tape; | ||
84 | u16 flags; | ||
85 | u32 token; | ||
86 | u64 len; | ||
87 | union { | ||
88 | struct { | ||
89 | u32 tape_op; | ||
90 | u32 count; | ||
91 | } op; | ||
92 | struct { | ||
93 | u32 type; | ||
94 | u32 resid; | ||
95 | u32 dsreg; | ||
96 | u32 gstat; | ||
97 | u32 erreg; | ||
98 | u32 file_no; | ||
99 | u32 block_no; | ||
100 | } get_status; | ||
101 | struct { | ||
102 | u32 block_no; | ||
103 | } get_pos; | ||
104 | } u; | ||
105 | }; | ||
106 | |||
107 | enum viotapesubtype { | ||
108 | viotapeopen = 0x0001, | ||
109 | viotapeclose = 0x0002, | ||
110 | viotaperead = 0x0003, | ||
111 | viotapewrite = 0x0004, | ||
112 | viotapegetinfo = 0x0005, | ||
113 | viotapeop = 0x0006, | ||
114 | viotapegetpos = 0x0007, | ||
115 | viotapesetpos = 0x0008, | ||
116 | viotapegetstatus = 0x0009 | ||
117 | }; | ||
118 | |||
78 | /* | 119 | /* |
79 | * Each subtype can register a handler to process their events. | 120 | * Each subtype can register a handler to process their events. |
80 | * The handler must have this interface. | 121 | * The handler must have this interface. |