/*
* drivers/s390/cio/device.c
* bus driver for ccw devices
* $Revision: 1.131 $
*
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
* Cornelia Huck (cohuck@de.ibm.com)
* Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/workqueue.h>
#include <asm/ccwdev.h>
#include <asm/cio.h>
#include "cio.h"
#include "css.h"
#include "device.h"
#include "ioasm.h"
/******************* bus type handling ***********************/
/* The Linux driver model distinguishes between a bus type and
* the bus itself. Of course we only have one channel
* subsystem driver and one channel system per machine, but
* we still use the abstraction. T.R. says it's a good idea. */
static int
ccw_bus_match (struct device * dev, struct device_driver * drv)
{
struct ccw_device *cdev = to_ccwdev(dev);
struct ccw_driver *cdrv = to_ccwdrv(drv);
const struct ccw_device_id *ids = cdrv->ids, *found;
if (!ids)
return 0;
found = ccw_device_id_match(ids, &cdev->id);
if (!found)
return 0;
cdev->id.driver_info = found->driver_info;
return 1;
}
/*
* Hotplugging interface for ccw devices.
* Heavily modeled on pci and usb hotplug.
*/
static int
ccw_hotplug (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct ccw_device *cdev = to_ccwdev(dev);
int i = 0;
int length = 0;
if (!cdev)
return -ENODEV;
/* what we want to pass to /sbin/hotplug */
envp[i++] = buffer;
length += scnprintf(buffer, buffer_size - length, "CU_TYPE=%04X",
cdev->id.cu_type);
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
++length;
buffer += length;
envp[i++] = buffer;
length += scnprintf(buffer, buffer_size - length, "CU_MODEL=%02X",
cdev->id.cu_model);
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
++length;
buffer += length;
/* The next two can be zero, that's ok for us */
envp[i++] = buffer;
length += scnprintf(buffer, buffer_size - length, "DEV_TYPE=%04X",
cdev->id.dev_type);
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
++length;
buffer += length;
envp[i++] = buffer;
length += scnprintf(buffer, buffer_size - length, "DEV_MODEL=%02X",
cdev->id.dev_model);
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
envp[i] = 0;
return 0;
}
struct bus_type ccw_bus_type = {
.name = "ccw",
.match = &ccw_bus_match,
.hotplug = &ccw_hotplug,
};
static int io_subchannel_probe (struct device *)