示例#1
0
文件: monreader.c 项目: 274914765/C
/******************************************************************************
 *                              module init/exit                              *
 *****************************************************************************/
static int __init mon_init(void)
{
    int rc;

    if (!MACHINE_IS_VM) {
        P_ERROR("not running under z/VM, driver not loaded\n");
        return -ENODEV;
    }

    /*
     * Register with IUCV and connect to *MONITOR service
     */
    rc = iucv_register(&monreader_iucv_handler, 1);
    if (rc) {
        P_ERROR("failed to register with iucv driver\n");
        return rc;
    }
    P_INFO("open, registered with IUCV\n");

    rc = segment_type(mon_dcss_name);
    if (rc < 0) {
        segment_warning(rc, mon_dcss_name);
        goto out_iucv;
    }
    if (rc != SEG_TYPE_SC) {
        P_ERROR("segment %s has unsupported type, should be SC\n",
            mon_dcss_name);
        rc = -EINVAL;
        goto out_iucv;
    }

    rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
              &mon_dcss_start, &mon_dcss_end);
    if (rc < 0) {
        segment_warning(rc, mon_dcss_name);
        rc = -EINVAL;
        goto out_iucv;
    }
    dcss_mkname(mon_dcss_name, &user_data_connect[8]);

    rc = misc_register(&mon_dev);
    if (rc < 0 ) {
        P_ERROR("misc_register failed, rc = %i\n", rc);
        goto out;
    }
    P_INFO("Loaded segment %s from %p to %p, size = %lu Byte\n",
        mon_dcss_name, (void *) mon_dcss_start, (void *) mon_dcss_end,
        mon_dcss_end - mon_dcss_start + 1);
    return 0;

out:
    segment_unload(mon_dcss_name);
out_iucv:
    iucv_unregister(&monreader_iucv_handler, 1);
    return rc;
}
static int monreader_restore(struct device *dev)
{
	int rc;

	segment_unload(mon_dcss_name);
	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
			  &mon_dcss_start, &mon_dcss_end);
	if (rc < 0) {
		segment_warning(rc, mon_dcss_name);
		panic("fatal monreader resume error: no monitor dcss\n");
	}
	return monreader_thaw(dev);
}
/******************************************************************************
 *                              module init/exit                              *
 *****************************************************************************/
static int __init mon_init(void)
{
	int rc;

	if (!MACHINE_IS_VM) {
		pr_err("The z/VM *MONITOR record device driver cannot be "
		       "loaded without z/VM\n");
		return -ENODEV;
	}

	/*
	 * Register with IUCV and connect to *MONITOR service
	 */
	rc = iucv_register(&monreader_iucv_handler, 1);
	if (rc) {
		pr_err("The z/VM *MONITOR record device driver failed to "
		       "register with IUCV\n");
		return rc;
	}

	rc = driver_register(&monreader_driver);
	if (rc)
		goto out_iucv;
	monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL);
	if (!monreader_device)
		goto out_driver;
	dev_set_name(monreader_device, "monreader-dev");
	monreader_device->bus = &iucv_bus;
	monreader_device->parent = iucv_root;
	monreader_device->driver = &monreader_driver;
	monreader_device->release = (void (*)(struct device *))kfree;
	rc = device_register(monreader_device);
	if (rc) {
		put_device(monreader_device);
		goto out_driver;
	}

	rc = segment_type(mon_dcss_name);
	if (rc < 0) {
		segment_warning(rc, mon_dcss_name);
		goto out_device;
	}
	if (rc != SEG_TYPE_SC) {
		pr_err("The specified *MONITOR DCSS %s does not have the "
		       "required type SC\n", mon_dcss_name);
		rc = -EINVAL;
		goto out_device;
	}

	rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
			  &mon_dcss_start, &mon_dcss_end);
	if (rc < 0) {
		segment_warning(rc, mon_dcss_name);
		rc = -EINVAL;
		goto out_device;
	}
	dcss_mkname(mon_dcss_name, &user_data_connect[8]);

	/*
	 * misc_register() has to be the last action in module_init(), because
	 * file operations will be available right after this.
	 */
	rc = misc_register(&mon_dev);
	if (rc < 0 )
		goto out;
	return 0;

out:
	segment_unload(mon_dcss_name);
out_device:
	device_unregister(monreader_device);
out_driver:
	driver_unregister(&monreader_driver);
out_iucv:
	iucv_unregister(&monreader_iucv_handler, 1);
	return rc;
}