+static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+{
+ char tapename[32];
+ int i = vdev->unit_address;
+ int j;
+
+ if (i >= viotape_numdev)
+ return -ENODEV;
+
+ tape_device[i] = &vdev->dev;
+
+ state[i].cur_part = 0;
+ for (j = 0; j < MAX_PARTITIONS; ++j)
+ state[i].part_stat_rwi[j] = VIOT_IDLE;
+ class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+ "iseries!vt%d", i);
+ class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ NULL, "iseries!nvt%d", i);
+ devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
+ "iseries/vt%d", i);
+ devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ S_IFCHR | S_IRUSR | S_IWUSR, "iseries/nvt%d", i);
+ sprintf(tapename, "iseries/vt%d", i);
+ state[i].dev_handle = devfs_register_tape(tapename);
+ printk(VIOTAPE_KERN_INFO "tape %s is iSeries "
+ "resource %10.10s type %4.4s, model %3.3s\n",
+ tapename, viotape_unitinfo[i].rsrcname,
+ viotape_unitinfo[i].type, viotape_unitinfo[i].model);
+ return 0;
+}
+
+static int viotape_remove(struct vio_dev *vdev)
+{
+ int i = vdev->unit_address;
+
+ devfs_remove("iseries/nvt%d", i);
+ devfs_remove("iseries/vt%d", i);
+ devfs_unregister_tape(state[i].dev_handle);
+ class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80));
+ class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i));
+ return 0;
+}
+
+/**
+ * viotape_device_table: Used by vio.c to match devices that we
+ * support.
+ */
+static struct vio_device_id viotape_device_table[] __devinitdata = {
+ { "viotape", "" },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(vio, viotape_device_table);
+static struct vio_driver viotape_driver = {
+ .name = "viotape",
+ .id_table = viotape_device_table,
+ .probe = viotape_probe,
+ .remove = viotape_remove
+};
+