diff options
Diffstat (limited to 'drivers/s390/net/cu3088.c')
-rw-r--r-- | drivers/s390/net/cu3088.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c new file mode 100644 index 000000000000..1b0a9f16024c --- /dev/null +++ b/drivers/s390/net/cu3088.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* | ||
2 | * $Id: cu3088.c,v 1.34 2004/06/15 13:16:27 pavlic Exp $ | ||
3 | * | ||
4 | * CTC / LCS ccw_device driver | ||
5 | * | ||
6 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
7 | * Author(s): Arnd Bergmann <arndb@de.ibm.com> | ||
8 | * Cornelia Huck <cohuck@de.ibm.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2, or (at your option) | ||
13 | * any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/err.h> | ||
29 | |||
30 | #include <asm/ccwdev.h> | ||
31 | #include <asm/ccwgroup.h> | ||
32 | |||
33 | #include "cu3088.h" | ||
34 | |||
35 | const char *cu3088_type[] = { | ||
36 | "not a channel", | ||
37 | "CTC/A", | ||
38 | "ESCON channel", | ||
39 | "FICON channel", | ||
40 | "P390 LCS card", | ||
41 | "OSA LCS card", | ||
42 | "unknown channel type", | ||
43 | "unsupported channel type", | ||
44 | }; | ||
45 | |||
46 | /* static definitions */ | ||
47 | |||
48 | static struct ccw_device_id cu3088_ids[] = { | ||
49 | { CCW_DEVICE(0x3088, 0x08), .driver_info = channel_type_parallel }, | ||
50 | { CCW_DEVICE(0x3088, 0x1f), .driver_info = channel_type_escon }, | ||
51 | { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon }, | ||
52 | { CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 }, | ||
53 | { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 }, | ||
54 | { /* end of list */ } | ||
55 | }; | ||
56 | |||
57 | static struct ccw_driver cu3088_driver; | ||
58 | |||
59 | struct device *cu3088_root_dev; | ||
60 | |||
61 | static ssize_t | ||
62 | group_write(struct device_driver *drv, const char *buf, size_t count) | ||
63 | { | ||
64 | const char *start, *end; | ||
65 | char bus_ids[2][BUS_ID_SIZE], *argv[2]; | ||
66 | int i; | ||
67 | int ret; | ||
68 | struct ccwgroup_driver *cdrv; | ||
69 | |||
70 | cdrv = to_ccwgroupdrv(drv); | ||
71 | if (!cdrv) | ||
72 | return -EINVAL; | ||
73 | start = buf; | ||
74 | for (i=0; i<2; i++) { | ||
75 | static const char delim[] = {',', '\n'}; | ||
76 | int len; | ||
77 | |||
78 | if (!(end = strchr(start, delim[i]))) | ||
79 | return count; | ||
80 | len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1); | ||
81 | strlcpy (bus_ids[i], start, len); | ||
82 | argv[i] = bus_ids[i]; | ||
83 | start = end + 1; | ||
84 | } | ||
85 | |||
86 | ret = ccwgroup_create(cu3088_root_dev, cdrv->driver_id, | ||
87 | &cu3088_driver, 2, argv); | ||
88 | |||
89 | return (ret == 0) ? count : ret; | ||
90 | } | ||
91 | |||
92 | static DRIVER_ATTR(group, 0200, NULL, group_write); | ||
93 | |||
94 | /* Register-unregister for ctc&lcs */ | ||
95 | int | ||
96 | register_cu3088_discipline(struct ccwgroup_driver *dcp) | ||
97 | { | ||
98 | int rc; | ||
99 | |||
100 | if (!dcp) | ||
101 | return -EINVAL; | ||
102 | |||
103 | /* Register discipline.*/ | ||
104 | rc = ccwgroup_driver_register(dcp); | ||
105 | if (rc) | ||
106 | return rc; | ||
107 | |||
108 | rc = driver_create_file(&dcp->driver, &driver_attr_group); | ||
109 | if (rc) | ||
110 | ccwgroup_driver_unregister(dcp); | ||
111 | |||
112 | return rc; | ||
113 | |||
114 | } | ||
115 | |||
116 | void | ||
117 | unregister_cu3088_discipline(struct ccwgroup_driver *dcp) | ||
118 | { | ||
119 | if (!dcp) | ||
120 | return; | ||
121 | |||
122 | driver_remove_file(&dcp->driver, &driver_attr_group); | ||
123 | ccwgroup_driver_unregister(dcp); | ||
124 | } | ||
125 | |||
126 | static struct ccw_driver cu3088_driver = { | ||
127 | .owner = THIS_MODULE, | ||
128 | .ids = cu3088_ids, | ||
129 | .name = "cu3088", | ||
130 | .probe = ccwgroup_probe_ccwdev, | ||
131 | .remove = ccwgroup_remove_ccwdev, | ||
132 | }; | ||
133 | |||
134 | /* module setup */ | ||
135 | static int __init | ||
136 | cu3088_init (void) | ||
137 | { | ||
138 | int rc; | ||
139 | |||
140 | cu3088_root_dev = s390_root_dev_register("cu3088"); | ||
141 | if (IS_ERR(cu3088_root_dev)) | ||
142 | return PTR_ERR(cu3088_root_dev); | ||
143 | rc = ccw_driver_register(&cu3088_driver); | ||
144 | if (rc) | ||
145 | s390_root_dev_unregister(cu3088_root_dev); | ||
146 | |||
147 | return rc; | ||
148 | } | ||
149 | |||
150 | static void __exit | ||
151 | cu3088_exit (void) | ||
152 | { | ||
153 | ccw_driver_unregister(&cu3088_driver); | ||
154 | s390_root_dev_unregister(cu3088_root_dev); | ||
155 | } | ||
156 | |||
157 | MODULE_DEVICE_TABLE(ccw,cu3088_ids); | ||
158 | MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>"); | ||
159 | MODULE_LICENSE("GPL"); | ||
160 | |||
161 | module_init(cu3088_init); | ||
162 | module_exit(cu3088_exit); | ||
163 | |||
164 | EXPORT_SYMBOL_GPL(cu3088_type); | ||
165 | EXPORT_SYMBOL_GPL(register_cu3088_discipline); | ||
166 | EXPORT_SYMBOL_GPL(unregister_cu3088_discipline); | ||